From 5b09d892295b7f9eb428203b8018cae863cb6e99 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Mon, 2 Sep 2019 13:45:14 -0600 Subject: [PATCH 01/28] Try to pop vmin and vmax out of norm_kw --- proplot/wrappers.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/proplot/wrappers.py b/proplot/wrappers.py index e0ab555e7..22ea6398d 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -1768,6 +1768,8 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, labels_kw = labels_kw or {} colorbar_kw = colorbar_kw or {} panel_kw = panel_kw or {} + vmin = _notNone(vmin, norm_kw.pop('vmin', None)) + vmax = _notNone(vmax, norm_kw.pop('vmax', None)) # Parse args # Disable edgefix=True for certain keyword combos e.g. if user wants # white lines around their pcolor mesh. From a3ebbb12e75a2a110d8d40c20ff0a41b89addf7c Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Mon, 2 Sep 2019 16:48:45 -0600 Subject: [PATCH 02/28] Respect vmin and vmax as hard minimum/maximum --- proplot/wrappers.py | 100 +++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 48 deletions(-) diff --git a/proplot/wrappers.py b/proplot/wrappers.py index 22ea6398d..aa675c3b1 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -1672,11 +1672,13 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, levels are inferred using `~proplot.utils.edges`. This will override any `levels` input. vmin, vmax : float, optional - Used to determine level locations if `levels` is an integer and at - least one of `vmin` and `vmax` is provided. The levels will be - ``np.linspace(vmin, vmax, levels)``. If `vmin` was omitted but `vmax` - was provided, `vmin` is the data minimum. If `vmax` was omitted but - `vmin` was provided, `vmax` is the data maximum. + Used to determine level locations if `levels` is an integer. Actual + levels may not fall exactly on `vmin` and `vmax`, but the minimum + level will be no smaller than `vmin` and the maximum level will be + no larger than `vmax. + + If `vmin` or `vmax` is not provided, the minimum and maximum data + values are used. locator : locator-spec, optional The locator used to determine level locations if `levels` or `values` is an integer and `vmin` and `vmax` were not provided. Passed to the @@ -1859,54 +1861,56 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, # TODO: Add kernel density plot to hexbin! levels = _notNone(N, levels, rc['image.levels'], names=('N', 'levels')) if isinstance(levels, Number): + # Cannot infer counts a priori, so do nothing if name in ('hexbin',): - levels = None # cannot infer *counts*, so do nothing + levels = None + # Use the locator to determine levels + # Mostly copied from the hidden contour.ContourSet._autolev else: - # Set levels according to vmin and vmax + # Get the locator N = levels - if vmin is not None or vmax is not None: - vmin = _notNone(vmin, zmin) - vmax = _notNone(vmax, zmax) - levels = np.linspace(vmin, vmax, N) - # Use the locator to determine levels - # Mostly copied from the hidden contour.ContourSet._autolev + if locator is not None: + locator = axistools.Locator(locator, **locator_kw) + elif isinstance(norm, mcolors.LogNorm): + locator = mticker.LogLocator(**locator_kw) else: - # Get and apply the locator - if locator is not None: - locator = axistools.Locator(locator, **locator_kw) - elif isinstance(norm, mcolors.LogNorm): - locator = mticker.LogLocator(**locator_kw) - else: - locator_kw = {**locator_kw} - locator_kw.setdefault('symmetric', symmetric) - locator = mticker.MaxNLocator(N, min_n_ticks=1, **locator_kw) - try: - levels = locator.tick_values(zmin, zmax) - except RuntimeError: - levels = np.linspace(zmin, zmax, N) # TODO: orig used N+1 - # Trim excess levels the locator may have supplied. - if not locator_kw.get('symmetric', None): - under, = np.where(levels < zmin) - i0 = under[-1] if len(under) else 0 - over, = np.where(levels > zmax) + locator_kw = {**locator_kw} + locator_kw.setdefault('symmetric', symmetric) + locator = mticker.MaxNLocator(N, min_n_ticks=1, **locator_kw) + # Get locations + hardmin, hardmax = (vmin is not None), (vmax is not None) + vmin = _notNone(vmin, zmin) + vmax = _notNone(vmax, zmax) + try: + levels = locator.tick_values(vmin, vmax) + except RuntimeError: + levels = np.linspace(vmin, vmax, N) # TODO: orig used N+1 + # Trim excess levels the locator may have supplied + if not locator_kw.get('symmetric', None): + i0, i1 = 0, len(levels) # defaults + under, = np.where(levels < vmin) + if len(under): + i0 = under[-1] + if hardmin or extend in ('min', 'both'): + i0 += 1 # permit out-of-bounds data + over, = np.where(levels > vmax) + if len(over): i1 = over[0] + 1 if len(over) else len(levels) - if extend in ('min', 'both'): - i0 += 1 - if extend in ('max', 'both'): - i1 -= 1 - if i1 - i0 < 3: - i0, i1 = 0, len(levels) - levels = levels[i0:i1] - # Special consideration if not enough levels - nn = N//len(levels) # how many times more levels did we want than what we got? - if nn >= 2: - olevels = norm(levels) - nlevels = [] - for i in range(len(levels)-1): - l1, l2 = olevels[i], olevels[i+1] - nlevels.extend(np.linspace(l1, l2, nn+1)[:-1]) - nlevels.append(olevels[-1]) - levels = norm.inverse(nlevels) + if hardmax or extend in ('max', 'both'): + i1 -= 1 # permit out-of-bounds data + if i1 - i0 < 3: + i0, i1 = 0, len(levels) # revert + levels = levels[i0:i1] + # Special consideration if not enough levels + nn = N//len(levels) # how many times more levels did we want than what we got? + if nn >= 2: + olevels = norm(levels) + nlevels = [] + for i in range(len(levels)-1): + l1, l2 = olevels[i], olevels[i+1] + nlevels.extend(np.linspace(l1, l2, nn+1)[:-1]) + nlevels.append(olevels[-1]) + levels = norm.inverse(nlevels) # Norm settings # Generate BinNorm, and update child norm object with vmin and vmax from levels From bad8024405355a3062ddefadfb2c6fe152f00205 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Mon, 2 Sep 2019 20:50:35 -0600 Subject: [PATCH 03/28] Remove PanelAxes, and remove 'panels' args from subplots()! Colorbar and legend panels can now only be generated on-the-fly. --- proplot/.proplotrc | 14 +- proplot/axes.py | 657 ++++++++++++++------------------------------ proplot/rctools.py | 14 +- proplot/subplots.py | 487 +++++++++----------------------- proplot/wrappers.py | 31 ++- 5 files changed, 372 insertions(+), 831 deletions(-) diff --git a/proplot/.proplotrc b/proplot/.proplotrc index a0723ce05..d42e79aac 100644 --- a/proplot/.proplotrc +++ b/proplot/.proplotrc @@ -164,22 +164,22 @@ innerborders.linewidth: 0.6 rivers.color: k rivers.linewidth: 0.6 # Colorbar settings -colorbar.loc: 'lower right' +colorbar.loc: right colorbar.grid: False colorbar.frameon: True colorbar.framealpha: 0.8 -colorbar.extend: 0.15 -colorbar.extendinset: 1em -colorbar.length: 8em -colorbar.width: 1.2em colorbar.axespad: 0.5em +colorbar.extend: 1.3em +colorbar.extendinset: 1em +colorbar.length: 1 +colorbar.lengthinset: 8em +colorbar.width: 1.5em # 0.17 inches +colorbar.widthinset: 1.2em # Subplot properties # Use font relative units for everything because this is common way user # might want to increase figure resolution subplots.axwidth: 18em # 2 inches subplots.panelwidth: 4em # 0.45 inches -subplots.colorbarwidth: 1.5em # 0.17 inches -subplots.legendwidth: 1.5em # 0.25 inches subplots.pad: 0.5em subplots.axpad: 1em subplots.panelpad: 0.5em diff --git a/proplot/axes.py b/proplot/axes.py index 7b8c40050..6a170a951 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -59,7 +59,6 @@ 'BasemapAxes', 'CartesianAxes', 'CartopyAxes', - 'EmptyPanel', 'PanelAxes', 'PolarAxes', 'ProjectionAxes', ] @@ -72,6 +71,13 @@ } _loc_translate = { None:None, + 'l':'left', + 'r':'right', + 'b':'bottom', + 't':'top', + 'c':'center', + 'i':'best', + 'inset':'best', 0:'best', 1:'upper right', 2:'upper left', @@ -82,7 +88,6 @@ 7:'lower center', 8:'upper center', 9:'center', - 'b':'best', 'ur':'upper right', 'ul':'upper left', 'll':'lower left', @@ -91,7 +96,6 @@ 'cl':'center left', 'uc':'upper center', 'lc':'lower center', - 'c':'center', } # Helper function @@ -154,13 +158,15 @@ def __init__(self, *args, number=None, self._title_pad = rc.get('axes.titlepad') # so we can copy to top panel self._title_above_panel = True # TODO: add rc prop? # Children and related properties - self._bottompanel = EmptyPanel() - self._toppanel = EmptyPanel() - self._leftpanel = EmptyPanel() - self._rightpanel = EmptyPanel() + self._bpanels = [] + self._tpanels = [] + self._lpanels = [] + self._rpanels = [] self._tight_bbox = None # bounding boxes are saved self._zoom = None + self._panel_side = None self._panel_parent = None + self._panel_filled = False # True when panels "filled" with colorbar/legend self._inset_zoom = False self._inset_parent = None self._alty_child = None @@ -171,7 +177,6 @@ def __init__(self, *args, number=None, self._auto_legend = {} self._auto_colorbar_kw = {} # keyword args for auto colorbar() self._auto_legend_kw = {} - self._filled = False # True when panels "filled" with colorbar/legend # Axis sharing, new text attributes, custom formatting self._spanx = spanx # boolean toggles, whether we want to span axes labels self._spany = spany @@ -253,11 +258,12 @@ def _get_title_props(self, abc=False, loc=None): loc = iloc elif iloc is not None and loc != iloc: cache = False - loc = _loc_translate.get(loc, loc) - loc = _side_translate.get(loc, loc) # Above axes - if loc in ('left','right','center'): + loc = _loc_translate.get(loc, loc) + if loc in ('top','bottom'): + raise ValueError(f'Invalid title location {loc!r}.') + elif loc in ('left','right','center'): kw = props(cache) kw.pop('border', None) # no border for titles outside axes kw.pop('linewidth', None) @@ -265,7 +271,6 @@ def _get_title_props(self, abc=False, loc=None): obj = self.title else: obj = getattr(self, '_' + loc + '_title') - # Inside axes elif loc in self._titles_dict: kw = props(cache) @@ -294,25 +299,13 @@ def _get_title_props(self, abc=False, loc=None): return loc, obj, kw @staticmethod - def _inset_or_panel_loc(loc, **kwargs): - """Translates location string `loc`, returns this axes or a panel axes - and the translated location string. If it is a panel axes, returned - location is ``'fill'``. If the panel does not exist, it is drawn, - and extra keyword args are passed to `~Axes.panel`.""" - # Panel index - idx = 0 - if (np.iterable(loc) and not isinstance(loc, str) - and len(loc) == 2 and isinstance(loc[0], str)): - loc, idx = loc # e.g. ('r',2) - - # Try getting the panel, and translate location - if isinstance(loc, str): - loc = _side_translate.get(loc, loc) + def _loc_translate(loc, **kwargs): + """Translates location string `loc` into a standardized form.""" if loc is True: loc = None elif isinstance(loc, (str, Integral)): loc = _loc_translate.get(loc, loc) # may still be invalid - return ax, loc + return loc def _make_inset_locator(self, bounds, trans): """Helper function, copied from private matplotlib version.""" @@ -353,14 +346,16 @@ def _reassign_suplabel(self, side): # this is called on the main axes *or* on the relevant panel itself # TODO: Mixed figure panels with super labels? How does that work? s = side[0] - if isinstance(self, PanelAxes) and s == self._side[0]: - ax = self._parent + side = _side_translate[s] + if s == self._panel_side: + ax = self._panel_parent else: ax = self - idx = (0 if s in 'lt' else -1) - pax = getattr(ax, s + 'panel')[idx] - if not pax: + paxs = getattr(ax, '_' + s + 'panels') + if not paxs: return ax + idx = (0 if s in 'lt' else -1) + pax = paxs[idx] kw = {} obj = getattr(ax, '_' + s + 'label') for key in ('color', 'fontproperties'): # TODO: add to this? @@ -381,13 +376,14 @@ def _reassign_title(self): # called on the main axes *or* on the top panel itself. This is # critical for bounding box calcs; not always clear whether draw() and # get_tightbbox() are called on the main axes or panel first - if isinstance(self, PanelAxes) and self._side == 'top': - ax, tax = self._parent, self + if self._panel_side == 'top': + ax, taxs = self._panel_parent, [self] else: - ax, tax = self, self.toppanel[0] - if not tax or not ax._title_above_panel: + ax, taxs = self, self._tpanels + if not taxs or not ax._title_above_panel: tax = ax else: + tax = taxs[0] tax._title_pad = ax._title_pad for loc,obj in ax._titles_dict.items(): if not obj.get_text() or loc not in ('left','center','right'): @@ -409,7 +405,7 @@ def _reassign_title(self): pos = tax.xaxis.get_ticks_position() labs = tax.xaxis.get_ticklabels() if pos == 'default' or (pos == 'top' and not len(labs)) or ( - pos == 'unknown' and getattr(tax, '_side', None) == 'top' + pos == 'unknown' and tax._panel_side == 'top' and not len(labs) and tax.xaxis.get_visible()): pad = tax.xaxis.get_tick_padding() tax._set_title_offset_trans(self._title_pad + pad) @@ -418,15 +414,15 @@ def _share_short_axis(self, share, side, level): """When sharing main subplots, shares the short axes of their side panels.""" # TODO: Re-calculate share settings at draw time! - if isinstance(self, PanelAxes): + if self._panel_side: # not None return s = side[0] if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') - paxs1 = getattr(self, s + 'panel') # calling this means, share properties on this axes with input 'share' axes - paxs2 = getattr(share, s + 'panel') - if not all(pax and not pax._filled for pax in paxs1) or not all( - pax and not pax._filled for pax in paxs2): + paxs1 = getattr(self, '_' + s + 'panels') # calling this means, share properties on this axes with input 'share' axes + paxs2 = getattr(share, '_' + s + 'panels') + if (not all(not pax._panel_filled for pax in paxs1) + or not all(not pax._panel_filled for pax in paxs2)): return if len(paxs1) != len(paxs2): raise AttributeError('Sync error. Different number of stacked panels along axes on like column/row of figure.') @@ -438,13 +434,13 @@ def _share_long_axis(self, share, side, level): """When sharing main subplots, shares the long axes of their side panels, assuming long axis sharing is enabled for that panel.""" # TODO: Re-calculate share settings at draw time! - if isinstance(self, PanelAxes): + if self._panel_side: return s = side[0] if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') - paxs = getattr(self, s + 'panel') # calling this means, share properties on this axes with input 'share' axes - if not all(pax and not pax._filled and pax._share for pax in paxs): + paxs = getattr(self, '_' + s + 'panels') # calling this means, share properties on this axes with input 'share' axes + if not all(not pax._panel_filled and pax._panel_share for pax in paxs): return axis = 'x' if s in 'tb' else 'y' for pax in paxs: @@ -506,26 +502,26 @@ def _sharey_setup(self, sharey, level): def _share_panels_setup(self): """Sets up axis sharing between main subplots and panels.""" - share = lambda paxs: (paxs and all(pax._share for pax in paxs)) + share = lambda paxs: (paxs and all(pax._panel_share for pax in paxs)) # Top and bottom bottom = None - if share(self.bottompanel): - bottom = self.bottompanel[-1] - for iax in (self, *self.bottompanel[:-1]): + if share(self._bpanels): + bottom = self._bpanels[-1] + for iax in (self, *self._bpanels[:-1]): iax._sharex_setup(bottom, 3) # parent is *bottom-most* panel - if share(self.toppanel): + if share(self._tpanels): bottom = bottom or self - for iax in self.toppanel: + for iax in self._tpanels: iax._sharex_setup(bottom, 3) # Left and right left = None - if share(self.leftpanel): - left = self.leftpanel[0] - for iax in (*self.leftpanel[1:], self): + if share(self._lpanels): + left = self._lpanels[0] + for iax in (*self._lpanels[1:], self): iax._sharey_setup(left, 3) # parent is *bottom-most* panel - if share(self.rightpanel): + if share(self._rpanels): left = left or self - for iax in self.rightpanel: + for iax in self._rpanels: iax._sharey_setup(left, 3) def _update_title(self, obj, **kwargs): @@ -731,7 +727,7 @@ def format(self, *, title=None, top=None, # A-b-c labels titles_dict = self._titles_dict - if not isinstance(self, PanelAxes): + if not self._panel_side: # Location and text abcformat = rc['abc.format'] # changed, or running format for first time? if abcformat and self.number is not None: @@ -931,79 +927,91 @@ def colorbar(self, *args, loc=None, pad=None, are interpreted by `~proplot.utils.units`. Defaults to ``rc['colorbar.pad']``. length : float or str, optional - The colorbar length. If float, units are inches. If string, - units are interpreted by `~proplot.utils.units`. Defaults to - ``rc['colorbar.length']``. + The colorbar length. For outer colorbars, units are relative to + the axes width or height. For inset colorbars, if float, units are + inches; if string, units are interpreted by `~proplot.utils.units`. + Defaults to ``rc['colorbar.length']``. width : float or str, optional - The colorbar width. If float, units are inches. If string, + The colorbar width. If float, units are inches. If string, units are interpreted by `~proplot.utils.units`. Defaults to ``rc['colorbar.width']`` for inset colorbars, - ``rc['subplots.cbarwidth']`` for panel colorbars. + ``rc['subplots.cbarwidth']`` for outer colorbars. frame, frameon : bool, optional - Whether to draw a frame behind the inset colorbar, just like - `~matplotlib.axes.Axes.legend`. Defaults to ``rc['colorbar.frameon']``. + Whether to draw a frame around inset colorbars, just like + `~matplotlib.axes.Axes.legend`. + Defaults to ``rc['colorbar.frameon']``. alpha, linewidth, edgecolor, facecolor : optional - Transparency, edge width, edge color, and face color for the frame. - Defaults to ``rc['colorbar.framealpha']``, ``rc['axes.linewidth']``, - ``rc['axes.edgecolor']``, and ``rc['axes.facecolor']``. + Transparency, edge width, edge color, and face color for the frame + around the inset colorbar. Defaults to + ``rc['colorbar.framealpha']``, ``rc['axes.linewidth']``, + ``rc['axes.edgecolor']``, and ``rc['axes.facecolor']``, + respectively. width : float or str, optional The width of the colorbar. If float, units are inches. If string, units are interpreted by `~proplot.utils.units`. Defaults to ``rc['colorbar.width']`` for inset colorbars and - ``rc['subplots.colorbarwidth']`` for colorbars outside the axes. + ``rc['subplots.colorbarwidth']`` for outer colorbars. space : float or str, optional - The space between the colorbar and the main axes. Ignored for - non-inset colorbars. If float, units are inches. If string, + The space between the colorbar and the main axes for outer + colorbars. If float, units are inches. If string, units are interpreted by `~proplot.utils.units`. By default, this - is adjusted automatically in the "tight layout" calculation. + is adjusted automatically in the "tight layout" calculation, + or is ``rc['subplots.panelspace']`` if "tight layout" is turned + off. **kwargs Passed to `~proplot.wrappers.colorbar_wrapper`. """ # TODO: add option to pad inset away from axes edge! kwargs.update({'edgecolor':edgecolor, 'linewidth':linewidth}) loc = _notNone(loc, rc['colorbar.loc']) - loc = self._inset_or_panel_loc(loc, **panel_kw) + loc = self._loc_translate(loc) + if loc == 'best': # a white lie + loc = 'lower right' if not isinstance(loc, str): # e.g. 2-tuple or ndarray raise ValueError(f'Invalid colorbar location {loc!r}.') - # Filled colorbar + # Generate panel if loc in ('left','right','top','bottom'): - # Generate the panel - ax = self.panel_axes(loc, width=width, space=space) + ax = self.panel_axes(loc, width=width, space=space, mode='colorbar') + return ax.colorbar(loc='_fill', *args, **kwargs) + # Filled colorbar + if loc == '_fill': # Hide content and resize panel # NOTE: Do not run self.clear in case we want title above this - for s in ax.spines.values(): + for s in self.spines.values(): s.set_visible(False) - ax.xaxis.set_visible(False) - ax.yaxis.set_visible(False) - ax.patch.set_alpha(0) - ax._filled = True - + self.xaxis.set_visible(False) + self.yaxis.set_visible(False) + self.patch.set_alpha(0) + self._panel_filled = True # Draw colorbar with arbitrary length relative to full length of panel - subspec = ax.get_subplotspec() - if length is not None and length != 1: - if length <= 0 or length >= 1: - raise ValueError(f'Panel colorbar length must be between 0 and 1, got length={length!r}.') - if loc in ('bottom','top'): - gridspec = mgridspec.GridSpecFromSubplotSpec( - nrows=1, ncols=3, wspace=0, - subplot_spec=subspec, - width_ratios=((1-length)/2, length, (1-length)/2), - ) - subspec = gridspec[1] - else: - gridspec = mgridspec.GridSpecFromSubplotSpec( - nrows=3, ncols=1, hspace=0, - subplot_spec=subspec, - height_ratios=((1-length)/2, length, (1-length)/2), - ) - subspec = gridspec[1] - - # Get properties - with ax.figure._unlock(): - ax = ax.figure.add_subplot(subspec, projection=None) - if loc in ('bottom','top'): + side = self._panel_side + length = _notNone(length, rc['colorbar.length']) + subplotspec = self.get_subplotspec() + if length <= 0 or length > 1: + raise ValueError(f'Panel colorbar length must satisfy 0 < length <= 1, got length={length!r}.') + if side in ('bottom','top'): + gridspec = mgridspec.GridSpecFromSubplotSpec( + nrows=1, ncols=3, wspace=0, + subplot_spec=subplotspec, + width_ratios=((1-length)/2, length, (1-length)/2), + ) + subplotspec = gridspec[1] + else: + gridspec = mgridspec.GridSpecFromSubplotSpec( + nrows=3, ncols=1, hspace=0, + subplot_spec=subplotspec, + height_ratios=((1-length)/2, length, (1-length)/2), + ) + subplotspec = gridspec[1] + with self.figure._unlock(): + ax = self.figure.add_subplot(subplotspec, projection=None) + if ax is self: + raise ValueError(f'Uh oh.') + self.add_child_axes(ax) + # Location + if side in ('bottom','top'): outside, inside = 'bottom', 'top' if side == 'top': outside, inside = inside, outside @@ -1015,16 +1023,13 @@ def colorbar(self, *args, loc=None, pad=None, outside, inside = inside, outside ticklocation = outside orientation = 'vertical' - - # For filled axes, call wrapper method directly - ax.add_child_axes(ax) + # Keyword args and add as child axes orient = kwargs.get('orientation', None) if orient is not None and orient != orientation: warnings.warn(f'Overriding input orientation={orient!r}.') ticklocation = kwargs.pop('tickloc', None) or ticklocation ticklocation = kwargs.pop('ticklocation', None) or ticklocation kwargs.update({'orientation':orientation, 'ticklocation':ticklocation}) - return wrappers.colorbar_wrapper(ax, *args, **kwargs) # Inset colorbar else: @@ -1032,29 +1037,17 @@ def colorbar(self, *args, loc=None, pad=None, cbwidth, cblength = width, length width, height = self.get_size_inches() extend = units(_notNone(kwargs.get('extendsize',None), rc['colorbar.extendinset'])) - cbwidth = units(_notNone(cbwidth, rc['colorbar.width']))/height - cblength = units(_notNone(cblength, rc['colorbar.length']))/width + cbwidth = units(_notNone(cbwidth, rc['colorbar.widthinset']))/height + cblength = units(_notNone(cblength, rc['colorbar.lengthinset']))/width pad = units(_notNone(pad, rc['colorbar.axespad'])) xpad, ypad = pad/width, pad/height - kwargs.setdefault('extendsize', extend) - - # Tick location handling - tickloc = kwargs.pop('tickloc', None) - ticklocation = kwargs.pop('ticklocation', None) - if any(loc is not None and loc!='bottom' - for loc in (tickloc,ticklocation)): - warnings.warn(f'Inset colorbars can only have ticks on the bottom.') - kwargs['ticklocation'] = 'bottom' - - # Space for labels + # Get location in axes-relative coordinates + # Bounds are x0, y0, width, height in axes-relative coordinate to start if kwargs.get('label', ''): xspace = 2.4*rc['font.size']/72 + rc['xtick.major.size']/72 else: xspace = 1.2*rc['font.size']/72 + rc['xtick.major.size']/72 - xspace /= height - - # Get location in axes-relative coordinates - # Bounds are x0, y0, width, height in axes-relative coordinate to start + xspace /= height # space for labels if loc == 'upper right': bounds = (1 - xpad - cblength, 1 - ypad - cbwidth) fbounds = (1 - 2*xpad - cblength, 1 - 2*ypad - cbwidth - xspace) @@ -1071,42 +1064,49 @@ def colorbar(self, *args, loc=None, pad=None, raise ValueError(f'Invalid colorbar location {loc!r}.') bounds = (bounds[0], bounds[1], cblength, cbwidth) fbounds = (fbounds[0], fbounds[1], 2*xpad + cblength, 2*ypad + cbwidth + xspace) - - # Make axes - locator = self._make_inset_locator(bounds, self.transAxes) - bbox = locator(None, None) - ax = maxes.Axes(self.figure, bbox.bounds, zorder=5) - ax.set_axes_locator(locator) - self.add_child_axes(ax) - - # Make colorbar - # WARNING: Inset colorbars are tiny! So use smart default locator - kwargs.setdefault('maxn', 5) - cb = wrappers.colorbar_wrapper(ax, *args, **kwargs) - # Make frame # NOTE: We do not allow shadow effects or fancy edges effect. # Also keep zorder same as with legend. frameon = _notNone(frame, frameon, rc['colorbar.frameon'], names=('frame','frameon')) if frameon: - # Make object + # Make patch object xmin, ymin, width, height = fbounds patch = mpatches.Rectangle((xmin,ymin), width, height, - snap=True, zorder=4.5, transform=self.transAxes) # fontsize defined in if statement - # Properties + snap=True, zorder=4.5, transform=self.transAxes) + # Update patch props alpha = _notNone(alpha, rc['colorbar.framealpha']) linewidth = _notNone(linewidth, rc['axes.linewidth']) edgecolor = _notNone(edgecolor, rc['axes.edgecolor']) facecolor = _notNone(facecolor, rc['axes.facecolor']) - patch.update({'alpha':alpha, 'linewidth':linewidth, 'edgecolor':edgecolor, 'facecolor':facecolor}) + patch.update({'alpha':alpha, 'linewidth':linewidth, + 'edgecolor':edgecolor, 'facecolor':facecolor}) self.add_artist(patch) - return cb + # Make axes + locator = self._make_inset_locator(bounds, self.transAxes) + bbox = locator(None, None) + ax = maxes.Axes(self.figure, bbox.bounds, zorder=5) + ax.set_axes_locator(locator) + self.add_child_axes(ax) + # Default keyword args + orient = kwargs.pop('orientation', None) + if orient is not None and orient != 'horizontal': + warnings.warn(f'Orientation for inset colorbars must be horizontal, ignoring orient={orient!r}.') + ticklocation = kwargs.pop('tickloc', None) + ticklocation = kwargs.pop('ticklocation', None) or ticklocation + if any(loc is not None and ticklocation != 'bottom'): + warnings.warn(f'Inset colorbars can only have ticks on the bottom.') + kwargs.update({'orientation':'horizontal', 'ticklocation':'bottom'}) + kwargs.setdefault('maxn', 5) + kwargs.setdefault('extendsize', extend) - def legend(self, *args, loc=None, width=None, panel_kw=None, **kwargs): + # Generate colorbar + return wrappers.colorbar_wrapper(ax, *args, **kwargs) + + def legend(self, *args, loc=None, width=None, space=None, **kwargs): """ - Adds an *inset* legend, or calls the `PanelAxes.legend` method - for the panel location at `loc`. See `~matplotlib.axes.Axes.legend` - and `~proplot.wrappers.legend_wrapper` for details. + Adds an *inset* legend or *outer* legend along the edge of the axes. + See `~matplotlib.axes.Axes.legend` and + `~proplot.wrappers.legend_wrapper` for details. Parameters ---------- @@ -1115,14 +1115,14 @@ def legend(self, *args, loc=None, width=None, panel_kw=None, **kwargs): are valid. Note that if a panel does not exist, it will be generated on-the-fly. - ================== =================================== + ================== ======================================= Location Valid keys - ================== =================================== + ================== ======================================= left panel ``'l'``, ``'left'`` right panel ``'r'``, ``'right'`` bottom panel ``'b'``, ``'bottom'`` top panel ``'t'``, ``'top'`` - "best" possible ``0``, ``'best'``, ``'b'`` + "best" possible ``0``, ``'best'``, ``'inset'``, ``'i'`` upper right inset ``1``, ``'upper right'``, ``'ur'`` upper left inset ``2``, ``'upper left'``, ``'ul'`` lower left inset ``3``, ``'lower left'``, ``'ll'`` @@ -1132,24 +1132,59 @@ def legend(self, *args, loc=None, width=None, panel_kw=None, **kwargs): lower center inset ``7``, ``'lower center'``, ``'lc'`` upper center inset ``8``, ``'upper center'``, ``'uc'`` center inset ``9``, ``'center'``, ``'c'`` - ================== =================================== + ================== ======================================= width : float or str, optional - The panel width, if it does not already exist. + The space allocated for the outer legends. This does nothing + if "tight layout" is turned on. If float, units are inches. If + string, units are interpreted by `~proplot.utils.units`. + space : float or str, optional + The space between the axes and the legend for outer legends. If float, units are inches. If string, units are interpreted by - `~proplot.utils.units`. Defaults to ``rc['subplots.legwidth']``. + `~proplot.utils.units`. + Other parameters + ---------------- *args, **kwargs Passed to `~matplotlib.axes.Axes.legend`. """ - panel_kw = panel_kw or {} - if width is not None: - panel_kw.setdefault('width', width) - loc = self._inset_or_panel_loc(loc, **panel_kw) - # TODO: FIXME + loc = self._loc_translate(loc, width=width, space=space) + if isinstance(loc, np.ndarray): + loc = loc.tolist() + + # Generate panel if loc in ('left','right','top','bottom'): - return self.legend(*args, loc=loc, **kwargs) - return wrappers.legend_wrapper(ax, *args, loc=loc, **kwargs) + ax = self.panel_axes(loc, width=width, space=space, mode='legend') + return ax.legend(*args, loc='_fill', **kwargs) + + # Fill + if loc == '_fill': + # Hide content + for s in self.spines.values(): + s.set_visible(False) + self.xaxis.set_visible(False) + self.yaxis.set_visible(False) + self.patch.set_alpha(0) + self._panel_filled = True + # Try to make handles and stuff flush against the axes edge + kwargs.setdefault('borderaxespad', 0) + if not kwargs.get('frameon', rc['legend.frameon']): + kwargs.setdefault('borderpad', 0) + # Apply legend location + side = self._panel_side + if side == 'bottom': + loc = 'upper center' + elif side == 'right': + loc = 'center left' + elif side == 'left': + loc = 'center right' + elif side == 'top': + loc = 'lower center' + else: + raise ValueError(f'Invalid panel side {side!r}.') + + # Draw legend + return wrappers.legend_wrapper(self, *args, loc=loc, **kwargs) def draw(self, renderer=None, *args, **kwargs): """Adds post-processing steps before axes is drawn.""" @@ -1299,46 +1334,29 @@ def indicate_inset_zoom(self, alpha=None, linewidth=None, color=None, edgecolor= def panel_axes(self, side, **kwargs): """ - Adds a single `~proplot.axes.PanelAxes` or a stack of panels, and - returns an `~proplot.subplots.axes_grid` of the panel stack. Also - saves the panel stack as the `~Axes.leftpanel`, - `~Axes.rightpanel`, `~Axes.bottompanel`, or - `~Axes.toppanel` attribute, with respective shorthands - `~Axes.lpanel`, `~Axes.rpanel`, `~Axes.bpanel`, and - `~Axes.tpanel`. - - Note that all `~Axes.panel_axes` keyword args can be side-specific, - e.g. `lwidth` instead of `width`. This is for compatibility with the - `~proplot.subplots.subplots` API. + Returns a panel drawn along the edge of an axes. Parameters ---------- ax : `~proplot.axes.Axes` The axes for which we are drawing a panel. - width, [lrbt]width : float or str or list thereof, optional - The panel width. If float or str, widths are same for all panels - in the stack. If list thereof, specifies widths of each panel in - the stack. If float, units are inches. If string, units are + width : float or str or list thereof, optional + The panel width. If float, units are inches. If string, units are interpreted by `~proplot.utils.units`. - space, [lrbt]space : float or str or list thereof, optional - Empty space between the main subplot and the panel. If float, + space : float or str or list thereof, optional + Empty space between the main subplot and the panel. If float, units are inches. If string, units are interpreted by `~proplot.utils.units`. - share, [lrbt]space : bool, optional + share : bool, optional Whether to enable axis sharing between the *x* and *y* axes of the main subplot and the panel long axes for each panel in the stack. - stack, [lrbt]stack : int, optional - The number of optional "stacked" panels on the left, right, bottom, - and top sides, respectively. Defaults to ``1``. - sep, [lrbt]sep : float, str, or list thereof, optional - The separation between stacked panels. If float, units are inches. - If string, units are interpreted by `~proplot.utils.units`. Ignored - if the respecitve `stack` keyword arg is None. + Sharing between the panel short axis and other panel short axes + is determined by figure-wide `sharex` and `sharey` settings. Returns ------- - `~proplot.subplots.axes_grid` of `~proplot.axes.PanelAxes` - The panel axes or stack of panel axes. + `~proplot.axes.Axes` + The panel axes. """ return self.figure._add_axes_panel(side, self, **kwargs) @@ -1354,39 +1372,13 @@ def number(self): `~proplot.subplots.subplots`.""" return self._number - @property - def leftpanel(self): - """An `~proplot.subplots.axes_grid` of the left panel stack.""" - return self._leftpanel - @property - def rightpanel(self): - """An `~proplot.subplots.axes_grid` of the right panel stack.""" - return self._rightpanel - @property - def toppanel(self): - """An `~proplot.subplots.axes_grid` of the top panel stack.""" - return self._toppanel - @property - def bottompanel(self): - """An `~proplot.subplots.axes_grid` of the bottom panel stack.""" - return self._bottompanel - - lpanel = leftpanel - """Alias for `~Axes.leftpanel`.""" - rpanel = rightpanel - """Alias for `~Axes.rightpanel`.""" - tpanel = toppanel - """Alias for `~Axes.toppanel`.""" - bpanel = bottompanel - """Alias for `~Axes.bottompanel`.""" - def _iter_panels(self, sides='lrbt'): """Iterates over axes and child panel axes.""" axs = [self] if self.get_visible() else [] if not ({*sides} <= {*'lrbt'}): raise ValueError(f'Invalid sides {sides!r}.') for s in sides: - for ax in getattr(self, s + 'panel'): + for ax in getattr(self, '_' + s + 'panels'): if not ax or not ax.get_visible(): continue axs.append(ax) @@ -1434,7 +1426,7 @@ class CartesianAxes(Axes): See also -------- - `~proplot.subplots.subplots`, `Axes`, `PanelAxes` + `~proplot.subplots.subplots`, `Axes` """ name = 'cartesian' """The registered projection name.""" @@ -2262,245 +2254,15 @@ def get_tightbbox(self, renderer, *args, **kwargs): def twinx(self): """Mimics matplotlib's `~matplotlib.axes.Axes.twinx` and intelligently handles axis ticks, gridlines, axis tick labels, axis labels, and axis - sharing. Returns an `CartesianAxes` instance.""" + sharing. Returns a `CartesianAxes` instance.""" return self.alty() def twiny(self): """Mimics matplotlib's `~matplotlib.axes.Axes.twiny` and intelligently handles axis ticks, gridlines, axis tick labels, axis labels, and axis - sharing. Returns an `CartesianAxes` instance.""" + sharing. Returns a `CartesianAxes` instance.""" return self.altx() -class EmptyPanel(object): - """Replaces `PanelAxes` when the axes or figure panel does not exist. - This gives a nicer error message than if we had just ``None``, and - permits indexing to mimick the behavior of a singleton - `~proplot.subplots.axes_grid`.""" - def __bool__(self): - """Returns False. Provides shorthand way to check whether panel - attribute is specifically EmptyPanel.""" - return False # it's empty, so this is 'falsey' - - def __len__(self): - """Returns 1. This allows us to treat `EmptyPanel` like an - `~proplot.subplots.axes_grid` of stacked panels.""" - return 1 - - def __getitem__(self, key): - """Returns itself. This allows us to treat `EmptyPanel` like an - `~proplot.subplots.axes_grid` of stacked panels.""" - # See: https://stackoverflow.com/a/26611639/4970632 - if not isinstance(key, tuple): - key = (key,) - if any(ikey not in (0,-1,slice(None)) for ikey in key): - raise IndexError - return self - - def __getattr__(self, attr, *args): - """Raises AttributeError.""" - # NOTE: `__getattr__` is invoked only when `__getattribute__` fails, i.e. - # when the user requests anything that isn't a builtin method. - raise AttributeError('Panel does not exist.') - -class PanelAxes(CartesianAxes): - """`~proplot.axes.CartesianAxes` subclass, adds `~PanelAxes.legend` and - `~PanelAxes.colorbar` methods that "fill" the entire axes.""" - # Notes: - # See `this post `_ - # and `this example `_. - name = 'panel' - """The registered projection name.""" - def __init__(self, *args, - parent=None, side=None, share=False, gridspec=None, - **kwargs): - """ - Parameters - ---------- - side : {'left', 'right', 'bottom', 'top'} - The side on which the panel is drawn. - parent : `~matplotlib.axes.Axes`, optional - The "parent" of the panel. Not relevant for "outer panel" axes. - share : bool, optional - Whether to share panel *x* and *y* axes with "parent" axes. - Irrelevant for figure panels, and defaults to ``False``. - gridspec : optional - For stacks of panel axes, this is the - `~proplot.subplots.FlexibleGridSpecFromSubplotSpec` used to - specify the panel stack location. - - Other parameters - ---------------- - *args, **kwargs - Passed to the `CartesianAxes` initializer. - - See also - -------- - `~proplot.subplots.subplots`, - `~proplot.subplots.Figure.add_subplot_and_panels` - """ - # Misc props - # WARNING: Need to set flush property before calling super init! - if side not in ('left', 'right', 'bottom', 'top'): - raise ValueError(f'Invalid panel side {side!r}.') - self._share = share - self._side = side - self._parent = parent # used when declaring parent - # Initialize - super().__init__(*args, **kwargs) - axis = (self.yaxis if side in ('left','right') else self.xaxis) - getattr(axis, 'tick_' + side)() # sets tick and tick label positions intelligently - axis.set_label_position(side) - - def legend(self, *args, fill=True, width=None, **kwargs): - """" - Fills the panel with a legend by adding a centered legend and - rendering the axes spines and patch invisible, or draws a normal - inset legend. - - Parameters - ---------- - fill : bool, optional - Whether to fill the panel with a legend or draw a normal - inset legend. Defaults to ``True``. - width : float or str, optional - The width of the panel in physical units. If float, units are - inches. If string, units are interpreted by `~proplot.utils.units`. - Note that the panel width does not matter unless you have turned - off automatic tight layout -- space for the legend is allocated - automatically. - *args, **kwargs - Passed to `~proplot.wrappers.legend_wrapper`. - """ - # Regular inset legend - if not fill: - return super().legend(*args, **kwargs) - # Hide content - for s in self.spines.values(): - s.set_visible(False) - self.xaxis.set_visible(False) - self.yaxis.set_visible(False) - self.patch.set_alpha(0) - self._filled = True - - # Allocate invisible axes for drawing legend; by default try to - # make handles and stuff flush against the axes edge - kwdefault = {'borderaxespad': 0} - if not kwargs.get('frameon', rc['legend.frameon']): - kwdefault['borderpad'] = 0 - kwdefault.update(kwargs) - kwargs = kwdefault - - # Apply legend location - side = self._side - if 'loc' in kwargs: - warnings.warn(f'Overriding input legend location loc={kwargs["loc"]!r}.') - if side == 'bottom': - loc = 'upper center' - elif side == 'right': - loc = 'center left' - elif side == 'left': - loc = 'center right' - elif side == 'top': - loc = 'lower center' - else: - raise ValueError(f'Invalid panel side {loc!r}.') - kwargs['loc'] = loc - leg = wrappers.legend_wrapper(self, *args, **kwargs) - - # Resize panel and return - # TODO: Make panel size dependent on legend width, and remove - # legwidth from .proplotrc - self.figure._resize_panel(self, width, 'legend') - return leg - - def colorbar(self, *args, fill=True, width=None, length=None, **kwargs): - """" - Fills the panel with a colorbar by calling - `~matplotlib.figure.Figure.colorbar` with ``cax=self``, or draws an - inset colorbar. - - Parameters - ---------- - fill : bool, optional - Whether to fill the panel with a colorbar or draw an inset - colorbar. Defaults to ``True``. - length : float, optional - When ``fill=True``, this is the fractional extent of the panel - long axis extended by the colorbar. For example, with - ``length=0.5``, the colorbar extends over the middle 50% - of the panel. When ``fill=False``, this is the inset colorbar - length in physical units, passed to `~BaseAxes.colorbar`. - width : float or str, optional - The width of the panel colorbar or inset colorbar in physical - units. If float, units are inches. If string, units are interpreted - by `~proplot.utils.units`. - *args, **kwargs - Passed to `~proplot.wrappers.colorbar_wrapper` when ``fill=True``, - or `~BaseAxes.colorbar` when ``fill=False``. - """ - # Inset 'legend-style' colorbar - if not fill: - return super().colorbar(*args, width=width, length=length, **kwargs) - # Hide content and resize panel - # NOTE: Do not run self.clear in case we want title above this - for s in self.spines.values(): - s.set_visible(False) - self.xaxis.set_visible(False) - self.yaxis.set_visible(False) - self.patch.set_alpha(0) - self._filled = True - - # Draw colorbar with arbitrary length relative to full length of panel - side = self._side - subspec = self.get_subplotspec() - if length is not None and length != 1: - if length <= 0 or length >= 1: - raise ValueError(f'Panel colorbar length must be between 0 and 1, got length={length!r}.') - if side in ('bottom','top'): - gridspec = mgridspec.GridSpecFromSubplotSpec( - nrows=1, ncols=3, wspace=0, - subplot_spec=subspec, - width_ratios=((1-length)/2, length, (1-length)/2), - ) - subspec = gridspec[1] - elif side in ('left','right'): - gridspec = mgridspec.GridSpecFromSubplotSpec( - nrows=3, ncols=1, hspace=0, - subplot_spec=subspec, - height_ratios=((1-length)/2, length, (1-length)/2), - ) - subspec = gridspec[1] - - # Get properties - with self.figure._unlock(): - ax = self.figure.add_subplot(subspec, projection=None) - if side in ('bottom','top'): - outside, inside = 'bottom', 'top' - if side == 'top': - outside, inside = inside, outside - ticklocation = outside - orientation = 'horizontal' - elif side in ('left','right'): - outside, inside = 'left', 'right' - if side == 'right': - outside, inside = inside, outside - ticklocation = outside - orientation = 'vertical' - - # For filled axes, call wrapper method directly - self.add_child_axes(ax) - orient = kwargs.get('orientation', None) - if orient is not None and orient != orientation: - warnings.warn(f'Overriding input orientation={orient!r}.') - ticklocation = kwargs.pop('tickloc', None) or ticklocation - ticklocation = kwargs.pop('ticklocation', None) or ticklocation - kwargs.update({'orientation':orientation, 'ticklocation':ticklocation}) - cbar = wrappers.colorbar_wrapper(ax, *args, **kwargs) - - # Resize panel and return - self.figure._resize_panel(self, width, 'colorbar') - return cbar - class ProjectionAxes(Axes): """Intermediate class, shared by `CartopyAxes` and `BasemapAxes`. Disables methods that are inappropriate for map @@ -3465,7 +3227,6 @@ def format(self, *, patch_kw=None, **kwargs): # Register the projections mproj.register_projection(Axes) -mproj.register_projection(PanelAxes) mproj.register_projection(PolarAxes) mproj.register_projection(CartesianAxes) mproj.register_projection(BasemapAxes) diff --git a/proplot/rctools.py b/proplot/rctools.py index 60001909a..ff9fa96fc 100644 --- a/proplot/rctools.py +++ b/proplot/rctools.py @@ -161,8 +161,10 @@ ``colorbar.grid`` Boolean, indicates whether to draw borders between each level of the colorbar. ``colorbar.frameon`` Boolean, indicates whether to draw a frame behind inset colorbars. ``colorbar.framealpha`` Opacity for inset colorbar frames. -``colorbar.length`` Length of inset colorbars. -``colorbar.width`` Width of inset colorbars. +``colorbar.length`` Length of outer colorbars. +``colorbar.lengthinset`` Length of inset colorbars. +``colorbar.width`` Width of outer colorbars. +``colorbar.widthinset`` Width of inset colorbars. ``colorbar.axespad`` Padding between axes edge and inset colorbars. ``colorbar.extend`` Length of rectangular or triangular "extensions" for panel colorbars. ``colorbar.extendinset`` Length of rectangular or triangular "extensions" for inset colorbars. @@ -177,8 +179,6 @@ ========================== ================================================================== ``subplots.axwidth`` Default width of each axes. ``subplots.panelwidth`` Width of side panels. -``subplots.colorbarwidth`` Width of "colorbar" panels. -``subplots.legendwidth`` Width of "legend" panels. ``subplots.pad`` Padding around figure edge. ``subplots.axpad`` Padding between adjacent subplots. ``subplots.panelpad`` Padding between subplots and panels, and between stacked panels. @@ -292,9 +292,11 @@ 'geogrid.labels', 'geogrid.alpha', 'geogrid.color', 'geogrid.labelsize', 'geogrid.linewidth', 'geogrid.linestyle', 'geogrid.latmax', 'geogrid.lonstep', 'geogrid.latstep', 'tick.labelweight', 'tick.labelcolor', 'tick.labelsize', 'subplots.pad', 'subplots.axpad', 'subplots.panelpad', - 'subplots.legendwidth', 'subplots.colorbarwidth', 'subplots.ylabspace', 'subplots.xlabspace', 'subplots.innerspace', 'subplots.titlespace', + 'subplots.ylabspace', 'subplots.xlabspace', 'subplots.innerspace', 'subplots.titlespace', 'subplots.axwidth', 'subplots.panelwidth', 'subplots.panelspace', - 'colorbar.grid', 'colorbar.frameon', 'colorbar.framealpha', 'colorbar.length', 'colorbar.width', 'colorbar.loc', 'colorbar.extend', 'colorbar.extendinset', 'colorbar.axespad', + 'colorbar.grid', 'colorbar.frameon', 'colorbar.framealpha', + 'colorbar.loc', 'colorbar.length', 'colorbar.width', 'colorbar.lengthinset', 'colorbar.widthinset', + 'colorbar.extend', 'colorbar.extendinset', 'colorbar.axespad', } # Used by Axes.format, allows user to pass rc settings as keyword args, # way less verbose. For example, landcolor='b' vs. rc_kw={'land.color':'b'}. diff --git a/proplot/subplots.py b/proplot/subplots.py index c16e87b13..30e695665 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -35,7 +35,6 @@ # NOTE: Importing backend causes issues with sphinx, and anyway not sure it's # always included, so make it optional import os -import re import numpy as np import functools import warnings @@ -43,7 +42,6 @@ import matplotlib.figure as mfigure import matplotlib.transforms as mtransforms import matplotlib.gridspec as mgridspec -import matplotlib.axes as maxes try: import matplotlib.backends.backend_macosx as mbackend except ImportError: @@ -212,7 +210,7 @@ def null_iterator(*args, **kwargs): return None return null_iterator # Panels - if all(isinstance(_, (axes_grid, axes.Axes, axes.EmptyPanel)) + if all(isinstance(_, (axes_grid, axes.Axes)) for _ in attrs): return axes_grid(attrs) # Objects @@ -472,6 +470,30 @@ def update(self, **kwargs): #-----------------------------------------------------------------------------# # Helper funcs #-----------------------------------------------------------------------------# +def _panels_kwargs(side, + share=None, width=None, space=None, + mode='panel', figure=False): + """Converts global keywords like `space` and `width` to side-local + keywords like `lspace` and `lwidth`, and applies default settings.""" + # Return values + s = side[0] + if s not in 'lrbt': + raise ValueError(f'Invalid panel spec {side!r}.') + space_orig = units(space) + if mode == 'panel': + default = rc['subplots.panelwidth'] + elif mode == 'colorbar': + default = rc['colorbar.width'] + else: + default = '1em' + share = _notNone(share, (mode == 'panel')) + width = units(_notNone(width, default)) + space = _notNone(space, units(rc['subplots.' + ('panel' if share + and not figure + else 'xlab' if s == 'b' else 'ylab' if s == 'l' + else 'inner' if figure else 'panel') + 'space'])) + return share, width, space, space_orig + def _subplots_geometry(**kwargs): """Saves arguments passed to `subplots`, calculates gridspec settings and figure size necessary for requested geometry, and returns keyword args @@ -610,66 +632,6 @@ def _subplots_geometry(**kwargs): return (width, height), gridspec_kw, kwargs -def _panels_kwargs(side, kwargs, figure=False, mode='panel'): - """Converts global keywords like `space` and `width` to side-local - keywords like `lspace` and `lwidth`, and applies default settings.""" - # Checks - # NOTE: The 'stack' keyword arg is now invalid, to add stacked panels - # simply call panel axes more than once or add colorbar more than once! - s = side[0] - if s not in 'lrbt': - raise ValueError(f'Invalid panel spec {side!r}.') - # Detect *unknown* keyword args, raise error if found! - regex = re.compile(f'^[tlrb]?({"array|" if figure else ""}share|space|width)$') - kwextra = {key:kwargs.pop(key) for key in (*kwargs,) if not regex.match(key)} - deprec1 = {key:value for key,value in kwextra.items() if key in ( - 'sep', 'lsep', 'rsep', 'bsep', 'tsep', - 'stack', 'lstack', 'rstack', 'bstack', 'tstack', - )} - deprec2 = {key:value for key,value in kwextra.items() if key in ( - 'colorbar', 'colorbars', 'legend', 'legends', - 'axcolorbar', 'axcolorbars', 'axlegend', 'axlegends', - 'axcolorbar_kw', 'axcolorbars_kw', 'axlegend_kw', 'axlegends_kw', - )} - unknown = {key:value for key,value in kwextra.items() - if key not in deprec1 and key not in deprec2} - if deprec1: - raise ValueError(f'You used the following deprecated subplots() or panel_axes() keyword arg(s): {deprec1!r}. To draw "stacked" panels with the current API, simply call e.g. Axes.colorbar(loc="r") or Axes.panel("r") more than once, and multiple panels will be drawn on that side.') - if deprec2: - raise ValueError(f'You used the following deprecated subplots() keyword arg(s): {deprec2!r}. With the current API, you just use "panel", "panels", "axpanel", "axpanels", "axpanel_kw", and/or "axpanels_kw". If you "fill" a panel with a colorbar or legend, its width will be adjusted automatically.') - if unknown: - raise ValueError(f'Unknown subplots() or panel_axes() keyword arg(s): {unknown!r}.') - - # Detect *ignored* panel keyword args, issue warning - s_off = ''.join({*'lrbt'} - {s}) - regex = re.compile(f'^[{s_off}]({"array|" if figure else ""}share|width|space)$') - ikw = {key:value for key,value in kwargs.items() if regex.match(s_off)} - if ikw: - warnings.warn(f'Ignoring keyword arg(s): {ikw}. Active sides are: {sides!r}.') - - # Try to use local first, global if no local found - def get(key): - return _notNone(kwargs.get(s + key, None), kwargs.get(key, None)) - kwout, kworig = {}, {} - # Store originals, prevents automatic changes if user passed anything - share = _notNone(get('share'), (mode == 'panel')) - width = units(get('width')) - space = units(get('space')) - kworig[s + 'width'] = width - kworig[s + 'space'] = space - # Store values used in initial drawing - width = units(_notNone(width, rc['subplots.' + mode + 'width'])) - space = _notNone(space, units(rc['subplots.' + ('panel' if share - and not figure - else 'xlab' if s == 'b' else 'ylab' if s == 'l' - else 'inner' if figure else 'panel') + 'space'])) - kwout[s + 'share'] = share - kwout[s + 'width'] = width - kwout[s + 'space'] = space - if figure: - kwout[s + 'array'] = get('array') - return kwout, kworig - #-----------------------------------------------------------------------------# # Figure class and helper classes #-----------------------------------------------------------------------------# @@ -760,16 +722,19 @@ def __init__(self, self._axes_main = [] self._subplots_orig_kw = subplots_orig_kw self._subplots_kw = subplots_kw - self._leftpanel = axes.EmptyPanel() - self._bottompanel = axes.EmptyPanel() - self._rightpanel = axes.EmptyPanel() - self._toppanel = axes.EmptyPanel() + self._bpanels = [] + self._tpanels = [] + self._lpanels = [] + self._rpanels = [] self._gridspec_main = FlexibleGridSpec(self, **(gridspec_kw or {})) self.suptitle('') # add _suptitle attribute @_counter def _add_axes_panel(self, side, ax, order='C', mode='panel', **kwargs): """Hidden method that powers `~proplot.axes.panel_axes`.""" + # Redirect to main axes, e.g. if want to draw outer colorbar or legend + # from data plotted in a panel or inset axes + ax = ax._panel_parent or ax # Interpret args # NOTE: Axis sharing not implemented for figure panels, 99% of the # time this is just used as construct for adding global colorbars and @@ -778,12 +743,8 @@ def _add_axes_panel(self, side, ax, order='C', mode='panel', **kwargs): if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') side = _side_translate[s] - kwargs, kworig = _panels_kwargs(s, kwargs, mode=mode, figure=False) - width = kwargs[s + 'width'] - space = kwargs[s + 'space'] - share = kwargs[s + 'share'] - width_orig = kworig[s + 'width'] - space_orig = kworig[s + 'space'] + share, width, space, space_orig = _panels_kwargs(s, + kwargs, mode=mode, figure=False) # Modify existing geometry, find incies for new panel by placing it # to the outside of *existing* panels if possible @@ -791,7 +752,7 @@ def _add_axes_panel(self, side, ax, order='C', mode='panel', **kwargs): # width and space. subplotspec = ax.get_subplotspec() nrows, ncols, row1, row2, col1, col2 = subplotspec.get_active_rows_columns() - pgrid = getattr(ax, '_' + side + 'panel') + pgrid = getattr(ax, '_' + s + 'panels') offset = (len(pgrid)*bool(pgrid)) + 1 if s in 'lr': idx1 = slice(row1, row2 + 1) @@ -801,46 +762,37 @@ def _add_axes_panel(self, side, ax, order='C', mode='panel', **kwargs): idx1 = (row1 - offset if s == 't' else row2 + offset) idx2 = slice(col1, col2 + 1) iratio = idx1 - gridspec = self._change_gridspec(side, iratio, - width, space, width_orig, space_orig, + gridspec = self._insert_row_column(side, iratio, + width, space, space_orig, figure=False, ) # Get keyword args and gridspec args # Loop through unique numbers with self._unlock(): - pax = self.add_subplot(gridspec[idx1,idx2], - projection='panel', - side=side, share=share, - ) + pax = self.add_subplot(gridspec[idx1,idx2], projection='cartesian') - # Add to panel attributes - pgrid = getattr(ax, '_' + side + 'panel') - # Create from scratch - if not pgrid: - order = self._order - pgrid = axes_grid([pax], n=1, order=order) - setattr(ax, '_' + side + 'panel', pgrid) - # Modify existing grid + # Add to panel list + pgrid = getattr(ax, '_' + s + 'panels') + if s in 'lt': + pgrid.insert(0, pax) else: - n = pgrid._n - order = pgrid._order - if s in 'lt': - pgrid.insert(0, pax) - else: - pgrid.append(pax) - if (s in 'lr' and order == 'C') or (s in 'tb' and order == 'F'): - n += 1 - pgrid._n = n + pgrid.append(pax) # Set up shared axes + pax._panel_side = side + pax._panel_share = share + pax._panel_parent = ax if share: ax._share_panels_setup() self._share_axes_setup(ax) + axis = (pax.yaxis if side in ('left','right') else pax.xaxis) + getattr(axis, 'tick_' + side)() # sets tick and tick label positions intelligently + axis.set_label_position(side) # Return axes grid of just this axes - return axes_grid([pax]) + return pax - def _add_figure_panels(self, side, mode='panel', **kwargs): + def _add_figure_panel(self, side, mode='panel', array=None, **kwargs): """Adds figure panels. Also modifies the panel attribute stored on the figure to include these panels.""" # Interpret args @@ -852,12 +804,8 @@ def _add_figure_panels(self, side, mode='panel', **kwargs): if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') side = _side_translate[s] - kwargs, kworig = _panels_kwargs(s, kwargs, mode=mode, figure=True) - array = kwargs[s + 'array'] - width = kwargs[s + 'width'] - space = kwargs[s + 'space'] - width_orig = kworig[s + 'width'] - space_orig = kworig[s + 'space'] + _, width, space, space_orig = _panels_kwargs(s, + kwargs, mode=mode, figure=True) # Modify existing geometry, and verify validity of the array arg # using boolean 1D arrays indicating where panels are present for @@ -876,9 +824,8 @@ def _add_figure_panels(self, side, mode='panel', **kwargs): if not np.iterable(array) or len(array) != len(idxs): raise ValueError(f'Need length-{len(idxs)} list of integers for "{s}array", got {s}array={array!r}.') iratio = (0 if s in 'lt' else nacross) - gridspec = self._change_gridspec(side, iratio, - width, space, width_orig, space_orig, - figure=True, + gridspec = self._insert_row_column(side, iratio, + width, space, space_orig, figure=True, ) # Pad array so it spans existing panel slots @@ -897,51 +844,25 @@ def _add_figure_panels(self, side, mode='panel', **kwargs): if s in 'bt': idx1, idx2 = idx2, idx1 with self._unlock(): - ipax = self.add_subplot(gridspec[idx1,idx2], - projection='panel', - side=side, share=False, - ) + ipax = self.add_subplot(gridspec[idx1,idx2], projection='cartesian') + ipax._panel_side = side + ipax._panel_share = False + ipax._panel_parent = None + axis = (ipax.yaxis if side in ('left','right') else ipax.xaxis) + getattr(axis, 'tick_' + side)() # sets tick and tick label positions intelligently + axis.set_label_position(side) paxs += [ipax] # Add to panel attributes - pgrid = getattr(self, '_' + side + 'panel') - # Create brand new axes_grid - if not pgrid: - order = self._order - if (s in 'tb' and order == 'C') or (s in 'lr' and order != 'C'): - n = 1 - else: - n = len(paxs) - pgrid = axes_grid(paxs, n=n, order=order) - setattr(self, '_' + side + 'panel', pgrid) - # Modify existing axes_grid + pgrid = getattr(self, '_' + s + 'panels') + if s in 'lt': + pgrid.insert(0, paxs[0]) else: - # Possible insertion modes - # The names are relevant for C-major order - order = pgrid._order - top = (s == 't' and order == 'C') or (s == 'l' and order == 'F') - bottom = (s == 'b' and order == 'C') or (s == 'r' and order == 'F') - left = (s == 'l' and order == 'C') or (s == 't' and order == 'F') - right = (s == 'r' and order == 'C') or (s == 'b' and order == 'F') - # Insert into lists - # NOTE: Can get weird grids for weird geometry, e.g. 3 figure - # panels side-by-side on top of one figure panel - n = pgrid._n - for i,ax in enumerate(paxs): - if top: - pgrid.insert(0, ax) - elif bottom: - pgrid.append(ax) - elif left: - pgrid.insert(i*n + i, ax) # plus i offsets after adding stuff - elif right: - pgrid.insert((i + 1)*n - 1 + i, ax) - if left or right: # fastest-moving dim length increased by 1 - n += 1 - pgrid._n = n + pgrid.append(paxs[0]) # Return axes_grid of just the axes drawn in this round - return axes_grid(paxs) # no 2D indexing + # TODO: Draw one at a time!!! + return paxs[0] def _adjust_aspect(self): """Adjust average aspect ratio used for gridspec calculations. This @@ -1218,13 +1139,13 @@ def _align_suplabels(self, renderer): 'transform':self.transFigure} suptitle.update(kw) - def _change_gridspec(self, side, idx, - ratio, space, ratio_orig, space_orig, + def _insert_row_column(self, side, idx, + ratio, space, space_orig, figure=False): - """Helper function that "overwrites" the main figure gridspec, used - when successively adding panels. The `side` is the panel side, - the `idx` is the slot you want the panel to occupy, and the remaining - args are the panel widths and spacings.""" + """Helper function that "overwrites" the main figure gridspec to make + room for a panel. The `side` is the panel side, the `idx` is the + slot you want the panel to occupy, and the remaining args are the + panel widths and spacings.""" # Constants and stuff # Insert spaces to the left of right panels or to the right of # left panels. And note that since .insert() pushes everything in @@ -1246,7 +1167,6 @@ def _change_gridspec(self, side, idx, panels = subplots_kw[w + 'panels'] ratios = subplots_kw[w + 'ratios'] spaces = subplots_kw[w + 'space'] - ratios_orig = subplots_orig_kw[w + 'ratios'] spaces_orig = subplots_orig_kw[w + 'space'] # Slot already exists @@ -1254,10 +1174,6 @@ def _change_gridspec(self, side, idx, # add them along entire side all at once exists = (not figure and idx < len(panels) and panels[idx] == s) if exists: # already exists! - # Modify existing width, defer to user input - if ratios_orig[idx] is None: - ratios_orig[idx] = units(ratio_orig) - ratios[idx] = _notNone(ratios_orig[idx], ratio) # Modify existing space if spaces_orig[idx_space] is None: spaces_orig[idx_space] = units(space_orig) @@ -1268,13 +1184,11 @@ def _change_gridspec(self, side, idx, idx += idx_offset idx_space += idx_offset subplots_kw[ncols] += 1 - # Ratio array, space array, panel toggles + # Original space, ratio array, space array, panel toggles + spaces_orig.insert(idx_space, space_orig) spaces.insert(idx_space, space) ratios.insert(idx, ratio) panels.insert(idx, 'f' if figure else s) - # Original info - ratios_orig.insert(idx, ratio_orig) - spaces_orig.insert(idx_space, space_orig) # Reference ax location array ref = subplots_kw[x + 'ref'] for i,val in enumerate(ref): @@ -1367,57 +1281,6 @@ def _get_align_axes(self, side): ord = [ax._range_gridspec(y)[0] for ax in axs] return [ax for _,ax in sorted(zip(ord, axs)) if ax.get_visible()] - def _resize_panel(self, pax, width, mode='panel'): - """Modifies the panel width in case it is being "filled" by a - colorbar or legend. The input is the user input width (may be ``None``) - and the mode, one of ``'colorbar'`` or ``'legend'``.""" - # Get index - subplotspec = pax.get_subplotspec() - *_, row, _, col, _ = subplotspec.get_active_rows_columns() - s = pax._side[0] - if s in 'lr': - x, y, w, idx = 'x', 'y', 'w', col - else: - x, y, w, idx = 'y', 'x', 'h', row - - # Set new widths, taking care to obey user input widths! - subplots_kw = self._subplots_kw - subplots_orig_kw = self._subplots_orig_kw - ratios = subplots_kw[w + 'ratios'] - ratios_orig = subplots_orig_kw[w + 'ratios'] - if ratios_orig[idx] is None or width is not None: - ratios_orig[idx] = units(width) - width = units(_notNone(ratios_orig[idx], rc['subplots.' + mode + 'width'])) - ratios[idx] = width - - # Apply to panel - figsize, gridspec_kw, _ = _subplots_geometry(**subplots_kw) - self.set_size_inches(figsize) - self._gridspec_main.update(**gridspec_kw) - - # Undo action of _sharex_setup and _sharey_setup - # NOTE: Largely copied from Figure._remove_ax, except we copy - # locators and formatters from parent to child. - irange = pax._range_gridspec(x) - jrange = pax._range_gridspec(y) - for ax in self._iter_axes(): - if not (ax._range_gridspec(x) == irange - or ax._range_gridspec(y) == jrange): - continue - for axis1,axis2,parent,grouper in zip( - (pax.xaxis, pax.yaxis), - (ax.xaxis, ax.yaxis), - ('_sharex', '_sharey'), - (ax._shared_x_axes, ax._shared_y_axes)): - if getattr(ax, parent) is not pax: - continue - setattr(ax, parent, None) - grouper.remove(pax) - axis2.label.set_visible(True) - axis2.set_minor_locator(axis1.get_minor_locator()) - axis2.set_major_locator(axis1.get_major_locator()) - axis2.set_major_formatter(axis1.get_major_formatter()) - def _unlock(self): """Prevents warning message when adding subplots one-by-one, used internally.""" @@ -1513,26 +1376,64 @@ def add_subplot(self, *args, **kwargs): ax = super().add_subplot(*args, **kwargs) return ax - def colorbar(self, *args, loc='r', panel_kw=None, **kwargs): - """Draws a colorbar along the left, right, bottom, or top side + def colorbar(self, *args, loc='r', width=None, space=None, **kwargs): + """ + Draws a colorbar along the left, right, bottom, or top side of the figure, centered between the leftmost and rightmost (or - topmost and bottommost) main axes.""" + topmost and bottommost) main axes. + + Parameters + ---------- + panel : str, optional + Adds :ref:`Global figure panels` to the specified side. + String should contain any of the characters ``'l'`` (left), ``'r'`` + (right), ``'b'`` (bottom), or ``'t'`` (top). For example, ``'br'`` + will draw panels on the right and bottom sides of the figure. + panels : str, optional + As with `panel`, but the default behavior is to assign a panel + to *every* row or column of subplots. Individual panels can then + be accessed with e.g. ``fig.leftpanel[0]``, ``fig.leftpanel[1]``. + array : list of int, optional + Defines how figure panels span rows and columns of subplots. + Interpreted like `array` -- the integers specify panels that span + *arbitrary, contiguous* columns or rows of subplots. + + For example, ``plot.suplots(ncols=3, panels='b', barray=[1, 2, 2])`` + draws a panel on the bottom of the first column and spanning the bottom + of the right 2 columns, and ``barray=[0, 2, 2]`` only draws a panel + underneath the right 2 columns -- as with `array`, the ``0`` indicates + an empty space. + width : float or str, optional + As in `~proplot.axes.Axes.panel_axes`. Use e.g. `lwidth`, `rwidth`, + `bwidth`, and `twidth` to apply these settings to panels on different + sides. + space : float or str, optional + As in `~proplot.axes.Axes.panel_axes`, but controls space + between the main subplot grid and the figure panels. + *args, **kwargs + Passed to `~proplot.axes.Axes.colorbar`. + """ if 'cax' in kwargs: return super().colorbar(*args, **kwargs) else: - panel_kw = panel_kw or {} - panel_kw.setdefault('mode', 'colorbar') - paxs = self._add_figure_panels(loc, **panel_kw) - return paxs.colorbar(*args, **kwargs) + ax = self._add_figure_panel(loc, space=space, width=width, array=None, mode='colorbar') + return ax.colorbar(*args, loc='_fill', **kwargs) - def legend(self, *args, loc='r', panel_kw=None, **kwargs): - """Draws a legend along the left, right, bottom, or top side of the + def legend(self, *args, loc='r', width=None, space=None, **kwargs): + """ + Draws a legend along the left, right, bottom, or top side of the figure, centered between the leftmost and rightmost (or - topmost and bottommost) main axes.""" - panel_kw = panel_kw or {} - panel_kw.setdefault('mode', 'legend') - paxs = self._add_figure_panels(loc, **panel_kw) - return paxs.legend(*args, **kwargs) + topmost and bottommost) main axes. + + Parameters + ---------- + loc, width, space + See `~Figure.colorbar`. + *args, **kwargs + Passed to `~proplot.axes.Axes.legend`. + """ + ax = self._add_figure_panel(loc, space=space, width=width, array=None, mode='legend') + return ax.legend(*args, loc='_fill', **kwargs) @_counter def draw(self, renderer): @@ -1606,44 +1507,18 @@ def savefig(self, filename, **kwargs): """Alias for `~Figure.savefig`, because calling ``fig.savefig`` is sort of redundant.""" - @property - def leftpanel(self): - """An `~proplot.subplots.axes_grid` of the left panel stack.""" - return self._leftpanel - @property - def rightpanel(self): - """An `~proplot.subplots.axes_grid` of the right panel stack.""" - return self._rightpanel - @property - def toppanel(self): - """An `~proplot.subplots.axes_grid` of the top panel stack.""" - return self._toppanel - @property - def bottompanel(self): - """An `~proplot.subplots.axes_grid` of the bottom panel stack.""" - return self._bottompanel - - lpanel = leftpanel - """Alias for `~Figure.leftpanel`.""" - rpanel = rightpanel - """Alias for `~Figure.rightpanel`.""" - tpanel = toppanel - """Alias for `~Figure.toppanel`.""" - bpanel = bottompanel - """Alias for `~Figure.bottompanel`.""" - def _iter_axes(self): """Iterates over all axes and panels in the figure belonging to the `~proplot.axes.Axes` class. Excludes inset and twin axes.""" axs = [] - for ax in (*self._axes_main, *self.leftpanel, *self.rightpanel, - *self.bottompanel, *self.toppanel): + for ax in (*self._axes_main, *self._lpanels, *self._rpanels, + *self._bpanels, *self._tpanels): if not ax or not ax.get_visible(): continue axs.append(ax) for ax in axs: for s in 'lrbt': - for iax in getattr(ax, s + 'panel'): + for iax in getattr(ax, '_' + s + 'panels'): if not iax or not iax.get_visible(): continue axs.append(iax) @@ -1732,11 +1607,9 @@ def subplots(array=None, ncols=1, nrows=1, span=None, spanx=None, spany=None, align=None, alignx=None, aligny=None, share=None, sharex=None, sharey=None, - panel=None, panels=None, axpanel=None, axpanels=None, - axpanel_kw=None, axpanels_kw=None, basemap=False, proj=None, projection=None, proj_kw=None, projection_kw=None, autoformat=True, - **kwargs): + ): """ Analogous to `matplotlib.pyplot.subplots`, creates a figure with a single axes or arbitrary grids of axes, any of which can be map projections, @@ -1873,39 +1746,6 @@ def subplots(array=None, ncols=1, nrows=1, If boolean, applies to all subplots. If dictionary, values apply to specific subplots, as with `proj`. - panel : str, optional - Adds :ref:`Global figure panels` to the specified side. - String should contain any of the characters ``'l'`` (left), ``'r'`` - (right), ``'b'`` (bottom), or ``'t'`` (top). For example, ``'br'`` - will draw panels on the right and bottom sides of the figure. - - Figure panels are saved as the `~Figure.leftpanel`, - `~Figure.rightpanel`, `~Figure.bottompanel`, or - `~Figure.toppanel` attributes, with respective shorthands - `~Figure.lpanel`, `~Figure.rpanel`, `~Figure.bpanel`, and - `~Figure.tpanel`. - panels : str, optional - As with `panel`, but the default behavior is to assign a panel - to *every* row or column of subplots. Individual panels can then - be accessed with e.g. ``fig.leftpanel[0]``, ``fig.leftpanel[1]``. - [lrbt]array : list of int, optional - Defines how figure panels span rows and columns of subplots. - Interpreted like `array` -- the integers specify panels that span - *arbitrary, contiguous* columns or rows of subplots. - - For example, ``plot.suplots(ncols=3, panels='b', barray=[1, 2, 2])`` - draws a panel on the bottom of the first column and spanning the bottom - of the right 2 columns, and ``barray=[0, 2, 2]`` only draws a panel - underneath the right 2 columns -- as with `array`, the ``0`` indicates - an empty space. - [lrbt]width, [lrbt]share, [lrbt]stack, [lrbt]sep - As in `~proplot.axes.Axes.panel_axes`. Use e.g. `lwidth`, `rwidth`, - `bwidth`, and `twidth` to apply these settings to panels on different - sides. - [lrtb]space : float or str, optional - As in `~proplot.axes.Axes.panel_axes`, but controls space - between the main subplot grid and the figure panels. - Other parameters ---------------- tight : bool, optional @@ -1918,32 +1758,6 @@ def subplots(array=None, ncols=1, nrows=1, autoformat : bool, optional Whether to automatically format axes when special datasets are passed to plotting commands. See `Figure` for details. - axpanel, axpanels : str or dict-like, optional - Adds :ref:`Bulk axes panels` to subplots with - `~proplot.axes.Axes.panel_axes`. Both `axpanel` and `axpanels` - are acceptable. The argument is interpreted as follows. - - * If string, panels are drawn on the same side for all subplots. - String should contain any of the characters ``'l'`` (left panel), - ``'r'`` (right panel), ``'t'`` (top panel), or ``'b'`` (bottom - panel). For example, ``'rt'`` will draw a right and top panel. - * If dict-like, panels can be drawn on different sides for - different subplots. For example, consider a 3-subplot figure. - With ``axpanels={2:'r', 3:'l'}``, subplot 1 will have no panel, - subplot 2 will have a panel on the right side, and subplot 3 - will have a panel on the left side. - - axpanel_kw, axpanels_kw : dict-like, optional - Keyword args passed to `~proplot.axes.Axes.panel_axes` for panels - listed in `axpanel` and `axpanels`. If dictionary of properties, - applies globally. If *dictionary of dictionary* of properties, applies - to specific subplots, as with `axpanels`. - - For example, consider a 2-subplot figure with ``axpanels='l'``. - With ``axpanel_kw={'lwidth':1}``, both left panels will be 1 inch wide. - With ``axpanel_kw={1:{'lwidth':1}, 2:{'lwidth':0.5}}``, the left - subplot panel will be 1 inch wide and the right subplot panel will be - 0.5 inches wide. Returns ------- @@ -2112,7 +1926,6 @@ def subplots(array=None, ncols=1, nrows=1, subplots_orig_kw = { 'left':left, 'right':right, 'top':top, 'bottom':bottom, 'wspace':wspace, 'hspace':hspace, - 'wratios':wratios, 'hratios':hratios, } # Default border spaces @@ -2171,42 +1984,6 @@ def subplots(array=None, ncols=1, nrows=1, fig._axes_main = axs fig._share_axes_setup() - # Draw figure panels - # First get default arrays - panel, panels = _notNone(panel, ''), _notNone(panels, '') - for ipanel,ispan in zip((panel,panels),(1,0)): - for s in ipanel: - nmax = (ncols if s in 'bt' else nrows) - value = ([1]*nmax if ispan else [*range(1,nmax+1)]) - kwargs.setdefault(s + 'array', value) - for s in (panel + panels): - fig._add_figure_panels(s, **kwargs) - - # Draw axes panel - # Input can be string e.g. 'rl' or dictionary e.g. {(1,2,3):'r', 4:'l'} - # NOTE: This *must* come after shared axes are set up! Otherwise tight - # layout scaling is wrong - axpanels = _notNone(axpanel, axpanels, '', names=('axpanel','axpanels')) - axpanels_kw = _notNone(axpanel_kw, axpanels_kw, {}, names=('axpanel_kw', 'axpanels_kw')) - axpanels = _axes_dict(naxs, axpanels, kw=False, default='') - axpanels_kw = _axes_dict(naxs, axpanels_kw, kw=True) - for idx in range(naxs): - ax = axs[idx] - num = idx + 1 - keys = {*()} - sides, panels_kw = axpanels[num], axpanels_kw[num] - # Loop through sides - for s in sides: - offsides = ''.join({*'lrbt'} - {s}) - reg = re.compile(f'^[{offsides}](share|space|width)$') - ikw = {key:value for key,value in panels_kw.items() if not reg.match(key)} - keys.update(ikw.keys()) - fig._add_axes_panel(s, ax, order=order, **ikw) - # Warning message - jkw = {key:value for key,value in panels_kw.items() if key not in keys} - if jkw: - warnings.warn(f'Ignoring axpanels_kw keyword arg(s): {jkw}. Active sides are: axpanels={sides!r}.') - # Return figure and axes n = (ncols if order == 'C' else nrows) return fig, axes_grid(axs, n=n, order=order) diff --git a/proplot/wrappers.py b/proplot/wrappers.py index 20d7341b2..4f230f29e 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -615,7 +615,7 @@ def plot_wrapper(self, func, *args, cmap=None, values=None, **kwargs): if len(args) > 3: # e.g. with fmt string raise ValueError(f'Expected 1-3 positional args, got {len(args)}.') if cmap is None: - lines = func(*args, **kwargs) + lines = func(*args, values=values, **kwargs) else: lines = self.cmapline(*args, cmap=cmap, values=values, **kwargs) return lines @@ -1512,6 +1512,7 @@ def cycle_wrapper(self, func, *args, objs = [] ncols = 1 label_leg = None # for colorbar or legend + print('hi!!!', values, labels) labels = _notNone(values, labels, label, None, names=('values', 'labels', 'label')) stacked = kwargs.pop('stacked', False) if name in ('pie','boxplot','violinplot'): @@ -1584,35 +1585,35 @@ def cycle_wrapper(self, func, *args, if colorbar: # Add handles panel_kw.setdefault('mode', 'colorbar') - ax, loc = self._inset_or_panel_loc(colorbar, **panel_kw) + loc = self._loc_translate(colorbar, **panel_kw) if not isinstance(loc, str): raise ValueError(f'Invalid on-the-fly location {loc!r}. Must be a preset location. See Axes.colorbar') - if loc not in ax._auto_colorbar: - ax._auto_colorbar[loc] = [] - ax._auto_colorbar_kw[loc] = {} - ax._auto_colorbar[loc].extend(objs) + if loc not in self._auto_colorbar: + self._auto_colorbar[loc] = [] + self._auto_colorbar_kw[loc] = {} + self._auto_colorbar[loc].extend(objs) # Add keywords if loc != 'fill': colorbar_kw.setdefault('loc', loc) if label_leg: colorbar_kw.setdefault('label', label_leg) - ax._auto_colorbar_kw[loc].update(colorbar_kw) + self._auto_colorbar_kw[loc].update(colorbar_kw) if legend: # Add handles panel_kw.setdefault('mode', 'legend') - ax, loc = self._inset_or_panel_loc(legend, **panel_kw) + loc = self._loc_translate(legend, **panel_kw) if not isinstance(loc, str): raise ValueError(f'Invalid on-the-fly location {loc!r}. Must be a preset location. See Axes.legend') - if loc not in ax._auto_legend: - ax._auto_legend[loc] = [] - ax._auto_legend_kw[loc] = {} - ax._auto_legend[loc].extend(objs) + if loc not in self._auto_legend: + self._auto_legend[loc] = [] + self._auto_legend_kw[loc] = {} + self._auto_legend[loc].extend(objs) # Add keywords if loc != 'fill': legend_kw.setdefault('loc', loc) if label_leg: legend_kw.setdefault('label', label_leg) - ax._auto_legend_kw[loc].update(legend_kw) + self._auto_legend_kw[loc].update(legend_kw) # Return # WARNING: Make sure plot always returns tuple of objects, and bar always @@ -2018,7 +2019,7 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, # Add colorbar if colorbar: panel_kw.setdefault('mode', 'colorbar') - ax, loc = self._inset_or_panel_loc(colorbar, **panel_kw) + loc = self._loc_translate(colorbar, **panel_kw) if not isinstance(loc, str): raise ValueError(f'Invalid on-the-fly location {loc!r}. Must be a preset location. See Axes.colorbar.') if 'label' not in colorbar_kw and self.figure._auto_format: @@ -2029,7 +2030,7 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, colorbar_kw.setdefault('values', values) if loc != 'fill': colorbar_kw.setdefault('loc', loc) - ax.colorbar(obj, **colorbar_kw) + self.colorbar(obj, **colorbar_kw) return obj #------------------------------------------------------------------------------# From aa4cccffa3fa456ff1fd54ade20a16e5e3f546a1 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Mon, 2 Sep 2019 23:41:46 -0600 Subject: [PATCH 04/28] On-the-fly figure colorbars and legends! --- proplot/axes.py | 60 ++++---- proplot/styletools.py | 8 +- proplot/subplots.py | 338 ++++++++++++++++++++++++------------------ proplot/wrappers.py | 4 +- 4 files changed, 227 insertions(+), 183 deletions(-) diff --git a/proplot/axes.py b/proplot/axes.py index 6a170a951..53a6df82d 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -640,19 +640,19 @@ def format(self, *, title=None, top=None, main title. The following locations keys are valid. Defaults to ``rc['abc.loc']`` and ``rc['title.loc']``. - ========================= ============================ - Location Valid keys - ========================= ============================ - center, above axes ``'center'``, ``'c'`` - left, above axes ``'left'``, ``'l'`` - right, above axes ``'right'``, ``'r'`` - lower center, inside axes ``'lower center``', ``'lc'`` - upper center, inside axes ``'upper center'``, ``'uc'`` - upper right, inside axes ``'upper right'``, ``'ur'`` - upper left, inside axes ``'upper left'``, ``'ul'`` - lower left, inside axes ``'lower left'``, ``'ll'`` - lower right, inside axes ``'lower right'``, ``'lr'`` - ========================= ============================ + ======================== ============================ + Location Valid keys + ======================== ============================ + center above axes ``'center'``, ``'c'`` + left above axes ``'left'``, ``'l'`` + right above axes ``'right'``, ``'r'`` + lower center inside axes ``'lower center``', ``'lc'`` + upper center inside axes ``'upper center'``, ``'uc'`` + upper right inside axes ``'upper right'``, ``'ur'`` + upper left inside axes ``'upper left'``, ``'ul'`` + lower left inside axes ``'lower left'``, ``'ll'`` + lower right inside axes ``'lower right'``, ``'lr'`` + ======================== ============================ abcborder, titleborder : bool, optional Whether to draw a white border around titles and a-b-c labels @@ -915,6 +915,7 @@ def colorbar(self, *args, loc=None, pad=None, outer right ``'r'``, ``'right'`` outer bottom ``'b'``, ``'bottom'`` outer top ``'t'``, ``'top'`` + default inset ``0``, ``'i'``, ``'inset'`` upper right inset ``1``, ``'upper right'``, ``'ur'`` upper left inset ``2``, ``'upper left'``, ``'ul'`` lower left inset ``3``, ``'lower left'``, ``'ll'`` @@ -930,12 +931,19 @@ def colorbar(self, *args, loc=None, pad=None, The colorbar length. For outer colorbars, units are relative to the axes width or height. For inset colorbars, if float, units are inches; if string, units are interpreted by `~proplot.utils.units`. - Defaults to ``rc['colorbar.length']``. + Defaults to ``rc['colorbar.length']`` for outer colorbars, + ``rc['colorbar.lengthinset']`` for inset colorbars. width : float or str, optional The colorbar width. If float, units are inches. If string, units are interpreted by `~proplot.utils.units`. Defaults to - ``rc['colorbar.width']`` for inset colorbars, - ``rc['subplots.cbarwidth']`` for outer colorbars. + ``rc['colorbar.width']`` for outer colorbars, + ``rc['colorbar.widthinset']`` for inset colorbars. + space : float or str, optional + The space between the colorbar and the main axes for outer + colorbars. If float, units are inches. If string, + units are interpreted by `~proplot.utils.units`. By default, this + is adjusted automatically in the "tight layout" calculation, or is + ``rc['subplots.panelspace']`` if "tight layout" is turned off. frame, frameon : bool, optional Whether to draw a frame around inset colorbars, just like `~matplotlib.axes.Axes.legend`. @@ -946,18 +954,6 @@ def colorbar(self, *args, loc=None, pad=None, ``rc['colorbar.framealpha']``, ``rc['axes.linewidth']``, ``rc['axes.edgecolor']``, and ``rc['axes.facecolor']``, respectively. - width : float or str, optional - The width of the colorbar. If float, units are inches. If string, - units are interpreted by `~proplot.utils.units`. Defaults to - ``rc['colorbar.width']`` for inset colorbars and - ``rc['subplots.colorbarwidth']`` for outer colorbars. - space : float or str, optional - The space between the colorbar and the main axes for outer - colorbars. If float, units are inches. If string, - units are interpreted by `~proplot.utils.units`. By default, this - is adjusted automatically in the "tight layout" calculation, - or is ``rc['subplots.panelspace']`` if "tight layout" is turned - off. **kwargs Passed to `~proplot.wrappers.colorbar_wrapper`. """ @@ -972,7 +968,7 @@ def colorbar(self, *args, loc=None, pad=None, # Generate panel if loc in ('left','right','top','bottom'): - ax = self.panel_axes(loc, width=width, space=space, mode='colorbar') + ax = self.panel_axes(loc, width=width, space=space, filled=True) return ax.colorbar(loc='_fill', *args, **kwargs) # Filled colorbar @@ -1122,7 +1118,7 @@ def legend(self, *args, loc=None, width=None, space=None, **kwargs): right panel ``'r'``, ``'right'`` bottom panel ``'b'``, ``'bottom'`` top panel ``'t'``, ``'top'`` - "best" possible ``0``, ``'best'``, ``'inset'``, ``'i'`` + "best" inset ``0``, ``'best'``, ``'inset'``, ``'i'`` upper right inset ``1``, ``'upper right'``, ``'ur'`` upper left inset ``2``, ``'upper left'``, ``'ul'`` lower left inset ``3``, ``'lower left'``, ``'ll'`` @@ -1154,7 +1150,7 @@ def legend(self, *args, loc=None, width=None, space=None, **kwargs): # Generate panel if loc in ('left','right','top','bottom'): - ax = self.panel_axes(loc, width=width, space=space, mode='legend') + ax = self.panel_axes(loc, width=width, space=space, filled=True) return ax.legend(*args, loc='_fill', **kwargs) # Fill @@ -1358,7 +1354,7 @@ def panel_axes(self, side, **kwargs): `~proplot.axes.Axes` The panel axes. """ - return self.figure._add_axes_panel(side, self, **kwargs) + return self.figure._add_axes_panel(self, side, **kwargs) panel = panel_axes """Alias for `~Axes.panel_axes`.""" diff --git a/proplot/styletools.py b/proplot/styletools.py index 00719def0..42571da1f 100644 --- a/proplot/styletools.py +++ b/proplot/styletools.py @@ -481,13 +481,9 @@ def _get_channel(color, channel, space='hsl'): # Interpret string or RGB tuple offset = 0 if isinstance(color, str): - regex = '([-+]\S*)$' # user can optionally offset from color; don't filter to just numbers, want to raise our own error if user messes up - match = re.search(regex, color) + match = re.search('([-+][0-9.]+)$', color) if match: - try: - offset = float(match.group(0)) - except ValueError: - raise ValueError(f'Invalid channel identifier "{color}".') + offset = float(match.group(0)) color = color[:match.start()] return offset + to_xyz(to_rgb(color), space)[channel] diff --git a/proplot/subplots.py b/proplot/subplots.py index 30e695665..95ad897ac 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -472,21 +472,21 @@ def update(self, **kwargs): #-----------------------------------------------------------------------------# def _panels_kwargs(side, share=None, width=None, space=None, - mode='panel', figure=False): + filled=False, figure=False): """Converts global keywords like `space` and `width` to side-local keywords like `lspace` and `lwidth`, and applies default settings.""" # Return values + # NOTE: Make default legend width same as default colorbar width, in + # case user draws legend and colorbar panel in same row or column! s = side[0] if s not in 'lrbt': raise ValueError(f'Invalid panel spec {side!r}.') space_orig = units(space) - if mode == 'panel': - default = rc['subplots.panelwidth'] - elif mode == 'colorbar': + if filled: default = rc['colorbar.width'] else: - default = '1em' - share = _notNone(share, (mode == 'panel')) + default = rc['subplots.panelwidth'] + share = _notNone(share, (not filled)) width = units(_notNone(width, default)) space = _notNone(space, units(rc['subplots.' + ('panel' if share and not figure @@ -564,6 +564,8 @@ def _subplots_geometry(**kwargs): rhspace = sum(haxes_space[y1:y2]) rwratio = (ncols_ax*sum(waxes[x1:x2+1]))/(dx*sum(waxes)) rhratio = (nrows_ax*sum(haxes[y1:y2+1]))/(dy*sum(haxes)) + if rwratio == 0 or rhratio == 0: + raise RuntimeError(f'Something went wrong, got wratio={rwratio!r} and hratio={rhratio!r} for reference axes.') if np.iterable(aspect): aspect = aspect[0]/aspect[1] @@ -726,11 +728,17 @@ def __init__(self, self._tpanels = [] self._lpanels = [] self._rpanels = [] - self._gridspec_main = FlexibleGridSpec(self, **(gridspec_kw or {})) + gridspec = FlexibleGridSpec(self, **(gridspec_kw or {})) + nrows, ncols = gridspec.get_active_geometry() + self._barray = np.empty((0, ncols), dtype=bool) + self._tarray = np.empty((0, ncols), dtype=bool) + self._larray = np.empty((0, nrows), dtype=bool) + self._rarray = np.empty((0, nrows), dtype=bool) + self._gridspec_main = gridspec self.suptitle('') # add _suptitle attribute @_counter - def _add_axes_panel(self, side, ax, order='C', mode='panel', **kwargs): + def _add_axes_panel(self, ax, side, filled=False, **kwargs): """Hidden method that powers `~proplot.axes.panel_axes`.""" # Redirect to main axes, e.g. if want to draw outer colorbar or legend # from data plotted in a panel or inset axes @@ -744,12 +752,9 @@ def _add_axes_panel(self, side, ax, order='C', mode='panel', **kwargs): raise ValueError(f'Invalid side {side!r}.') side = _side_translate[s] share, width, space, space_orig = _panels_kwargs(s, - kwargs, mode=mode, figure=False) + kwargs, filled=filled, figure=False) - # Modify existing geometry, find incies for new panel by placing it - # to the outside of *existing* panels if possible - # TODO: If panel slot already exists, permit user to change the - # width and space. + # Get gridspec and subplotspec indices subplotspec = ax.get_subplotspec() nrows, ncols, row1, row2, col1, col2 = subplotspec.get_active_rows_columns() pgrid = getattr(ax, '_' + s + 'panels') @@ -763,106 +768,106 @@ def _add_axes_panel(self, side, ax, order='C', mode='panel', **kwargs): idx2 = slice(col1, col2 + 1) iratio = idx1 gridspec = self._insert_row_column(side, iratio, - width, space, space_orig, figure=False, - ) + width, space, space_orig, figure=False, + ) - # Get keyword args and gridspec args - # Loop through unique numbers + # Draw and setup panel with self._unlock(): pax = self.add_subplot(gridspec[idx1,idx2], projection='cartesian') - - # Add to panel list - pgrid = getattr(ax, '_' + s + 'panels') - if s in 'lt': - pgrid.insert(0, pax) - else: - pgrid.append(pax) - - # Set up shared axes + getattr(ax, '_' + s + 'panels').append(pax) pax._panel_side = side pax._panel_share = share pax._panel_parent = ax - if share: - ax._share_panels_setup() - self._share_axes_setup(ax) - axis = (pax.yaxis if side in ('left','right') else pax.xaxis) - getattr(axis, 'tick_' + side)() # sets tick and tick label positions intelligently - axis.set_label_position(side) - - # Return axes grid of just this axes + + # Axis sharing and axis setup only for non-legend or colorbar axes + if not filled: + if share: + ax._share_panels_setup() + self._share_axes_setup(ax) + axis = (pax.yaxis if side in ('left','right') else pax.xaxis) + getattr(axis, 'tick_' + side)() # sets tick and tick label positions intelligently + axis.set_label_position(side) + return pax - def _add_figure_panel(self, side, mode='panel', array=None, **kwargs): + def _add_figure_panel(self, side, span=None, **kwargs): """Adds figure panels. Also modifies the panel attribute stored on the figure to include these panels.""" - # Interpret args - # TODO: Allow successive panels! - # NOTE: Axis sharing not implemented for figure panels, 99% of the - # time this is just used as construct for adding global colorbars and - # legends, really not worth implementing axis sharing + # Get default panel args s = side[0] if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') side = _side_translate[s] - _, width, space, space_orig = _panels_kwargs(s, - kwargs, mode=mode, figure=True) + _, width, space, space_orig = _panels_kwargs(s, kwargs, + filled=True, figure=True) - # Modify existing geometry, and verify validity of the array arg - # using boolean 1D arrays indicating where panels are present for - # the dimension *spanned* by the new panel + # Get props subplots_kw = self._subplots_kw if s in 'lr': - panels = subplots_kw['wpanels'] - nacross, nalong = subplots_kw['ncols'], subplots_kw['nrows'] + panels, nacross = subplots_kw['hpanels'], subplots_kw['ncols'] else: - panels = subplots_kw['hpanels'] - nacross, nalong = subplots_kw['nrows'], subplots_kw['ncols'] - panels = np.array([bool(s) for s in panels]) - idxs, = np.where(~panels) - if array is None: - array = [1]*len(idxs) - if not np.iterable(array) or len(array) != len(idxs): - raise ValueError(f'Need length-{len(idxs)} list of integers for "{s}array", got {s}array={array!r}.') - iratio = (0 if s in 'lt' else nacross) - gridspec = self._insert_row_column(side, iratio, - width, space, space_orig, figure=True, - ) - - # Pad array so it spans existing panel slots - # NOTE: Does not matter if have e.g. [1, 0, 0, 1, 2, 0, 0, 2], because - # panels are drawn based on minimum and maximum indices - paxs = [] - array_new = np.zeros((nalong,)) - array_new[idxs] = array - # Get indices and draw axes - for num in np.unique(array_new).flat: - if num == 0: - continue - idx, = np.where(array_new == num) - idx1 = slice(min(idx), max(idx)+1) # ignores axes panel slots - idx2 = -1*(s in 'br') - if s in 'bt': - idx1, idx2 = idx2, idx1 - with self._unlock(): - ipax = self.add_subplot(gridspec[idx1,idx2], projection='cartesian') - ipax._panel_side = side - ipax._panel_share = False - ipax._panel_parent = None - axis = (ipax.yaxis if side in ('left','right') else ipax.xaxis) - getattr(axis, 'tick_' + side)() # sets tick and tick label positions intelligently - axis.set_label_position(side) - paxs += [ipax] - - # Add to panel attributes - pgrid = getattr(self, '_' + s + 'panels') - if s in 'lt': - pgrid.insert(0, paxs[0]) + panels, nacross = subplots_kw['wpanels'], subplots_kw['nrows'] + array = getattr(self, '_' + s + 'array') + npanels, nalong = array.shape + # Check span array + span = _notNone(span, (1, nalong)) + if not np.iterable(span) or len(span)==1: + span = 2*np.atleast_1d(span).tolist() + if len(span) != 2: + raise ValueError(f'Invalid span {span!r}.') + if span[0] < 1 or span[1] > nalong: + raise ValueError(f'Invalid coordinates in span={span!r}. Coordinates must satisfy 1 <= c <= {nalong}.') + start, stop = span[0] - 1, span[1] # zero-indexed + + # See if there is room for panel on the figure + # The 'array' is an array of boolean values, where each row corresponds + # to another figure panel, moving toward the outside, and + # We use add to panels toward the outside by appending rows to boolean + # arrays indicating which main axes rows and columns are occupied + iratio = (-1 if s in 'lt' else nacross) # default vals + for i in range(npanels): + if not any(array[i,start:stop]): + array[i,start:stop] = True + if s in 'lt': # descending array moves us closer to 0 + # npanels=1, i=0 --> iratio=0 + # npanels=2, i=0 --> iratio=1 + # npanels=2, i=1 --> iratio=0 + iratio = npanels - 1 - i + else: # descending array moves us closer to nacross-1 + # npanels=1, i=0 --> iratio=nacross-1 + # npanels=2, i=0 --> iratio=nacross-2 + # npanels=2, i=1 --> iratio=nacross-1 + iratio = nacross - (npanels - i) + break + # Add to array, since we are adding another panel + if iratio in (-1, nacross): + iarray = np.zeros((1, nalong), dtype=bool) + iarray[0,start:stop] = True + array = np.concatenate((array, iarray), axis=0) + setattr(self, '_' + s + 'array', array) + + # Get gridspec and subplotspec indices + idxs, = np.where(np.array(panels) == '') + if len(idxs) != nalong: + raise RuntimeError('Wut?') + if s in 'lr': + idx1 = slice(idxs[start], idxs[stop-1] + 1) + idx2 = max(iratio, 0) else: - pgrid.append(paxs[0]) + idx1 = max(iratio, 0) + idx2 = slice(idxs[start], idxs[stop-1] + 1) + gridspec = self._insert_row_column(side, iratio, + width, space, space_orig, figure=True, + ) - # Return axes_grid of just the axes drawn in this round - # TODO: Draw one at a time!!! - return paxs[0] + # Draw and setup panel + with self._unlock(): + pax = self.add_subplot(gridspec[idx1,idx2], projection='cartesian') + getattr(self, '_' + s + 'panels').append(pax) + pax._panel_side = side + pax._panel_share = False + pax._panel_parent = None + return pax def _adjust_aspect(self): """Adjust average aspect ratio used for gridspec calculations. This @@ -1140,8 +1145,8 @@ def _align_suplabels(self, renderer): suptitle.update(kw) def _insert_row_column(self, side, idx, - ratio, space, space_orig, - figure=False): + ratio, space, space_orig, figure=False, + ): """Helper function that "overwrites" the main figure gridspec to make room for a panel. The `side` is the panel side, the `idx` is the slot you want the panel to occupy, and the remaining args are the @@ -1155,13 +1160,13 @@ def _insert_row_column(self, side, idx, if s not in 'lrbt': raise ValueError(f'Invalid side {side}.') idx_space = idx - 1*bool(s in 'br') - idx_offset = 1*bool(s in 'tl')*bool(idx > 0) + idx_offset = 1*bool(s in 'tl') if s in 'lr': x, w, ncols = 'x', 'w', 'ncols' else: x, w, ncols = 'y', 'h', 'nrows' - # Load arrays + # Load arrays and test if we need to insert subplots_kw = self._subplots_kw subplots_orig_kw = self._subplots_orig_kw panels = subplots_kw[w + 'panels'] @@ -1170,11 +1175,9 @@ def _insert_row_column(self, side, idx, spaces_orig = subplots_orig_kw[w + 'space'] # Slot already exists - # NOTE: This is never the case for figure panels, because we always - # add them along entire side all at once - exists = (not figure and idx < len(panels) and panels[idx] == s) + entry = ('f' if figure else s) + exists = (idx not in (-1, len(panels)) and panels[idx] == entry) if exists: # already exists! - # Modify existing space if spaces_orig[idx_space] is None: spaces_orig[idx_space] = units(space_orig) spaces[idx_space] = _notNone(spaces_orig[idx_space], space) @@ -1188,12 +1191,12 @@ def _insert_row_column(self, side, idx, spaces_orig.insert(idx_space, space_orig) spaces.insert(idx_space, space) ratios.insert(idx, ratio) - panels.insert(idx, 'f' if figure else s) + panels.insert(idx, entry) # Reference ax location array - ref = subplots_kw[x + 'ref'] - for i,val in enumerate(ref): - if val >= idx: - ref[i] += 1 + # TODO: For now do not need to increment, but need to double + # check algorithm for fixing axes aspect! + # ref = subplots_kw[x + 'ref'] + # ref[:] = [val + 1 if val >= idx else val for val in ref] # Update figure figsize, gridspec_kw, _ = _subplots_geometry(**subplots_kw) @@ -1369,14 +1372,16 @@ def _share_axes_setup(self, ref=None): def add_subplot(self, *args, **kwargs): """Issues warning for new users that try to call - `~matplotlib.figure.Figure.add_subplot` or - `~matplotlib.figure.Figure.colorbar` manually.""" + `~matplotlib.figure.Figure.add_subplot` manually.""" if self._locked: - warnings.warn('Using "fig.add_subplot" or "fig.colorbar" with ProPlot figures may result in unexpected behavior. Please use "proplot.subplots" and "Axes.colorbar" instead.') + warnings.warn('Using "fig.add_subplot()" with ProPlot figures may result in unexpected behavior. Please use "proplot.subplots()" instead.') ax = super().add_subplot(*args, **kwargs) return ax - def colorbar(self, *args, loc='r', width=None, space=None, **kwargs): + def colorbar(self, *args, + loc='r', width=None, space=None, + row=None, col=None, rows=None, cols=None, span=None, + **kwargs): """ Draws a colorbar along the left, right, bottom, or top side of the figure, centered between the leftmost and rightmost (or @@ -1384,42 +1389,57 @@ def colorbar(self, *args, loc='r', width=None, space=None, **kwargs): Parameters ---------- - panel : str, optional - Adds :ref:`Global figure panels` to the specified side. - String should contain any of the characters ``'l'`` (left), ``'r'`` - (right), ``'b'`` (bottom), or ``'t'`` (top). For example, ``'br'`` - will draw panels on the right and bottom sides of the figure. - panels : str, optional - As with `panel`, but the default behavior is to assign a panel - to *every* row or column of subplots. Individual panels can then - be accessed with e.g. ``fig.leftpanel[0]``, ``fig.leftpanel[1]``. - array : list of int, optional - Defines how figure panels span rows and columns of subplots. - Interpreted like `array` -- the integers specify panels that span - *arbitrary, contiguous* columns or rows of subplots. - - For example, ``plot.suplots(ncols=3, panels='b', barray=[1, 2, 2])`` - draws a panel on the bottom of the first column and spanning the bottom - of the right 2 columns, and ``barray=[0, 2, 2]`` only draws a panel - underneath the right 2 columns -- as with `array`, the ``0`` indicates - an empty space. - width : float or str, optional - As in `~proplot.axes.Axes.panel_axes`. Use e.g. `lwidth`, `rwidth`, - `bwidth`, and `twidth` to apply these settings to panels on different - sides. + loc : str, optional + The colorbar location. Valid location keys are as follows. + + =========== ===================== + Location Valid keys + =========== ===================== + left edge ``'l'``, ``'left'`` + right edge ``'r'``, ``'right'`` + bottom edge ``'b'``, ``'bottom'`` + top edge ``'t'``, ``'top'`` + =========== ===================== + + row, col, rows, cols : optional + Aliases for `span`. + span : int or (int, int), optional + Describes how the colorbar spans rows and columns of subplots. + For example, ``fig.colorbar(loc='b', col=1)`` draws a colorbar + beneath the leftmost column of subplots, and + ``fig.colorbar(loc='b', cols=(1,2))`` draws a colorbar beneath the + left two columns of subplots. By default, the colorbar will span + all rows and columns. space : float or str, optional - As in `~proplot.axes.Axes.panel_axes`, but controls space - between the main subplot grid and the figure panels. + The space between the main subplot grid and the colorbar, or the + space between successively stacked colorbars. If float, units + are inches. If string, units are interpreted by + `~proplot.utils.units`. By default, this is adjusted automatically + in the "tight layout" calculation, or is + ``rc['subplots.panelspace']`` if "tight layout" is turned off. + width : float or str, optional + The colorbar width. If float, units are inches. If string, units + are interpreted by `~proplot.utils.units`. Defaults to + ``rc['colorbar.width']``. *args, **kwargs Passed to `~proplot.axes.Axes.colorbar`. """ if 'cax' in kwargs: return super().colorbar(*args, **kwargs) + elif 'ax' in kwargs: + return kwargs.pop('ax').colorbar(*args, + space=space, width=width, **kwargs) else: - ax = self._add_figure_panel(loc, space=space, width=width, array=None, mode='colorbar') + span = _notNone(span, row, col, rows, cols, None, + names=('span', 'row', 'col', 'rows', 'cols')) + ax = self._add_figure_panel(loc, + space=space, width=width, span=span) return ax.colorbar(*args, loc='_fill', **kwargs) - def legend(self, *args, loc='r', width=None, space=None, **kwargs): + def legend(self, *args, + loc='r', width=None, space=None, + row=None, col=None, rows=None, cols=None, span=None, + **kwargs): """ Draws a legend along the left, right, bottom, or top side of the figure, centered between the leftmost and rightmost (or @@ -1427,13 +1447,46 @@ def legend(self, *args, loc='r', width=None, space=None, **kwargs): Parameters ---------- - loc, width, space - See `~Figure.colorbar`. + loc : str, optional + The legend location. Valid location keys are as follows. + + =========== ===================== + Location Valid keys + =========== ===================== + left edge ``'l'``, ``'left'`` + right edge ``'r'``, ``'right'`` + bottom edge ``'b'``, ``'bottom'`` + top edge ``'t'``, ``'top'`` + =========== ===================== + + row, col, rows, cols : optional + Aliases for `span`. + span : int or (int, int), optional + Describes how the legend spans rows and columns of subplots. + For example, ``fig.legend(loc='b', col=1)`` draws a legend + beneath the leftmost column of subplots, and + ``fig.legend(loc='b', cols=(1,2))`` draws a legend beneath the + left two columns of subplots. By default, the legend will span + all rows and columns. + space : float or str, optional + The space between the main subplot grid and the legend, or the + space between successively stacked colorbars. If float, units + are inches. If string, units are interpreted by + `~proplot.utils.units`. By default, this is adjusted automatically + in the "tight layout" calculation, or is + ``rc['subplots.panelspace']`` if "tight layout" is turned off. *args, **kwargs Passed to `~proplot.axes.Axes.legend`. """ - ax = self._add_figure_panel(loc, space=space, width=width, array=None, mode='legend') - return ax.legend(*args, loc='_fill', **kwargs) + if 'ax' in kwargs: + return kwargs.pop('ax').legend(*args, + space=space, width=width, **kwargs) + else: + span = _notNone(span, row, col, rows, cols, None, + names=('span', 'row', 'col', 'rows', 'cols')) + ax = self._add_figure_panel(loc, + space=space, width=width, span=span) + return ax.legend(*args, loc='_fill', **kwargs) @_counter def draw(self, renderer): @@ -1643,8 +1696,7 @@ def subplots(array=None, ncols=1, nrows=1, Tuple specifying the figure `(width, height)`. width, height : float or str, optional The figure width and height. If float, units are inches. If string, - units are interpreted by `~proplot.utils.units`. For example, - ``width="10cm"`` creates a 10cm wide figure. + units are interpreted by `~proplot.utils.units`. journal : str, optional String name corresponding to an academic journal standard that is used to control the figure width (and height, if specified). Valid names diff --git a/proplot/wrappers.py b/proplot/wrappers.py index 4f230f29e..6cdd626bf 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -2639,9 +2639,9 @@ def colorbar_wrapper(self, maxn_minor = _notNone(maxn_minor, int(length/(0.5*fontsize/72))) # Get locator if tickminor and minorlocator is None: - step = 1 + len(locator)//maxn_minor + step = 1 + len(locator) // max(1, maxn_minor) minorlocator = locator[::step] - step = 1 + len(locator)//maxn + step = 1 + len(locator) // max(1, maxn) locator = locator[::step] # Locator object locator = axistools.Locator(locator, **locator_kw) From c264999ee5c6ed6329d9d39905ee223430cd594b Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Mon, 2 Sep 2019 23:56:38 -0600 Subject: [PATCH 05/28] Return axes_grid of panels, fix _panels_kwargs bug --- proplot/subplots.py | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index 95ad897ac..d7340ba77 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -209,12 +209,8 @@ def __getattr__(self, attr): def null_iterator(*args, **kwargs): return None return null_iterator - # Panels - if all(isinstance(_, (axes_grid, axes.Axes)) - for _ in attrs): - return axes_grid(attrs) # Objects - elif not any(callable(_) for _ in attrs): + if not any(callable(_) for _ in attrs): if len(self) == 1: return attrs[0] else: @@ -231,6 +227,8 @@ def axes_grid_iterator(*args, **kwargs): return ret[0] elif all(res is None for res in ret): return None + elif all(isinstance(res, axes.Axes) for res in ret): + return axes_grid(ret, n=self._n, order=self._order) else: return ret return axes_grid_iterator @@ -752,7 +750,7 @@ def _add_axes_panel(self, ax, side, filled=False, **kwargs): raise ValueError(f'Invalid side {side!r}.') side = _side_translate[s] share, width, space, space_orig = _panels_kwargs(s, - kwargs, filled=filled, figure=False) + filled=filled, figure=False, **kwargs) # Get gridspec and subplotspec indices subplotspec = ax.get_subplotspec() @@ -798,8 +796,8 @@ def _add_figure_panel(self, side, span=None, **kwargs): if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') side = _side_translate[s] - _, width, space, space_orig = _panels_kwargs(s, kwargs, - filled=True, figure=True) + _, width, space, space_orig = _panels_kwargs(s, + filled=True, figure=True, **kwargs) # Get props subplots_kw = self._subplots_kw From 088a5374a3c2ad60b2cc02f67197e2a6c423eb11 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Mon, 2 Sep 2019 23:58:17 -0600 Subject: [PATCH 06/28] Fix axes_grid docstring --- proplot/subplots.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index d7340ba77..dc1834ce9 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -198,9 +198,10 @@ def __getattr__(self, attr): ------- >>> import proplot as plot - ... f, axs = plot.subplots(nrows=2, ncols=2, axcolorbars='b') - ... axs.format(xticks=5) # calls "format" on all subplots in the list - ... axs.bpanel.colorbar(m) # calls "colorbar" on all panels in the axes_grid returned by "axs.bpanel" + ... f, axs = plot.subplots(nrows=2, ncols=2) + ... axs.format(...) # calls "format" on all subplots in the list + ... paxs = axs.panel_axes('r') + ... paxs.format(...) # calls "format" on all panels in the axes_grid returned by "axs.panel_axes" """ attrs = (*(getattr(ax, attr) for ax in self),) # may raise error From bf87d3a8e37a1f77666eb3b269cc6692b50c48f0 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Mon, 2 Sep 2019 23:59:17 -0600 Subject: [PATCH 07/28] Minor --- proplot/subplots.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index dc1834ce9..15db23e51 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -186,7 +186,8 @@ def __getitem__(self, key): return objs def __getattr__(self, attr): - """If the attribute is *callable*, returns a dummy function that loops + """ + If the attribute is *callable*, returns a dummy function that loops through each identically named method, calls them in succession, and returns a tuple of the results. This lets you call arbitrary methods on multiple axes at once! If the `axes_grid` has length ``1``, From cfe7e66484c093c9019dfcdef1a7cad878b32605 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Tue, 3 Sep 2019 00:00:09 -0600 Subject: [PATCH 08/28] axes_grid docstring --- proplot/subplots.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index 15db23e51..eadf3615a 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -192,8 +192,8 @@ def __getattr__(self, attr): returns a tuple of the results. This lets you call arbitrary methods on multiple axes at once! If the `axes_grid` has length ``1``, just returns the single result. If the attribute is *not callable*, - returns an `axes_grid` of identically named attributes for every object - in the list. + returns a tuple of identically named attributes for every object in + the list. Example ------- From 3205230583ba5a72946563aae24462247c139f75 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Tue, 3 Sep 2019 00:25:49 -0600 Subject: [PATCH 09/28] Zoom attribute change --- proplot/axes.py | 14 ++++++-------- proplot/subplots.py | 1 - 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/proplot/axes.py b/proplot/axes.py index 53a6df82d..bb3af176e 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -163,12 +163,12 @@ def __init__(self, *args, number=None, self._lpanels = [] self._rpanels = [] self._tight_bbox = None # bounding boxes are saved - self._zoom = None self._panel_side = None self._panel_parent = None self._panel_filled = False # True when panels "filled" with colorbar/legend - self._inset_zoom = False self._inset_parent = None + self._inset_zoom = False + self._inset_zoom_data = None self._alty_child = None self._altx_child = None self._alty_parent = None @@ -1308,24 +1308,22 @@ def indicate_inset_zoom(self, alpha=None, linewidth=None, color=None, edgecolor= kwargs.update({'linewidth':linewidth, 'edgecolor':edgecolor, 'alpha':alpha}) rectpatch, connects = parent.indicate_inset(rect, self, **kwargs) # Adopt properties from old one - if self._zoom: - rectpatch_old, connects_old = self._zoom + if self._inset_zoom_data: + rectpatch_old, connects_old = self._inset_zoom_data rectpatch.update_from(rectpatch_old) rectpatch_old.set_visible(False) for line,line_old in zip(connects,connects_old): - # Actually want to *preserve* whether line is visible! This - # is automatically determined! visible = line.get_visible() line.update_from(line_old) line.set_visible(visible) line_old.set_visible(False) - # By default linewidth is only applied to box + # Format zoom data else: for line in connects: line.set_linewidth(linewidth) line.set_color(edgecolor) line.set_alpha(alpha) - self._zoom = (rectpatch, connects) + self._inset_zoom_data = (rectpatch, connects) return (rectpatch, connects) def panel_axes(self, side, **kwargs): diff --git a/proplot/subplots.py b/proplot/subplots.py index eadf3615a..1d2a772b4 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -899,7 +899,6 @@ def _adjust_aspect(self): self.set_size_inches(figsize) self._gridspec_main.update(**gridspec_kw) - @_counter def _adjust_tight_layout(self, renderer): """Applies tight layout scaling that permits flexible figure dimensions and preserves panel widths and subplot aspect ratios. From 00bd9ffdc3a59f4e6bd77ec5c5e58b4be06b380a Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Tue, 3 Sep 2019 08:52:44 -0600 Subject: [PATCH 10/28] Auto legend cleanup --- proplot/axes.py | 14 +++++--------- proplot/wrappers.py | 14 ++++++-------- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/proplot/axes.py b/proplot/axes.py index bb3af176e..1d01bcab4 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -173,10 +173,8 @@ def __init__(self, *args, number=None, self._altx_child = None self._alty_parent = None self._altx_parent = None - self._auto_colorbar = {} # stores plot handles for auto colorbar + self._auto_colorbar = {} # stores handles and kwargs for auto colorbar self._auto_legend = {} - self._auto_colorbar_kw = {} # keyword args for auto colorbar() - self._auto_legend_kw = {} # Axis sharing, new text attributes, custom formatting self._spanx = spanx # boolean toggles, whether we want to span axes labels self._spany = spany @@ -210,14 +208,12 @@ def _draw_auto_legends_colorbars(self): """Generate automatic legends and colorbars. Wrapper funcs let user add handles to location lists with successive calls to make successive calls to plotting commands.""" - for loc,handles in self._auto_colorbar.items(): - self.colorbar(handles, **self._auto_colorbar_kw[loc]) - for loc,handles in self._auto_legend.items(): - self.legend(handles, **self._auto_legend_kw[loc]) + for loc,(handles,kwargs) in self._auto_colorbar.items(): + self.colorbar(handles, **kwargs) + for loc,(handles,kwargs) in self._auto_legend.items(): + self.legend(handles, **kwargs) self._auto_legend = {} self._auto_colorbar = {} - self._auto_legend_kw = {} - self._auto_colorbar_kw = {} def _get_side_axes(self, side): """Returns groups of axes in row or column or the single group in the diff --git a/proplot/wrappers.py b/proplot/wrappers.py index 6cdd626bf..b70ced6f4 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -1589,15 +1589,14 @@ def cycle_wrapper(self, func, *args, if not isinstance(loc, str): raise ValueError(f'Invalid on-the-fly location {loc!r}. Must be a preset location. See Axes.colorbar') if loc not in self._auto_colorbar: - self._auto_colorbar[loc] = [] - self._auto_colorbar_kw[loc] = {} - self._auto_colorbar[loc].extend(objs) + self._auto_colorbar[loc] = ([], {}) + self._auto_colorbar[loc][0].extend(objs) # Add keywords if loc != 'fill': colorbar_kw.setdefault('loc', loc) if label_leg: colorbar_kw.setdefault('label', label_leg) - self._auto_colorbar_kw[loc].update(colorbar_kw) + self._auto_colorbar[loc][1].update(colorbar_kw) if legend: # Add handles panel_kw.setdefault('mode', 'legend') @@ -1605,15 +1604,14 @@ def cycle_wrapper(self, func, *args, if not isinstance(loc, str): raise ValueError(f'Invalid on-the-fly location {loc!r}. Must be a preset location. See Axes.legend') if loc not in self._auto_legend: - self._auto_legend[loc] = [] - self._auto_legend_kw[loc] = {} - self._auto_legend[loc].extend(objs) + self._auto_legend[loc] = ([], {}) + self._auto_legend[loc][0].extend(objs) # Add keywords if loc != 'fill': legend_kw.setdefault('loc', loc) if label_leg: legend_kw.setdefault('label', label_leg) - self._auto_legend_kw[loc].update(legend_kw) + self._auto_legend[loc][1].update(legend_kw) # Return # WARNING: Make sure plot always returns tuple of objects, and bar always From 25934db4e01d7cca697ef89240f9850aa34fb079 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Tue, 3 Sep 2019 09:00:18 -0600 Subject: [PATCH 11/28] Comments --- proplot/subplots.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index 1d2a772b4..7cec8679f 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -740,9 +740,6 @@ def __init__(self, @_counter def _add_axes_panel(self, ax, side, filled=False, **kwargs): """Hidden method that powers `~proplot.axes.panel_axes`.""" - # Redirect to main axes, e.g. if want to draw outer colorbar or legend - # from data plotted in a panel or inset axes - ax = ax._panel_parent or ax # Interpret args # NOTE: Axis sharing not implemented for figure panels, 99% of the # time this is just used as construct for adding global colorbars and @@ -750,6 +747,7 @@ def _add_axes_panel(self, ax, side, filled=False, **kwargs): s = side[0] if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') + ax = ax._panel_parent or ax # redirect to main axes side = _side_translate[s] share, width, space, space_orig = _panels_kwargs(s, filled=filled, figure=False, **kwargs) @@ -793,7 +791,7 @@ def _add_axes_panel(self, ax, side, filled=False, **kwargs): def _add_figure_panel(self, side, span=None, **kwargs): """Adds figure panels. Also modifies the panel attribute stored on the figure to include these panels.""" - # Get default panel args + # Interpret args s = side[0] if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') @@ -809,6 +807,7 @@ def _add_figure_panel(self, side, span=None, **kwargs): panels, nacross = subplots_kw['wpanels'], subplots_kw['nrows'] array = getattr(self, '_' + s + 'array') npanels, nalong = array.shape + # Check span array span = _notNone(span, (1, nalong)) if not np.iterable(span) or len(span)==1: @@ -819,11 +818,10 @@ def _add_figure_panel(self, side, span=None, **kwargs): raise ValueError(f'Invalid coordinates in span={span!r}. Coordinates must satisfy 1 <= c <= {nalong}.') start, stop = span[0] - 1, span[1] # zero-indexed - # See if there is room for panel on the figure + # See if there is room for panel in current figure panels # The 'array' is an array of boolean values, where each row corresponds - # to another figure panel, moving toward the outside, and - # We use add to panels toward the outside by appending rows to boolean - # arrays indicating which main axes rows and columns are occupied + # to another figure panel, moving toward the outside, and boolean + # True indicates the slot has been filled iratio = (-1 if s in 'lt' else nacross) # default vals for i in range(npanels): if not any(array[i,start:stop]): @@ -839,8 +837,7 @@ def _add_figure_panel(self, side, span=None, **kwargs): # npanels=2, i=1 --> iratio=nacross-1 iratio = nacross - (npanels - i) break - # Add to array, since we are adding another panel - if iratio in (-1, nacross): + if iratio in (-1, nacross): # add to array iarray = np.zeros((1, nalong), dtype=bool) iarray[0,start:stop] = True array = np.concatenate((array, iarray), axis=0) From 73dd02cfad66ceb38700f64a1e56990a479af603 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Tue, 3 Sep 2019 09:08:14 -0600 Subject: [PATCH 12/28] Better 'span' fig panel aliases --- proplot/subplots.py | 38 ++++++++++++++++++++++++++------------ 1 file changed, 26 insertions(+), 12 deletions(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index 7cec8679f..4217eca6d 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -788,16 +788,28 @@ def _add_axes_panel(self, ax, side, filled=False, **kwargs): return pax - def _add_figure_panel(self, side, span=None, **kwargs): + def _add_figure_panel(self, side, + span=None, row=None, col=None, rows=None, cols=None, + **kwargs): """Adds figure panels. Also modifies the panel attribute stored on the figure to include these panels.""" - # Interpret args + # Interpret args and enforce sensible keyword args s = side[0] if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') side = _side_translate[s] _, width, space, space_orig = _panels_kwargs(s, filled=True, figure=True, **kwargs) + if s in 'lr': + for key,value in (('col',col),('cols',cols)): + if value is not None: + raise ValueError(f'Invalid keyword arg {key!r} for figure panel on side {side!r}.') + span = _notNone(span, row, rows, None, names=('span', 'row', 'rows')) + else: + for key,value in (('row',row),('rows',rows)): + if value is not None: + raise ValueError(f'Invalid keyword arg {key!r} for figure panel on side {side!r}.') + span = _notNone(span, col, cols, None, names=('span', 'col', 'cols')) # Get props subplots_kw = self._subplots_kw @@ -1397,8 +1409,10 @@ def colorbar(self, *args, top edge ``'t'``, ``'top'`` =========== ===================== - row, col, rows, cols : optional - Aliases for `span`. + row, rows : optional + Aliases for `span` for panels on the left or right side. + col, cols : optional + Aliases for `span` for panels on the top or bottom side. span : int or (int, int), optional Describes how the colorbar spans rows and columns of subplots. For example, ``fig.colorbar(loc='b', col=1)`` draws a colorbar @@ -1426,10 +1440,9 @@ def colorbar(self, *args, return kwargs.pop('ax').colorbar(*args, space=space, width=width, **kwargs) else: - span = _notNone(span, row, col, rows, cols, None, - names=('span', 'row', 'col', 'rows', 'cols')) ax = self._add_figure_panel(loc, - space=space, width=width, span=span) + space=space, width=width, span=span, + row=row, col=col, rows=rows, cols=cols) return ax.colorbar(*args, loc='_fill', **kwargs) def legend(self, *args, @@ -1455,8 +1468,10 @@ def legend(self, *args, top edge ``'t'``, ``'top'`` =========== ===================== - row, col, rows, cols : optional - Aliases for `span`. + row, rows : optional + Aliases for `span` for panels on the left or right side. + col, cols : optional + Aliases for `span` for panels on the top or bottom side. span : int or (int, int), optional Describes how the legend spans rows and columns of subplots. For example, ``fig.legend(loc='b', col=1)`` draws a legend @@ -1478,10 +1493,9 @@ def legend(self, *args, return kwargs.pop('ax').legend(*args, space=space, width=width, **kwargs) else: - span = _notNone(span, row, col, rows, cols, None, - names=('span', 'row', 'col', 'rows', 'cols')) ax = self._add_figure_panel(loc, - space=space, width=width, span=span) + space=space, width=width, span=span, + row=row, col=col, rows=rows, cols=cols) return ax.legend(*args, loc='_fill', **kwargs) @_counter From 9254346ba34e1ad1df3c0d23ecfb70eb4328324d Mon Sep 17 00:00:00 2001 From: "Riley X. Brady" Date: Wed, 4 Sep 2019 15:09:08 -0600 Subject: [PATCH 13/28] Add AAAS to journals; fix bug in pulling their dims --- proplot/subplots.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index a2c4ed149..240703600 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -1485,6 +1485,8 @@ def _journals(journal): 'agu2': ('190mm', '115mm'), 'agu3': ('95mm', '230mm'), 'agu4': ('190mm', '230mm'), + 'aaas1': '5.5cm', # AAAS (e.g., Science) 1 column + 'aaas2': '12cm', # AAAS 2 column } value = table.get(journal, None) if value is None: @@ -1494,7 +1496,7 @@ def _journals(journal): width, height = None, None try: width, height = value - except TypeError: + except ValueError: width = value return width, height From 32c4cc8ede5d98dd479145f5db518cf1bb845c4c Mon Sep 17 00:00:00 2001 From: "Riley X. Brady" Date: Wed, 4 Sep 2019 15:20:32 -0600 Subject: [PATCH 14/28] Move journal dictionary to top; add testing for journals --- CHANGELOG.rst | 11 +++++++++- docs/conf.py | 5 +++++ proplot/subplots.py | 40 +++++++++++++++++++--------------- proplot/tests/test_journals.py | 11 ++++++++++ 4 files changed, 48 insertions(+), 19 deletions(-) create mode 100644 proplot/tests/test_journals.py diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 96e6c9b2c..905065882 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ +================= Changelog History ================= ProPlot v1.0.0 --------------- +============== First official release. Coming soon! Future changes and releases will be documented. + +Internals/Minor Fixes +--------------------- +- Add AAAS journal specifications to ``journal`` keyword for ``proplot.subplots()``, fix bug breaking on certain journals, add testing. (:pr:`30`) `Riley X. Brady`_. + + +.. _`Luke Davis`: https://github.com/lukelbd +.. _`Riley X. Brady`: https://github.com/bradyrx diff --git a/docs/conf.py b/docs/conf.py index e2817f2e1..cc92d3360 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -61,6 +61,11 @@ # 'matplotlib.sphinxext.plot_directive', # see: https://matplotlib.org/sampledoc/extensions.html ] +extlinks = { + 'issue': ('https://github.com/lukelbd/proplot/issues/%s', 'GH#'), + 'pr': ('https://github.com/lukelbd/proplot/pull/%s', 'GH#'), +} + # Do not run doctest tests, these are just to show syntax and expected # output may be graphical doctest_test_doctest_blocks = '' diff --git a/proplot/subplots.py b/proplot/subplots.py index 240703600..cb0309322 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -63,6 +63,24 @@ 't':'top', } +# Dimensions of figures for common journals +JOURNAL_SPECS = { + 'pnas1': '8.7cm', # if 1 number specified, this is a tuple + 'pnas2': '11.4cm', + 'pnas3': '17.8cm', + 'ams1': 3.2, # spec is in inches + 'ams2': 4.5, + 'ams3': 5.5, + 'ams4': 6.5, + 'agu1': ('95mm', '115mm'), + 'agu2': ('190mm', '115mm'), + 'agu3': ('95mm', '230mm'), + 'agu4': ('190mm', '230mm'), + 'aaas1': '5.5cm', # AAAS (e.g., Science) 1 column + 'aaas2': '12cm', # AAAS 2 column + } + + #-----------------------------------------------------------------------------# # Miscellaneous stuff #-----------------------------------------------------------------------------# @@ -1473,30 +1491,16 @@ def _iter_axes(self): #-----------------------------------------------------------------------------# def _journals(journal): """Journal sizes for figures.""" - table = { - 'pnas1': '8.7cm', # if 1 number specified, this is a tuple - 'pnas2': '11.4cm', - 'pnas3': '17.8cm', - 'ams1': 3.2, # spec is in inches - 'ams2': 4.5, - 'ams3': 5.5, - 'ams4': 6.5, - 'agu1': ('95mm', '115mm'), - 'agu2': ('190mm', '115mm'), - 'agu3': ('95mm', '230mm'), - 'agu4': ('190mm', '230mm'), - 'aaas1': '5.5cm', # AAAS (e.g., Science) 1 column - 'aaas2': '12cm', # AAAS 2 column - } - value = table.get(journal, None) + # Get dimensions for figure from common journals. + value = JOURNAL_SPECS.get(journal, None) if value is None: raise ValueError(f'Unknown journal figure size specifier {journal!r}. ' + - 'Current options are: ' + ', '.join(table.keys())) + 'Current options are: ' + ', '.join(JOURNAL_SPECS.keys())) # Return width, and optionally also the height width, height = None, None try: width, height = value - except ValueError: + except (TypeError, ValueError): width = value return width, height diff --git a/proplot/tests/test_journals.py b/proplot/tests/test_journals.py new file mode 100644 index 000000000..7bbd8b01e --- /dev/null +++ b/proplot/tests/test_journals.py @@ -0,0 +1,11 @@ +import pytest + +import proplot as plot +from proplot.subplots import JOURNAL_SPECS + + +# Loop through all available journals. +@pytest.mark.parametrize('journal', JOURNAL_SPECS.keys()) +def test_journal_subplots(journal): + """Tests that subplots can be generated with journal specifications.""" + f, axs = plot.subplots(journal=journal) From 7b6e4e0bdab5bcaba43610b1659446df2f2dcdce Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 11:33:04 -0600 Subject: [PATCH 15/28] Misc bugfixes and cleanup --- proplot/axes.py | 12 ++++------ proplot/styletools.py | 2 +- proplot/subplots.py | 25 ++++++++++++++++---- proplot/wrappers.py | 54 +++++++++++++++++++++++++------------------ 4 files changed, 58 insertions(+), 35 deletions(-) diff --git a/proplot/axes.py b/proplot/axes.py index 1d01bcab4..ac1aa4a0b 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -119,8 +119,6 @@ def _abc(i): class Axes(maxes.Axes): """Lowest-level axes subclass. Handles titles and axis sharing. Adds several new methods and overrides existing ones.""" - name = 'base' - """The registered projection name.""" def __init__(self, *args, number=None, sharex=None, sharey=None, sharex_level=0, sharey_level=0, spanx=None, spany=None, alignx=None, aligny=None, @@ -2097,8 +2095,8 @@ def altx(self, *args, **kwargs): if self._altx_parent: raise ValueError('This *is* a twin axes!') with self.figure._unlock(): - ax = self._make_twin_axes(sharey=self, projection=self.name) - ax.set_autoscaley_on(self.get_autoscaley_on()) # shared axes must have matching autoscale + ax = self._make_twin_axes(sharey=self, projection='cartesian') + # ax.set_autoscaley_on(self.get_autoscaley_on()) # shared axes must have matching autoscale ax.grid(False) self._altx_child = ax ax._altx_parent = self @@ -2117,8 +2115,8 @@ def alty(self): if self._alty_parent: raise ValueError('This *is* a twin axes!') with self.figure._unlock(): - ax = self._make_twin_axes(sharex=self, projection=self.name) - ax.set_autoscalex_on(self.get_autoscalex_on()) # shared axes must have matching autoscale + ax = self._make_twin_axes(sharex=self, projection='cartesian') + # ax.set_autoscalex_on(self.get_autoscalex_on()) # shared axes must have matching autoscale ax.grid(False) self._alty_child = ax ax._alty_parent = self @@ -3216,7 +3214,7 @@ def format(self, *, patch_kw=None, **kwargs): BasemapAxes.format.__doc__ = _projection_format_docstring # Register the projections -mproj.register_projection(Axes) +# TODO: Remove BasemapAxes!!! Cartopy will support gridline labels soon. mproj.register_projection(PolarAxes) mproj.register_projection(CartesianAxes) mproj.register_projection(BasemapAxes) diff --git a/proplot/styletools.py b/proplot/styletools.py index 42571da1f..57f69b639 100644 --- a/proplot/styletools.py +++ b/proplot/styletools.py @@ -1600,7 +1600,7 @@ def monochrome_cmap(color, fade, reverse=False, space='hsl', name='no_name', **k #-----------------------------------------------------------------------------# # Return arbitrary normalizer #-----------------------------------------------------------------------------# -def Norm(norm, levels=None, values=None, **kwargs): +def Norm(norm, levels=None, **kwargs): """ Returns an arbitrary `~matplotlib.colors.Normalize` instance, used to interpret the `norm` and `norm_kw` arguments when passed to any plotting diff --git a/proplot/subplots.py b/proplot/subplots.py index 4217eca6d..44ab249db 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -237,6 +237,23 @@ def axes_grid_iterator(*args, **kwargs): # Mixed raise AttributeError(f'Found mixed types for attribute {attr!r}.') + # TODO! No more putting panels, legends, colorbars on the SubplotSpec, + # put them in the margin and increase default space + # def colorbar(self, loc=None): + # """Draws a colorbar that spans axes in the selected range.""" + # for ax in self: + # pass + # + # def legend(self, loc=None): + # """Draws a legend that spans axes in the selected range.""" + # for ax in self: + # pass + # + # def text(self, loc=None): + # """Draws text that spans axes in the selected range.""" + # for ax in self: + # pass + #-----------------------------------------------------------------------------# # Gridspec classes #-----------------------------------------------------------------------------# @@ -1307,15 +1324,15 @@ def _update_axislabels(self, axis=None, **kwargs): return # Update label on this axes axis.label.update(kwargs) + kwargs.pop('color', None) # Defer to parent (main) axes if possible, then get the axes # shared by that parent # TODO: Share panels in successive stacks, but share short axes # just like sharing long axes ax = axis.axes - sax = getattr(ax, '_share' + x, None) - while isinstance(ax, axes.PanelAxes) and sax is not None: - ax, sax = sax, getattr(sax, '_share' + x, None) + ax = ax._panel_parent or ax + ax = getattr(ax, '_share' + x) or ax # Apply to spanning axes and their panels axs = [ax] @@ -1325,7 +1342,7 @@ def _update_axislabels(self, axis=None, **kwargs): axs = ax._get_side_axes(s) for ax in axs: getattr(ax, x + 'axis').label.update(kwargs) # apply to main axes - pax = getattr(ax, '_share' + x, None) + pax = getattr(ax, '_share' + x) if pax is not None: # apply to panel? getattr(pax, x + 'axis').label.update(kwargs) diff --git a/proplot/wrappers.py b/proplot/wrappers.py index b70ced6f4..e643a65ac 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -90,6 +90,7 @@ def _load_objects(): _map_disabled_methods = ( # These are obvious # TODO: Error bars? Will they work? Also bar and barh can be used w/ polar + 'twinx', 'twiny', 'matshow', 'imshow', 'spy', # don't disable 'bar' or 'barh', can be used in polar plots 'hist', 'hist2d', 'boxplot', 'violinplot', 'step', 'stem', # Look into these @@ -1629,7 +1630,7 @@ def cycle_wrapper(self, func, *args, @_expand_methods_list def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, extend='neither', norm=None, norm_kw=None, - N=None, levels=None, values=None, vmin=None, vmax=None, + N=None, levels=None, values=None, centers=None, vmin=None, vmax=None, locator=None, symmetric=False, locator_kw=None, edgefix=None, labels=False, labels_kw=None, fmt=None, precision=2, colorbar=False, colorbar_kw=None, panel_kw=None, @@ -1659,7 +1660,7 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, extend : {'neither', 'min', 'max', 'both'}, optional Where to assign unique colors to out-of-bounds data and draw "extensions" (triangles, by default) on the colorbar. - N, levels : int or list of float, optional + levels, N : int or list of float, optional The number of level edges, or a list of level edges. If the former, `locator` is used to generate this many levels at "nice" intervals. Defaults to ``rc['image.levels']``. @@ -1668,7 +1669,7 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, `~matplotlib.axes.Axes.pcolormesh`, this means they now accept the `levels` keyword arg. You can now discretize your colors in a ``pcolor`` plot just like with ``contourf``. - values : int or list of float, optional + values, centers : int or list of float, optional The number of level centers, or a list of level centers. If provided, levels are inferred using `~proplot.utils.edges`. This will override any `levels` input. @@ -1771,14 +1772,16 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, labels_kw = labels_kw or {} colorbar_kw = colorbar_kw or {} panel_kw = panel_kw or {} - vmin = _notNone(vmin, norm_kw.pop('vmin', None)) - vmax = _notNone(vmax, norm_kw.pop('vmax', None)) # Parse args # Disable edgefix=True for certain keyword combos e.g. if user wants # white lines around their pcolor mesh. name = func.__name__ if not args: return func(*args, **kwargs) + vmin = _notNone(vmin, norm_kw.pop('vmin', None), None, names=('vmin', 'norm_kw={"vmin":value}')) + vmax = _notNone(vmax, norm_kw.pop('vmax', None), None, names=('vmax', 'norm_kw={"vmax":value}')) + levels = _notNone(N, levels, norm_kw.pop('levels', None), rc['image.levels'], names=('N', 'levels', 'norm_kw={"levels":value}')) + values = _notNone(values, centers, None, names=('values', 'centers')) colors = _notNone(color, colors, edgecolor, edgecolors, None, names=('color', 'colors', 'edgecolor', 'edgecolors')) linewidths = _notNone(lw, linewidth, linewidths, None, names=('lw', 'linewidth', 'linewidths')) linestyles = _notNone(ls, linestyle, linestyles, None, names=('ls', 'linestyle', 'linestyles')) @@ -1798,29 +1801,34 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, for key,val in (('levels',levels),('values',values)): if not np.iterable(val): continue + if 'contour' in name and 'contourf' not in name: + continue if len(val) < 2 or any(np.diff(val) <= 0): raise ValueError(f'{key!r} must be monotonically increasing and at least length 2, got {val}.') # Get level edges from level centers - # Make sure values are *averages* of encompassing levels, so that tick - # marks appear in the center of the colorbar level. if values is not None: if isinstance(values, Number): levels = values + 1 elif np.iterable(values): + # Plotting command accepts a 'values' keyword arg if name in ('cmapline',): kwargs['values'] = values + # Try to generate levels such that a LinearSegmentedNorm will + # place values ticks right at the center of each colorbar level if norm is None or norm in ('segments','segmented'): levels = [values[0] - (values[1]-values[0])/2] # reasonable starting point for i,val in enumerate(values): levels.append(2*val - levels[-1]) if any(np.diff(levels) <= 0): # algorithm failed, default to this levels = utils.edges(values) + # Generate levels by finding in-between points in the + # normalized numeric space else: - norm_tmp = styletools.Norm(norm, **norm_kw) - levels = norm_tmp.inverse(utils.edges(norm_tmp(values))) + inorm = styletools.Norm(norm, **norm_kw) + levels = inorm.inverse(utils.edges(inorm(values))) else: - raise ValueError('Unexpected values input {values!r}. Must be integer or list of numbers.') + raise ValueError(f'Unexpected input values={values!r}. Must be integer or list of numbers.') # Data limits used for normalizer Z = ma.masked_invalid(args[-1], copy=False) @@ -1832,7 +1840,7 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, zmin, zmax = 0, 1 # Input colormap, for methods that accept a colormap and normalizer - if not name[-7:] == 'contour': # contour, tricontour, i.e. not a method where cmap is optional + if not ('contour' in name and 'contourf' not in name): # contour, tricontour, i.e. not a method where cmap is optional cmap = _notNone(cmap, rc['image.cmap']) if cmap is not None: # Get colormap object @@ -1845,22 +1853,22 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, # Get default normalizer # Only use LinearSegmentedNorm if necessary, because it is slow - if norm is None and name not in ('hexbin',): - if not np.iterable(levels): - norm = 'linear' - else: - diff = np.diff(levels) - eps = diff.mean()/1e3 - if (np.abs(np.diff(diff)) >= eps).any(): - norm = 'segmented' - else: + if name not in ('hexbin',): + if norm is None: + if not np.iterable(levels) or len(levels) == 1: norm = 'linear' - if norm is not None: - norm = styletools.Norm(norm, levels=levels, **norm_kw) + else: + diff = np.diff(levels) + eps = diff.mean()/1e3 + if (np.abs(np.diff(diff)) >= eps).any(): + norm = 'segmented' + norm_kw.setdefault('levels', levels) + else: + norm = 'linear' + norm = styletools.Norm(norm, **norm_kw) # Get default levels # TODO: Add kernel density plot to hexbin! - levels = _notNone(N, levels, rc['image.levels'], names=('N', 'levels')) if isinstance(levels, Number): # Cannot infer counts a priori, so do nothing if name in ('hexbin',): From b8df9e1f05072cf9549753fb152027ceaaabc705 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 11:53:56 -0600 Subject: [PATCH 16/28] Panels bugfix --- proplot/axes.py | 2 +- proplot/subplots.py | 12 +++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/proplot/axes.py b/proplot/axes.py index ac1aa4a0b..0daf52bfe 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -1083,7 +1083,7 @@ def colorbar(self, *args, loc=None, pad=None, warnings.warn(f'Orientation for inset colorbars must be horizontal, ignoring orient={orient!r}.') ticklocation = kwargs.pop('tickloc', None) ticklocation = kwargs.pop('ticklocation', None) or ticklocation - if any(loc is not None and ticklocation != 'bottom'): + if ticklocation is not None and ticklocation != 'bottom': warnings.warn(f'Inset colorbars can only have ticks on the bottom.') kwargs.update({'orientation':'horizontal', 'ticklocation':'bottom'}) kwargs.setdefault('maxn', 5) diff --git a/proplot/subplots.py b/proplot/subplots.py index 44ab249db..c8be29cc1 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -775,13 +775,13 @@ def _add_axes_panel(self, ax, side, filled=False, **kwargs): pgrid = getattr(ax, '_' + s + 'panels') offset = (len(pgrid)*bool(pgrid)) + 1 if s in 'lr': + iratio = (col1 - offset if s == 'l' else col2 + offset) idx1 = slice(row1, row2 + 1) - idx2 = (col1 - offset if s == 'l' else col2 + offset) - iratio = idx2 + idx2 = max(0, iratio) else: - idx1 = (row1 - offset if s == 't' else row2 + offset) + iratio = (row1 - offset if s == 't' else row2 + offset) + idx1 = max(0, iratio) idx2 = slice(col1, col2 + 1) - iratio = idx1 gridspec = self._insert_row_column(side, iratio, width, space, space_orig, figure=False, ) @@ -995,7 +995,9 @@ def _adjust_tight_layout(self, renderer): idx1, = np.where(filt & filt1) idx2, = np.where(filt & filt2) if idx1.size > 1 or idx2.size > 2: - raise RuntimeError('This should never happen.') + warnings.warn('This should never happen.') + continue + # raise RuntimeError('This should never happen.') elif not idx1.size or not idx2.size: continue idx1, idx2 = idx1[0], idx2[0] From c67c3f847231079c8e9ea16670996bc8da5e097e Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 11:54:59 -0600 Subject: [PATCH 17/28] Remove print statement --- proplot/wrappers.py | 1 - 1 file changed, 1 deletion(-) diff --git a/proplot/wrappers.py b/proplot/wrappers.py index e643a65ac..b6b11fd09 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -1513,7 +1513,6 @@ def cycle_wrapper(self, func, *args, objs = [] ncols = 1 label_leg = None # for colorbar or legend - print('hi!!!', values, labels) labels = _notNone(values, labels, label, None, names=('values', 'labels', 'label')) stacked = kwargs.pop('stacked', False) if name in ('pie','boxplot','violinplot'): From 5643867879c962d5c3dbc1242438af75919590b1 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 14:35:48 -0600 Subject: [PATCH 18/28] Update documentation to reflect new colorbars, legends usage, add inset axes and panel axes demos to Cartesian axes section, misc panel bugfixes --- docs/tutorial/tutorial_100_0.svg | 2852 - docs/tutorial/tutorial_101_0.svg | 5655 + docs/tutorial/tutorial_104_0.svg | 2043 + docs/tutorial/tutorial_105_0.svg | 7221 +- ...{tutorial_110_0.svg => tutorial_106_0.svg} | 0 docs/tutorial/tutorial_108_0.svg | 20558 +- docs/tutorial/tutorial_109_0.svg | 2002 - docs/tutorial/tutorial_112_0.svg | 28153 +- ...{tutorial_116_1.svg => tutorial_112_1.svg} | 0 ...{tutorial_118_0.svg => tutorial_114_0.svg} | 0 ...{tutorial_118_1.svg => tutorial_114_1.svg} | 0 docs/tutorial/tutorial_116_0.svg | 9760 - docs/tutorial/tutorial_117_1.svg | 193147 +++++++++++++ ...{tutorial_123_0.svg => tutorial_119_0.svg} | 0 ...{tutorial_123_1.svg => tutorial_119_1.svg} | 0 ...{tutorial_125_0.svg => tutorial_121_0.svg} | 0 docs/tutorial/tutorial_121_1.svg | 210959 ++------------- docs/tutorial/tutorial_125_1.svg | 19176 -- ...{tutorial_130_0.svg => tutorial_126_0.svg} | 0 docs/tutorial/tutorial_129_0.svg | 2613 + docs/tutorial/tutorial_12_0.svg | 5551 + docs/tutorial/tutorial_12_1.svg | 3574 - ...{tutorial_135_0.svg => tutorial_131_0.svg} | 0 docs/tutorial/tutorial_133_0.svg | 2787 +- docs/tutorial/tutorial_137_0.svg | 1548 - ...{tutorial_142_0.svg => tutorial_138_0.svg} | 0 ...{tutorial_142_1.svg => tutorial_138_1.svg} | 0 ...{tutorial_145_0.svg => tutorial_141_0.svg} | 0 ...{tutorial_148_0.svg => tutorial_144_0.svg} | 0 ...{tutorial_153_0.svg => tutorial_149_0.svg} | 0 docs/tutorial/tutorial_14_0.svg | 4188 + docs/tutorial/tutorial_150_0.svg | 12617 + ...{tutorial_156_0.svg => tutorial_152_0.svg} | 0 docs/tutorial/tutorial_154_0.svg | 16962 +- ...{tutorial_161_0.svg => tutorial_157_0.svg} | 0 ...{tutorial_161_1.svg => tutorial_157_1.svg} | 0 docs/tutorial/tutorial_158_0.svg | 6313 - docs/tutorial/tutorial_15_0.svg | 7190 + ...{tutorial_164_0.svg => tutorial_160_0.svg} | 0 ...{tutorial_167_0.svg => tutorial_163_0.svg} | 0 ...{tutorial_170_0.svg => tutorial_166_0.svg} | 0 ...{tutorial_173_1.svg => tutorial_169_1.svg} | 0 docs/tutorial/tutorial_16_2.svg | 3622 - ...{tutorial_176_1.svg => tutorial_172_1.svg} | 0 ...{tutorial_179_0.svg => tutorial_175_0.svg} | 0 .../{tutorial_88_1.svg => tutorial_17_1.svg} | 24840 +- docs/tutorial/tutorial_18_0.svg | 15698 +- docs/tutorial/tutorial_21_0.svg | 8830 +- docs/tutorial/tutorial_22_0.svg | 6561 +- docs/tutorial/tutorial_26_0.svg | 6927 - docs/tutorial/tutorial_26_2.svg | 8417 +- docs/tutorial/tutorial_28_0.svg | 6331 + docs/tutorial/tutorial_29_0.svg | 9124 - docs/tutorial/tutorial_31_0.svg | 5321 + .../{tutorial_21_1.svg => tutorial_31_1.svg} | 0 docs/tutorial/tutorial_32_0.svg | 5318 +- .../{tutorial_23_0.svg => tutorial_33_0.svg} | 0 docs/tutorial/tutorial_36_0.svg | 9118 +- .../{tutorial_26_1.svg => tutorial_36_1.svg} | 0 docs/tutorial/tutorial_36_2.svg | 6733 + .../{tutorial_26_3.svg => tutorial_36_3.svg} | 0 .../{tutorial_27_0.svg => tutorial_37_0.svg} | 0 .../{tutorial_27_1.svg => tutorial_37_1.svg} | 0 docs/tutorial/tutorial_39_0.svg | 11516 +- docs/tutorial/tutorial_42_0.svg | 2000 + docs/tutorial/tutorial_44_1.svg | 5333 +- docs/tutorial/tutorial_48_0.svg | 4111 + docs/tutorial/tutorial_49_0.svg | 5195 - docs/tutorial/tutorial_51_0.svg | 2714 + .../{tutorial_41_0.svg => tutorial_53_0.svg} | 0 docs/tutorial/tutorial_56_1.svg | 3239 + .../{tutorial_45_0.svg => tutorial_57_0.svg} | 0 .../{tutorial_46_0.svg => tutorial_58_0.svg} | 0 docs/tutorial/tutorial_61_0.svg | 15243 +- docs/tutorial/tutorial_64_0.svg | 62617 ----- .../{tutorial_52_1.svg => tutorial_64_1.svg} | 0 .../{tutorial_52_2.svg => tutorial_64_2.svg} | 0 .../{tutorial_53_1.svg => tutorial_65_1.svg} | 0 docs/tutorial/tutorial_67_0.svg | 10409 +- docs/tutorial/tutorial_68_0.svg | 13254 + docs/tutorial/tutorial_70_0.svg | 3476 + .../{tutorial_58_3.svg => tutorial_75_3.svg} | 0 .../{tutorial_58_4.svg => tutorial_75_4.svg} | 0 docs/tutorial/tutorial_78_0.svg | 10708 + .../{tutorial_61_1.svg => tutorial_78_1.svg} | 0 docs/tutorial/tutorial_81_0.svg | 66922 ++++- docs/tutorial/tutorial_84_0.svg | 10668 +- .../{tutorial_67_1.svg => tutorial_84_1.svg} | 0 docs/tutorial/tutorial_85_0.svg | 10979 - .../{tutorial_70_1.svg => tutorial_87_1.svg} | 0 docs/tutorial/tutorial_89_0.svg | 11768 - .../{tutorial_73_0.svg => tutorial_90_0.svg} | 0 docs/tutorial/tutorial_91_0.svg | 8595 - .../{tutorial_76_0.svg => tutorial_93_0.svg} | 0 docs/tutorial/tutorial_94_0.svg | 3839 - docs/tutorial/tutorial_96_0.svg | 4613 + docs/tutorial/tutorial_97_0.svg | 5338 - docs/tutorial1.rst | 341 +- docs/tutorial2.rst | 108 +- docs/tutorial3.rst | 91 +- docs/tutorial4.rst | 808 +- docs/tutorial5.rst | 832 +- proplot/axes.py | 27 +- proplot/styletools.py | 4 + proplot/subplots.py | 30 +- 105 files changed, 483279 insertions(+), 473208 deletions(-) delete mode 100644 docs/tutorial/tutorial_100_0.svg create mode 100644 docs/tutorial/tutorial_101_0.svg create mode 100644 docs/tutorial/tutorial_104_0.svg rename docs/tutorial/{tutorial_110_0.svg => tutorial_106_0.svg} (100%) delete mode 100644 docs/tutorial/tutorial_109_0.svg rename docs/tutorial/{tutorial_116_1.svg => tutorial_112_1.svg} (100%) rename docs/tutorial/{tutorial_118_0.svg => tutorial_114_0.svg} (100%) rename docs/tutorial/{tutorial_118_1.svg => tutorial_114_1.svg} (100%) delete mode 100644 docs/tutorial/tutorial_116_0.svg create mode 100644 docs/tutorial/tutorial_117_1.svg rename docs/tutorial/{tutorial_123_0.svg => tutorial_119_0.svg} (100%) rename docs/tutorial/{tutorial_123_1.svg => tutorial_119_1.svg} (100%) rename docs/tutorial/{tutorial_125_0.svg => tutorial_121_0.svg} (100%) delete mode 100644 docs/tutorial/tutorial_125_1.svg rename docs/tutorial/{tutorial_130_0.svg => tutorial_126_0.svg} (100%) create mode 100644 docs/tutorial/tutorial_129_0.svg create mode 100644 docs/tutorial/tutorial_12_0.svg delete mode 100644 docs/tutorial/tutorial_12_1.svg rename docs/tutorial/{tutorial_135_0.svg => tutorial_131_0.svg} (100%) delete mode 100644 docs/tutorial/tutorial_137_0.svg rename docs/tutorial/{tutorial_142_0.svg => tutorial_138_0.svg} (100%) rename docs/tutorial/{tutorial_142_1.svg => tutorial_138_1.svg} (100%) rename docs/tutorial/{tutorial_145_0.svg => tutorial_141_0.svg} (100%) rename docs/tutorial/{tutorial_148_0.svg => tutorial_144_0.svg} (100%) rename docs/tutorial/{tutorial_153_0.svg => tutorial_149_0.svg} (100%) create mode 100644 docs/tutorial/tutorial_14_0.svg create mode 100644 docs/tutorial/tutorial_150_0.svg rename docs/tutorial/{tutorial_156_0.svg => tutorial_152_0.svg} (100%) rename docs/tutorial/{tutorial_161_0.svg => tutorial_157_0.svg} (100%) rename docs/tutorial/{tutorial_161_1.svg => tutorial_157_1.svg} (100%) delete mode 100644 docs/tutorial/tutorial_158_0.svg create mode 100644 docs/tutorial/tutorial_15_0.svg rename docs/tutorial/{tutorial_164_0.svg => tutorial_160_0.svg} (100%) rename docs/tutorial/{tutorial_167_0.svg => tutorial_163_0.svg} (100%) rename docs/tutorial/{tutorial_170_0.svg => tutorial_166_0.svg} (100%) rename docs/tutorial/{tutorial_173_1.svg => tutorial_169_1.svg} (100%) delete mode 100644 docs/tutorial/tutorial_16_2.svg rename docs/tutorial/{tutorial_176_1.svg => tutorial_172_1.svg} (100%) rename docs/tutorial/{tutorial_179_0.svg => tutorial_175_0.svg} (100%) rename docs/tutorial/{tutorial_88_1.svg => tutorial_17_1.svg} (58%) delete mode 100644 docs/tutorial/tutorial_26_0.svg create mode 100644 docs/tutorial/tutorial_28_0.svg delete mode 100644 docs/tutorial/tutorial_29_0.svg create mode 100644 docs/tutorial/tutorial_31_0.svg rename docs/tutorial/{tutorial_21_1.svg => tutorial_31_1.svg} (100%) rename docs/tutorial/{tutorial_23_0.svg => tutorial_33_0.svg} (100%) rename docs/tutorial/{tutorial_26_1.svg => tutorial_36_1.svg} (100%) create mode 100644 docs/tutorial/tutorial_36_2.svg rename docs/tutorial/{tutorial_26_3.svg => tutorial_36_3.svg} (100%) rename docs/tutorial/{tutorial_27_0.svg => tutorial_37_0.svg} (100%) rename docs/tutorial/{tutorial_27_1.svg => tutorial_37_1.svg} (100%) create mode 100644 docs/tutorial/tutorial_42_0.svg create mode 100644 docs/tutorial/tutorial_48_0.svg delete mode 100644 docs/tutorial/tutorial_49_0.svg create mode 100644 docs/tutorial/tutorial_51_0.svg rename docs/tutorial/{tutorial_41_0.svg => tutorial_53_0.svg} (100%) create mode 100644 docs/tutorial/tutorial_56_1.svg rename docs/tutorial/{tutorial_45_0.svg => tutorial_57_0.svg} (100%) rename docs/tutorial/{tutorial_46_0.svg => tutorial_58_0.svg} (100%) delete mode 100644 docs/tutorial/tutorial_64_0.svg rename docs/tutorial/{tutorial_52_1.svg => tutorial_64_1.svg} (100%) rename docs/tutorial/{tutorial_52_2.svg => tutorial_64_2.svg} (100%) rename docs/tutorial/{tutorial_53_1.svg => tutorial_65_1.svg} (100%) create mode 100644 docs/tutorial/tutorial_68_0.svg create mode 100644 docs/tutorial/tutorial_70_0.svg rename docs/tutorial/{tutorial_58_3.svg => tutorial_75_3.svg} (100%) rename docs/tutorial/{tutorial_58_4.svg => tutorial_75_4.svg} (100%) create mode 100644 docs/tutorial/tutorial_78_0.svg rename docs/tutorial/{tutorial_61_1.svg => tutorial_78_1.svg} (100%) rename docs/tutorial/{tutorial_67_1.svg => tutorial_84_1.svg} (100%) delete mode 100644 docs/tutorial/tutorial_85_0.svg rename docs/tutorial/{tutorial_70_1.svg => tutorial_87_1.svg} (100%) delete mode 100644 docs/tutorial/tutorial_89_0.svg rename docs/tutorial/{tutorial_73_0.svg => tutorial_90_0.svg} (100%) delete mode 100644 docs/tutorial/tutorial_91_0.svg rename docs/tutorial/{tutorial_76_0.svg => tutorial_93_0.svg} (100%) delete mode 100644 docs/tutorial/tutorial_94_0.svg create mode 100644 docs/tutorial/tutorial_96_0.svg delete mode 100644 docs/tutorial/tutorial_97_0.svg diff --git a/docs/tutorial/tutorial_100_0.svg b/docs/tutorial/tutorial_100_0.svg deleted file mode 100644 index a8db8a46b..000000000 --- a/docs/tutorial/tutorial_100_0.svg +++ /dev/null @@ -1,2852 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_101_0.svg b/docs/tutorial/tutorial_101_0.svg new file mode 100644 index 000000000..2398210ea --- /dev/null +++ b/docs/tutorial/tutorial_101_0.svg @@ -0,0 +1,5655 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_104_0.svg b/docs/tutorial/tutorial_104_0.svg new file mode 100644 index 000000000..66f47be80 --- /dev/null +++ b/docs/tutorial/tutorial_104_0.svg @@ -0,0 +1,2043 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_105_0.svg b/docs/tutorial/tutorial_105_0.svg index 2398210ea..2b579f8e8 100644 --- a/docs/tutorial/tutorial_105_0.svg +++ b/docs/tutorial/tutorial_105_0.svg @@ -2,7 +2,7 @@ - + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - - - - - - +" id="HelveticaNeue-52"/> + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + - - - - - - - - - - + +" id="HelveticaNeue-101"/> - - - - - - - - - - + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" id="HelveticaNeue-108"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - + - - - - - - - - - - + +" id="HelveticaNeue-99"/> - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - + + - - + + - - - - - - - - - - - - - - - - - + + + + + - - + + - + + +" id="HelveticaNeue-Bold-76"/> - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + - - + + - - - - - - - - - - - + + - - + + - - - + - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - - - - - - - - - - - - - - - + + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_110_0.svg b/docs/tutorial/tutorial_106_0.svg similarity index 100% rename from docs/tutorial/tutorial_110_0.svg rename to docs/tutorial/tutorial_106_0.svg diff --git a/docs/tutorial/tutorial_108_0.svg b/docs/tutorial/tutorial_108_0.svg index 66f47be80..744278a5a 100644 --- a/docs/tutorial/tutorial_108_0.svg +++ b/docs/tutorial/tutorial_108_0.svg @@ -2,7 +2,7 @@ - + - - +" style="fill:#ffffff;"/> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + + + + + - - + + - + - - - - - - - - + + + + + - - + + - + - - - - - - - - - - + + + + + - - + + - + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - +" id="HelveticaNeue-53"/> - + - - + - - + + + + + + + + + + + + + + + + + + + + + + - + - - + + - +" id="HelveticaNeue-55"/> - - - - + + + - - + + + + + - + - - - - - + + + + + - - - - + + + + + + + + + + + + + + + - + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - +" id="Cc_0_3fcb00da59"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + - - - - - - - - - - - - - + + - - - - - - - - - - - - - + + - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + - - - +" id="Ce_0_4cc32e6a5b"/> - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + - + - - - - + + + + + + + + - - + + + + + - + - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + - - + + - + - - - - - - + + + + + - - + + - + - - - - - - + + + + + - - + + - + - - - - - - + + + + + - - + + - + - - - - - - + + + + + + + + + + + + - - - - - - + + + + + - - - - + + - + - - - - + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - + + + - - + + + + + - + - - - + + + + - - + + + + + - + - - - + + + + - - + + + + + - + - - - + + + + - - + + + + + - + - - - + + + - - - - - - - - - - - - - - - - - + - - + - - + - - + - - + + - + - - - - + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" id="HelveticaNeue-Bold-116"/> + + + + + + + + - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - - + + + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + + + + + - - + + - - + + + + - + + +" id="HelveticaNeue-Bold-112"/> - - - - - + - + - - - - - - - +" id="HelveticaNeue-Bold-104"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + - - + + - - + + diff --git a/docs/tutorial/tutorial_109_0.svg b/docs/tutorial/tutorial_109_0.svg deleted file mode 100644 index 2b579f8e8..000000000 --- a/docs/tutorial/tutorial_109_0.svg +++ /dev/null @@ -1,2002 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_112_0.svg b/docs/tutorial/tutorial_112_0.svg index 744278a5a..7dbbb3e95 100644 --- a/docs/tutorial/tutorial_112_0.svg +++ b/docs/tutorial/tutorial_112_0.svg @@ -2,7 +2,7 @@ - + - - - +" id="md65e955135" style="stroke:#8f1402;stroke-width:0.4;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - +" id="m5487defcd9" style="stroke:#d62305;stroke-width:0.4;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - +" id="m47f37074cc" style="stroke:#fe645c;stroke-width:0.4;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - + + + + + + + - - + + + + + + + - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - + - + - + + + - + + + + - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" style="fill:#d2c9c5;stroke:#d2c9c5;stroke-width:0.4;"/> + + + + + + + + + + + + + + + + + + + + - - - - - - + + - + - + +" id="HelveticaNeue-114"/> - - - - - - - - - - - + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + +M 38.40625 26.703125 +Q 36.796875 25.5 34.1875 24.953125 +Q 31.59375 24.40625 28.75 24.046875 +Q 25.90625 23.703125 23 23.25 +Q 20.09375 22.796875 17.796875 21.796875 +Q 15.5 20.796875 14.046875 18.9375 +Q 12.59375 17.09375 12.59375 13.90625 +Q 12.59375 11.796875 13.4375 10.34375 +Q 14.296875 8.90625 15.640625 8 +Q 17 7.09375 18.796875 6.6875 +Q 20.59375 6.296875 22.59375 6.296875 +Q 26.796875 6.296875 29.796875 7.4375 +Q 32.796875 8.59375 34.6875 10.34375 +Q 36.59375 12.09375 37.5 14.140625 +Q 38.40625 16.203125 38.40625 18 +z +" id="HelveticaNeue-97"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +L 28.5 0 +L 28.5 7.5 +L 24.59375 7.5 +Q 22.59375 7.5 21.34375 7.640625 +Q 20.09375 7.796875 19.390625 8.296875 +Q 18.703125 8.796875 18.453125 9.6875 +Q 18.203125 10.59375 18.203125 12.09375 +L 18.203125 44.203125 +L 28.5 44.203125 +L 28.5 51.703125 +z +" id="HelveticaNeue-116"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + - - + + + + + + + - +" id="md28a8308b0" style="stroke:#bde1ff;stroke-width:0.4;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - + - - + + - +" id="HelveticaNeue-79"/> - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - +" id="HelveticaNeue-Bold-101"/> + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + - - + + diff --git a/docs/tutorial/tutorial_116_1.svg b/docs/tutorial/tutorial_112_1.svg similarity index 100% rename from docs/tutorial/tutorial_116_1.svg rename to docs/tutorial/tutorial_112_1.svg diff --git a/docs/tutorial/tutorial_118_0.svg b/docs/tutorial/tutorial_114_0.svg similarity index 100% rename from docs/tutorial/tutorial_118_0.svg rename to docs/tutorial/tutorial_114_0.svg diff --git a/docs/tutorial/tutorial_118_1.svg b/docs/tutorial/tutorial_114_1.svg similarity index 100% rename from docs/tutorial/tutorial_118_1.svg rename to docs/tutorial/tutorial_114_1.svg diff --git a/docs/tutorial/tutorial_116_0.svg b/docs/tutorial/tutorial_116_0.svg deleted file mode 100644 index 7dbbb3e95..000000000 --- a/docs/tutorial/tutorial_116_0.svg +++ /dev/null @@ -1,9760 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_117_1.svg b/docs/tutorial/tutorial_117_1.svg new file mode 100644 index 000000000..09e6284fd --- /dev/null +++ b/docs/tutorial/tutorial_117_1.svg @@ -0,0 +1,193147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_123_0.svg b/docs/tutorial/tutorial_119_0.svg similarity index 100% rename from docs/tutorial/tutorial_123_0.svg rename to docs/tutorial/tutorial_119_0.svg diff --git a/docs/tutorial/tutorial_123_1.svg b/docs/tutorial/tutorial_119_1.svg similarity index 100% rename from docs/tutorial/tutorial_123_1.svg rename to docs/tutorial/tutorial_119_1.svg diff --git a/docs/tutorial/tutorial_125_0.svg b/docs/tutorial/tutorial_121_0.svg similarity index 100% rename from docs/tutorial/tutorial_125_0.svg rename to docs/tutorial/tutorial_121_0.svg diff --git a/docs/tutorial/tutorial_121_1.svg b/docs/tutorial/tutorial_121_1.svg index 09e6284fd..8b60bc872 100644 --- a/docs/tutorial/tutorial_121_1.svg +++ b/docs/tutorial/tutorial_121_1.svg @@ -2,7 +2,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - + + + + + + + + + + + +" style="fill:#ffffff;"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - +" id="HelveticaNeue-52"/> + + + + + + + - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - + + - - - - - - - - - - - - + + - - - - - - - - - - - + + - - - - - - - - - - + + + - + - - - + - + - - + - + - +" id="HelveticaNeue-97"/> + + + + + + + + + - - - - - + + +" style="fill:#ffffff;"/> - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + - - + + + + + + + + + + + + + - + - - + + + + + - + - - + + + + + - + - - + + + + + - + - - + + + + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - + - - - - - + + - - - - - - - - + - - - - - + + - - - - - - - - + - - - - - + + - - - - - - - - + - - - - - + + - - - - - - - - + - - - - - + + - + - - + + - + - - + + - + - - + + - + + + - + + + + - + - - - - - + + + + - - + + + + + - + - - - - - + + + + + - - + + + + + - + - - - - - + + + + + - - + + + + + - + - - - - - + + + + + - - + + + + + - + - - - - - + + + + + - - + + + + + - + - - - - - - - - - - - - - + + + + + + + - - + - - + - - + - - + - - + + - + +" id="HelveticaNeue-105"/> - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - + - + - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - + + - - - - - - - - - - - + + - - - - - - - - - - - + + - - - - - - - + + - - - + + + - + + - + +" id="HelveticaNeue-116"/> + + + + + + + + + + + + + + + + + - - - + + +" style="fill:#ffffff;"/> - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - - - - - + + - - - - - - - - - - - + + - - - - - - - - - + + - - - - - - - - - + + - - - - - - - - - + + - - - - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + - - - - - - - + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + - - + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +" id="HelveticaNeue-Bold-110"/> + - - +" id="HelveticaNeue-Bold-114"/> + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_125_1.svg b/docs/tutorial/tutorial_125_1.svg deleted file mode 100644 index 8b60bc872..000000000 --- a/docs/tutorial/tutorial_125_1.svg +++ /dev/null @@ -1,19176 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_130_0.svg b/docs/tutorial/tutorial_126_0.svg similarity index 100% rename from docs/tutorial/tutorial_130_0.svg rename to docs/tutorial/tutorial_126_0.svg diff --git a/docs/tutorial/tutorial_129_0.svg b/docs/tutorial/tutorial_129_0.svg new file mode 100644 index 000000000..207d9334f --- /dev/null +++ b/docs/tutorial/tutorial_129_0.svg @@ -0,0 +1,2613 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_12_0.svg b/docs/tutorial/tutorial_12_0.svg new file mode 100644 index 000000000..a8580aa2e --- /dev/null +++ b/docs/tutorial/tutorial_12_0.svg @@ -0,0 +1,5551 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_12_1.svg b/docs/tutorial/tutorial_12_1.svg deleted file mode 100644 index 85e1ff443..000000000 --- a/docs/tutorial/tutorial_12_1.svg +++ /dev/null @@ -1,3574 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_135_0.svg b/docs/tutorial/tutorial_131_0.svg similarity index 100% rename from docs/tutorial/tutorial_135_0.svg rename to docs/tutorial/tutorial_131_0.svg diff --git a/docs/tutorial/tutorial_133_0.svg b/docs/tutorial/tutorial_133_0.svg index 207d9334f..dc3701e43 100644 --- a/docs/tutorial/tutorial_133_0.svg +++ b/docs/tutorial/tutorial_133_0.svg @@ -2,7 +2,7 @@ - + - - - +" id="m789d0468c5" style="stroke:#000000;stroke-width:0.6;"/> - + @@ -96,20 +96,20 @@ Q 4.203125 38.703125 4.203125 34.796875 z " id="HelveticaNeue-48"/> - + - - + @@ -199,7 +199,7 @@ L 18.40625 62.203125 z " id="HelveticaNeue-53"/> - + @@ -208,31 +208,31 @@ z - - + - + - - + @@ -255,7 +255,7 @@ Q 45.5 57.09375 50.90625 62.40625 z " id="HelveticaNeue-55"/> - + @@ -264,13 +264,13 @@ z - - + @@ -289,7 +289,7 @@ L 27.09375 0 z " id="HelveticaNeue-49"/> - + @@ -297,1828 +297,985 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - - - - + + + + + + - - - + + - + - + - - - - + + + + - - - + + - + - + - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - + + +L 0 2 +" id="m03f684513e" style="stroke:#000000;stroke-width:0.48;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - - + + + + + - - - - - + + - + - - - - - + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - + + + - + + + + - + + + + + + + + + + + + + - - - + + - + - + + + + + + + - - - + + - + - + + + + + + + + + - - - + + - + - + + + + + + + - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - + - - + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + +" id="HelveticaNeue-Bold-108"/> + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + diff --git a/docs/tutorial/tutorial_137_0.svg b/docs/tutorial/tutorial_137_0.svg deleted file mode 100644 index dc3701e43..000000000 --- a/docs/tutorial/tutorial_137_0.svg +++ /dev/null @@ -1,1548 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_142_0.svg b/docs/tutorial/tutorial_138_0.svg similarity index 100% rename from docs/tutorial/tutorial_142_0.svg rename to docs/tutorial/tutorial_138_0.svg diff --git a/docs/tutorial/tutorial_142_1.svg b/docs/tutorial/tutorial_138_1.svg similarity index 100% rename from docs/tutorial/tutorial_142_1.svg rename to docs/tutorial/tutorial_138_1.svg diff --git a/docs/tutorial/tutorial_145_0.svg b/docs/tutorial/tutorial_141_0.svg similarity index 100% rename from docs/tutorial/tutorial_145_0.svg rename to docs/tutorial/tutorial_141_0.svg diff --git a/docs/tutorial/tutorial_148_0.svg b/docs/tutorial/tutorial_144_0.svg similarity index 100% rename from docs/tutorial/tutorial_148_0.svg rename to docs/tutorial/tutorial_144_0.svg diff --git a/docs/tutorial/tutorial_153_0.svg b/docs/tutorial/tutorial_149_0.svg similarity index 100% rename from docs/tutorial/tutorial_153_0.svg rename to docs/tutorial/tutorial_149_0.svg diff --git a/docs/tutorial/tutorial_14_0.svg b/docs/tutorial/tutorial_14_0.svg new file mode 100644 index 000000000..087d20846 --- /dev/null +++ b/docs/tutorial/tutorial_14_0.svg @@ -0,0 +1,4188 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_150_0.svg b/docs/tutorial/tutorial_150_0.svg new file mode 100644 index 000000000..10abe70ab --- /dev/null +++ b/docs/tutorial/tutorial_150_0.svg @@ -0,0 +1,12617 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_156_0.svg b/docs/tutorial/tutorial_152_0.svg similarity index 100% rename from docs/tutorial/tutorial_156_0.svg rename to docs/tutorial/tutorial_152_0.svg diff --git a/docs/tutorial/tutorial_154_0.svg b/docs/tutorial/tutorial_154_0.svg index 10abe70ab..f7f18e968 100644 --- a/docs/tutorial/tutorial_154_0.svg +++ b/docs/tutorial/tutorial_154_0.svg @@ -2,7 +2,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +" id="m487f27f273" style="stroke:#000000;stroke-width:0.6;"/> - + - + + + + - + - + + + + - + - + + + + - + - + +" id="m94b3232e7a" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + +" id="m41e5c8b202" style="stroke:#000000;stroke-width:0.6;"/> - + @@ -2645,65 +2098,25 @@ Q 4.203125 38.703125 4.203125 34.796875 z " id="HelveticaNeue-48"/> - + - + + + + - + - + - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - + + + - - - + - + - + - + - - - - - - - - - - - - - - + + + - - - + - + - + - + - - - - - - - - - - - - - - - - - - + + +" id="m45d785b727" style="stroke:#000000;stroke-width:0.48;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - + + - - - + - + - - + - + +" id="HelveticaNeue-100"/> + - - - +" id="HelveticaNeue-111"/> - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" id="HelveticaNeue-118"/> + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + - + + + + - + - + + + + - + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + + + + + + - + - - + + + + + - + - - + + + + + - + - - + + + + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - + + - - - + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" style="fill:none;opacity:0;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + - - - - - + + + + + - - - - - - - - + + + + + + + + - - - - - + + + + + - - - - - - + + + + + - - - - - + + + + + - - - - - - + + + + + + + - - - - - + + + + + - - - - - - + + + + + + + - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" id="HelveticaNeue-51"/> + + + - - + + - - - + + - - - + + - - - - - - - - - + + + + + + + + + + + + - - - + + + - + - - - - + + + + + + + - - + + - + - - - - - + + + + + + + + + + + + + + + + + + + + - - + + - + - - - + + + - - + + - - + + - + - - - + + + - - + + - - + + - + - - - + + + - - + + - - - + + - - - + + - - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - + - - - - + + + + + + + + + + - - + + - + - - - - - + + + + + + + - - + + - + - - - - - - + + + + + + + - - + + - + - - - - - - + + + + + + + - - + + - + - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + - - - + + - - - - - - - - - - - + + + + + + + + + + + + - - - + + + - + - - - - + + + + + + + - - + + - + - - - - - + + + + + + + - - + + - + - - - - - - + + + + + + + - - + + - + - - - - - - + + + + + + + - - + + - + - - - - - - + + + + + + + + + + + + + + + + + + + - - - + + - - + + - - + - + +M 42.296875 6.59375 +L 42.296875 0 +L 55.796875 0 +L 55.796875 71.40625 +L 41.59375 71.40625 +L 41.59375 45.40625 +L 41.40625 45.40625 +Q 39 49.203125 34.84375 51.140625 +Q 30.703125 53.09375 26.09375 53.09375 +Q 20.40625 53.09375 16.09375 50.84375 +Q 11.796875 48.59375 8.9375 44.890625 +Q 6.09375 41.203125 4.640625 36.34375 +Q 3.203125 31.5 3.203125 26.296875 +Q 3.203125 20.90625 4.640625 15.90625 +Q 6.09375 10.90625 8.9375 7.046875 +Q 11.796875 3.203125 16.1875 0.953125 +Q 20.59375 -1.296875 26.40625 -1.296875 +Q 31.5 -1.296875 35.546875 0.546875 +Q 39.59375 2.40625 42.09375 6.59375 +z +" id="HelveticaNeue-Bold-100"/> + - - - - +" id="HelveticaNeue-Bold-110"/> + + - + - - - - - - - +" id="HelveticaNeue-Bold-108"/> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_161_0.svg b/docs/tutorial/tutorial_157_0.svg similarity index 100% rename from docs/tutorial/tutorial_161_0.svg rename to docs/tutorial/tutorial_157_0.svg diff --git a/docs/tutorial/tutorial_161_1.svg b/docs/tutorial/tutorial_157_1.svg similarity index 100% rename from docs/tutorial/tutorial_161_1.svg rename to docs/tutorial/tutorial_157_1.svg diff --git a/docs/tutorial/tutorial_158_0.svg b/docs/tutorial/tutorial_158_0.svg deleted file mode 100644 index f7f18e968..000000000 --- a/docs/tutorial/tutorial_158_0.svg +++ /dev/null @@ -1,6313 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_15_0.svg b/docs/tutorial/tutorial_15_0.svg new file mode 100644 index 000000000..1e7530d09 --- /dev/null +++ b/docs/tutorial/tutorial_15_0.svg @@ -0,0 +1,7190 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_164_0.svg b/docs/tutorial/tutorial_160_0.svg similarity index 100% rename from docs/tutorial/tutorial_164_0.svg rename to docs/tutorial/tutorial_160_0.svg diff --git a/docs/tutorial/tutorial_167_0.svg b/docs/tutorial/tutorial_163_0.svg similarity index 100% rename from docs/tutorial/tutorial_167_0.svg rename to docs/tutorial/tutorial_163_0.svg diff --git a/docs/tutorial/tutorial_170_0.svg b/docs/tutorial/tutorial_166_0.svg similarity index 100% rename from docs/tutorial/tutorial_170_0.svg rename to docs/tutorial/tutorial_166_0.svg diff --git a/docs/tutorial/tutorial_173_1.svg b/docs/tutorial/tutorial_169_1.svg similarity index 100% rename from docs/tutorial/tutorial_173_1.svg rename to docs/tutorial/tutorial_169_1.svg diff --git a/docs/tutorial/tutorial_16_2.svg b/docs/tutorial/tutorial_16_2.svg deleted file mode 100644 index 6d14bd1f4..000000000 --- a/docs/tutorial/tutorial_16_2.svg +++ /dev/null @@ -1,3622 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_176_1.svg b/docs/tutorial/tutorial_172_1.svg similarity index 100% rename from docs/tutorial/tutorial_176_1.svg rename to docs/tutorial/tutorial_172_1.svg diff --git a/docs/tutorial/tutorial_179_0.svg b/docs/tutorial/tutorial_175_0.svg similarity index 100% rename from docs/tutorial/tutorial_179_0.svg rename to docs/tutorial/tutorial_175_0.svg diff --git a/docs/tutorial/tutorial_88_1.svg b/docs/tutorial/tutorial_17_1.svg similarity index 58% rename from docs/tutorial/tutorial_88_1.svg rename to docs/tutorial/tutorial_17_1.svg index f9fe11fb3..31455f0b7 100644 --- a/docs/tutorial/tutorial_88_1.svg +++ b/docs/tutorial/tutorial_17_1.svg @@ -27,2406 +27,2406 @@ z " style="fill:#ffffff;"/> - - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - - + - + - + - - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - + - + - + - - + - + - - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + +" style="fill:#a4a4a4;stroke:#a4a4a4;stroke-width:0.4;"/> @@ -2434,17 +2434,17 @@ L 111.34375 28.011875 +" id="m55e34583c1" style="stroke:#000000;stroke-width:0.6;"/> - + - + @@ -2453,59 +2453,59 @@ L 0 4 +" id="m64a7bac45d" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - + - + @@ -2516,10 +2516,10 @@ L 0 2 +" id="mdb5a4fe439" style="stroke:#000000;stroke-width:0.6;"/> - + @@ -2583,7 +2583,7 @@ z - + @@ -2636,7 +2636,7 @@ z - + @@ -2664,7 +2664,7 @@ z - + @@ -2680,115 +2680,115 @@ z +" id="m541e6e116b" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -2894,2475 +2894,2475 @@ z " style="fill:#ffffff;"/> - - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - - + - + - + - - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - + - + - + - - + - + - - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + +" style="fill:#a4a4a4;stroke:#a4a4a4;stroke-width:0.4;"/> - + - + - + - + - + - + - + - + - + - + @@ -5371,140 +5371,140 @@ L 209.74375 28.011875 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -5588,2475 +5588,2475 @@ z " style="fill:#ffffff;"/> - - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - - + - + - + - - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - + - + - + - - + - + - - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + +" style="fill:#a4a4a4;stroke:#a4a4a4;stroke-width:0.4;"/> - + - + - + - + - + - + - + - + - + - + @@ -8065,140 +8065,140 @@ L 308.14375 28.011875 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -8265,2483 +8265,2483 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + +" style="fill:#a4a4a4;stroke:#a4a4a4;stroke-width:0.4;"/> - + - + - + - + - + - + - + - + - + - + @@ -10750,12 +10750,12 @@ L 111.34375 135.838437 - + - + @@ -10763,12 +10763,12 @@ L 111.34375 135.838437 - + - + @@ -10776,12 +10776,12 @@ L 111.34375 135.838437 - + - + @@ -10790,7 +10790,7 @@ L 111.34375 135.838437 - + @@ -10804,112 +10804,112 @@ L 111.34375 135.838437 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -11087,23 +11087,23 @@ z - - - - @@ -11149,7 +11149,7 @@ Q 39.59375 2.40625 42.09375 6.59375 z " id="HelveticaNeue-Bold-100"/> - + @@ -11157,2483 +11157,2483 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + +" style="fill:#a4a4a4;stroke:#a4a4a4;stroke-width:0.4;"/> - + - + - + - + - + - + - + - + - + - + @@ -13642,162 +13642,162 @@ L 209.74375 135.838437 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -13836,7 +13836,7 @@ Q 17.40625 15.5 17.09375 22.40625 z " id="HelveticaNeue-Bold-101"/> - + @@ -13844,2483 +13844,2483 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - + - + - + - + - + - + - + - + - + - + - + - - - + - - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + +" style="fill:#a4a4a4;stroke:#a4a4a4;stroke-width:0.4;"/> - + - + - + - + - + - + - + - + - + - + @@ -16329,162 +16329,162 @@ L 308.14375 135.838437 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -16512,7 +16512,7 @@ L 0 42.203125 z " id="HelveticaNeue-Bold-102"/> - + @@ -16528,2412 +16528,2412 @@ z " style="fill:#ffffff;"/> - - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - - + - + - + - - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - + - + - + - - + - + - - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + +" style="fill:#a4a4a4;stroke:#a4a4a4;stroke-width:0.4;"/> - + @@ -18946,7 +18946,7 @@ L 111.34375 243.665 - + @@ -18960,56 +18960,56 @@ L 111.34375 243.665 - + - + - + - + - + - + - + - + @@ -19018,7 +19018,7 @@ L 111.34375 243.665 - + @@ -19031,7 +19031,7 @@ L 111.34375 243.665 - + @@ -19044,7 +19044,7 @@ L 111.34375 243.665 - + @@ -19058,7 +19058,7 @@ L 111.34375 243.665 - + @@ -19072,112 +19072,112 @@ L 111.34375 243.665 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -19274,2412 +19274,2412 @@ z " style="fill:#ffffff;"/> - - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - - + - + - + - - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - + - + - + - - + - + - - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + +" style="fill:#a4a4a4;stroke:#a4a4a4;stroke-width:0.4;"/> - + @@ -21692,7 +21692,7 @@ L 209.74375 243.665 - + @@ -21706,56 +21706,56 @@ L 209.74375 243.665 - + - + - + - + - + - + - + - + @@ -21791,140 +21791,140 @@ z - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -21990,2412 +21990,2412 @@ z " style="fill:#ffffff;"/> - - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - + - + - - + - + - + - - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + - - + - + - + - + - + - + - - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - - + - + - + - + - - + - + - - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - - - + - - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + +" style="fill:#a4a4a4;stroke:#a4a4a4;stroke-width:0.4;"/> - + @@ -24408,7 +24408,7 @@ L 308.14375 243.665 - + @@ -24422,56 +24422,56 @@ L 308.14375 243.665 - + - + - + - + - + - + - + - + @@ -24480,140 +24480,140 @@ L 308.14375 243.665 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -24670,101 +24670,101 @@ z - - - - - - - - - - - - - - + - + @@ -24772,7 +24772,7 @@ L 104.86375 369.3225 - + @@ -24795,12 +24795,12 @@ z - + - + @@ -24819,12 +24819,12 @@ z @@ -24833,6 +24833,160 @@ z + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - + - - - - - - - - - - - - - - + + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - - + + - + - + - + - + @@ -25183,23 +25337,209 @@ z - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + - - + - - - - - - - - - - - + + + + + + + + + + - - + + - + +" id="mc0b0984be2" style="stroke:#000000;stroke-width:0.6;"/> - + - + - + - + - + - + - + @@ -25330,14 +25670,14 @@ L 4 0 - + - + - + - + @@ -25345,12 +25685,12 @@ L 4 0 - + - + - + - + @@ -25413,14 +25753,14 @@ z - + - + - + - + @@ -25428,14 +25768,14 @@ z - + - + - + - + @@ -25443,14 +25783,14 @@ z - + - + - + - + @@ -25458,12 +25798,12 @@ z - + - + - + - + @@ -25491,14 +25831,14 @@ z - + - + - + - + @@ -25506,12 +25846,12 @@ z - + - + - + - + @@ -25568,21 +25908,21 @@ z - + - + - + - + - + - + @@ -25591,445 +25931,105 @@ z - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + @@ -26037,12 +26037,12 @@ L 320.46375 79.34938 - + - + @@ -26050,12 +26050,12 @@ L 320.46375 79.34938 - + - + @@ -26065,12 +26065,12 @@ L 320.46375 79.34938 - + - + @@ -26080,12 +26080,12 @@ L 320.46375 79.34938 - + - + @@ -26095,12 +26095,12 @@ L 320.46375 79.34938 - + - + @@ -26110,12 +26110,12 @@ L 320.46375 79.34938 - + - + @@ -26125,12 +26125,12 @@ L 320.46375 79.34938 - + - + @@ -26140,12 +26140,12 @@ L 320.46375 79.34938 - + - + @@ -26155,12 +26155,12 @@ L 320.46375 79.34938 - + - + @@ -26170,12 +26170,12 @@ L 320.46375 79.34938 - + - + @@ -26185,19 +26185,19 @@ L 320.46375 79.34938 - + - + - + @@ -26208,19 +26208,19 @@ L 320.46375 79.34938 - + - - +" id="HelveticaNeue-Bold-111"/> + - - + @@ -26477,56 +26438,71 @@ z - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - - + + - - + + - + - + - + - + - + - - + + diff --git a/docs/tutorial/tutorial_18_0.svg b/docs/tutorial/tutorial_18_0.svg index 079181ef2..f77679bf6 100644 --- a/docs/tutorial/tutorial_18_0.svg +++ b/docs/tutorial/tutorial_18_0.svg @@ -2,7 +2,7 @@ - + - - - - - - - - + + + + + + - - + + + - - + + + + + + - - + + - - + + + - - + + - - + + - - + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + - +" id="m4dc793af4d" style="stroke:#000000;stroke-width:0.6;"/> - + - + - - - - - - + + - - + - - - + + + + + + + - - + - - - + + + + + + @@ -1378,114 +3985,72 @@ L 172.51875 23.415469 +" id="m158d0613bd" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + - - - - +" id="HelveticaNeue-98"/> - - - - - - - - - - - - - - + + + + + + + - - + - + +" id="m4d8a213089" style="stroke:#000000;stroke-width:0.6;"/> - + + + + + + + - - + - + - + + + + + + + + + + + - - + - + - + + + + + + + + - - + - + - + + + + + + + + + + + - - + - + - + - - - - - - - - + + + + + - - + + +" id="mc970b2e221" style="stroke:#000000;stroke-width:0.48;"/> - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - - - - - - - - - - - - - - + + +" id="HelveticaNeue-115"/> + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - + + + + + + - - - - - - + + + - + - - + + - - - - - - + + - - - - - - + + + - - - - - - + + - - - - - - + + - - - - - - + + - - - - - - + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - + + + + + - - - + + + + + - + + + - + - - - - - - - + + + + + - + - - - - + - - - - - - - + + + + + - + - + + + + + - + - - - - - + + + + + + + + + + - + + + - - + - - - - + + + + - + - - + - - - - - - - + + + + + - + - - + - - - - + + + + + - + - - + - - - - - - - + + + + + - + - - + - - - - + + + + + - + - - - - + - - - - - - - + + + + + - + - - - - + - - - - - - - + + + + + - + - - - - + - - - - + + + + + - + - - - - + - - - - - - - + + + + + - + - - - - + - - - - + + + + + - + - + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + - + - - - - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - + + + - - - + + - + - + - + - + - - + + - - - - - + + - + - - - - - - - + + + + + - - - - - + + - + - - - - + + + + + - - - - - - - - - - - + + + + + - - - - - + + + + + - + + + - + - - - - + + + + + - - - + + + + + + + + + + + + + + + - + - + - - + + - - - + + - + - - - + + - + - + - - - - + + + + + + - - - + + - + - + - - + + - + - - + + - + - - - + + - + - + - - + + - +M 6.5 52.796875 +Q 6.5 48 9.203125 43.953125 +Q 11.90625 39.90625 16.40625 38.09375 +Q 10.40625 36 7.203125 31.34375 +Q 4 26.703125 4 20.40625 +Q 4 15 5.84375 10.953125 +Q 7.703125 6.90625 10.953125 4.203125 +Q 14.203125 1.5 18.59375 0.203125 +Q 23 -1.09375 28.09375 -1.09375 +Q 33 -1.09375 37.296875 0.296875 +Q 41.59375 1.703125 44.75 4.453125 +Q 47.90625 7.203125 49.75 11.203125 +Q 51.59375 15.203125 51.59375 20.40625 +Q 51.59375 27 48.5 31.546875 +Q 45.40625 36.09375 39 38.09375 +Q 43.5 40.09375 46.140625 44.046875 +Q 48.796875 48 48.796875 52.796875 +Q 48.796875 56.203125 47.59375 59.453125 +Q 46.40625 62.703125 43.84375 65.25 +Q 41.296875 67.796875 37.1875 69.34375 +Q 33.09375 70.90625 27.296875 70.90625 +Q 23.203125 70.90625 19.453125 69.703125 +Q 15.703125 68.5 12.796875 66.203125 +Q 9.90625 63.90625 8.203125 60.546875 +Q 6.5 57.203125 6.5 52.796875 +z +M 13 20 +Q 13 23.09375 14.140625 25.59375 +Q 15.296875 28.09375 17.34375 29.890625 +Q 19.40625 31.703125 22.15625 32.640625 +Q 24.90625 33.59375 28 33.59375 +Q 31 33.59375 33.640625 32.546875 +Q 36.296875 31.5 38.296875 29.703125 +Q 40.296875 27.90625 41.4375 25.453125 +Q 42.59375 23 42.59375 20.09375 +Q 42.59375 17.09375 41.546875 14.59375 +Q 40.5 12.09375 38.546875 10.25 +Q 36.59375 8.40625 33.9375 7.34375 +Q 31.296875 6.296875 28.09375 6.296875 +Q 21.5 6.296875 17.25 9.9375 +Q 13 13.59375 13 20 +z +" id="HelveticaNeue-56"/> - - - + + + + - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + + + + + - - - - - + + - + - - - - - + + + + + - - - + + + + + - + + + - + - - - - - - - + + + + + - - + + - + - - + + - + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + - - + + + + + - + + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + + + + + + + + + + + + + + + + + - + + + + + + + + + - - + + + + + - + + + + + + + + + - - + + + + + - + + + + + + + + + - - + + + + + - + + + + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - + + - - + + - - + + - - + + - - + + - - - - - - - - - - - - + - - + - - + - - + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - - + + - - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - + - + - + - - + + - + - - - - - + + + + - - + + - + - - - - + + + + - - + + - + - - - - - - - - + + + + + - - + + - + - - - - - - - + + + + - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - + + - - - - - - - - - - + + + + + + + + + + + - - - - + + + - + - + - + - - + + - + - - - - - + + + + - - + + - + - - - - + + + + - - + + - + - - - - - + + + + + - - + + - + - - - - + + + + - - - - - + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - + + + + + + - - - - - + - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +" id="HelveticaNeue-Bold-109"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_21_0.svg b/docs/tutorial/tutorial_21_0.svg index 99cd2b55a..370434ecd 100644 --- a/docs/tutorial/tutorial_21_0.svg +++ b/docs/tutorial/tutorial_21_0.svg @@ -2,7 +2,7 @@ - + - - - +" id="m5ec9ffb235" style="stroke:#000000;stroke-width:0.6;"/> - + @@ -96,90 +96,267 @@ Q 4.203125 38.703125 4.203125 34.796875 z " id="HelveticaNeue-48"/> - + - - + - + - - +" id="HelveticaNeue-50"/> - - - - + + - - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + - - + + +" id="meaaf3246cf" style="stroke:#000000;stroke-width:0.48;"/> - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - + @@ -446,4280 +669,4392 @@ z - - + - + +" id="medde04a5b3" style="stroke:#000000;stroke-width:0.6;"/> - + - - - - + + + + - - + - + - + - - + + - +" id="HelveticaNeue-46"/> + - - + + - - + - - + - + - + - - - - - - + + + + - - + - + - + - - - - - - - + + + + - - + - - + - + - + - - - - + + + + + + + - + +" id="m9f025b3472" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + + + - - - - - - - - - - +" style="fill:#ffffff;stroke:#ffffff;stroke-linejoin:miter;stroke-width:0.01;"/> - - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - - - - - - - - - +" id="HelveticaNeue-115"/> + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - - + + - + - + - - - - - - + + + + - - - + + - + - + - - - - + + + + - - - - - + + + - - - + - + + + + + + + - - + + + + + - + + + + + + + - - + + + + + - + + + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - + + + + + - + + + - + - - - - + + + + + - - - + + + + + - + + + - + - - - - - - - + + + + + - - - + + + + + - + + + - + - - - - - - + + + + + - - - + + + + + - + + + - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - + - - - - + + + + - + + + + - + + + + + + + - + + + + - + + + + + + + - + + + + - + + + + + + + - + + + + - + + + + + + + - + + + + - + + + + + + + - + + + + - + + + + + + + - + + + + - + + + + + + + - + + + + - + + + + + + + - + + + + - + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - + - - - - - + + - - - - - - - - - - + - - - - - + + - - - - - - - - - + - - - - - + + - - - - - - - - - - + - - - - - + + - - - - - - - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - + + + + + + + + + - - + - - + - - + - - + - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" style="fill:#ffffff;opacity:0.5;stroke:#495057;stroke-linejoin:miter;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +M 37.59375 25.296875 +Q 36.703125 24.5 35.34375 24.046875 +Q 34 23.59375 32.453125 23.296875 +Q 30.90625 23 29.203125 22.796875 +Q 27.5 22.59375 25.796875 22.296875 +Q 24.203125 22 22.640625 21.5 +Q 21.09375 21 19.9375 20.140625 +Q 18.796875 19.296875 18.09375 18 +Q 17.40625 16.703125 17.40625 14.703125 +Q 17.40625 12.796875 18.09375 11.5 +Q 18.796875 10.203125 20 9.453125 +Q 21.203125 8.703125 22.796875 8.390625 +Q 24.40625 8.09375 26.09375 8.09375 +Q 30.296875 8.09375 32.59375 9.5 +Q 34.90625 10.90625 36 12.84375 +Q 37.09375 14.796875 37.34375 16.796875 +Q 37.59375 18.796875 37.59375 20 +z +" id="HelveticaNeue-Bold-97"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - + + + + - - + + - + - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - + + + + - - - - - + + - + - - - - - - + + + + - - - - - + + - + - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - - + + + + + - - + + - + - - - - - + + + + + - - - - - - - + + - + - - - - + + + + + - - - - - + + - + - - - - - - - + + + + + - - - - - + + - + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + @@ -4727,255 +5062,350 @@ L 316.765938 264.95125 - - - - - + + - + - + - + - - - - - - - - - + + - + - - - - - + + + + + + + - - + + - + - - - - - + + + + + + - - + + - + - - - - - + + + + + + + - - + + - + - - - - - + + + + - - + + - + - - - - - + + + + + + + - - + + - + - - - - - + + + + + + - - + + - + - - - - - + + + + + + + - - + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + - - + + - - + + - - - - + +" id="HelveticaNeue-Bold-98"/> + + - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_22_0.svg b/docs/tutorial/tutorial_22_0.svg index 755a0de3d..fe614b6a2 100644 --- a/docs/tutorial/tutorial_22_0.svg +++ b/docs/tutorial/tutorial_22_0.svg @@ -2,7 +2,7 @@ - + - - - +" id="m749c7043d6" style="stroke:#000000;stroke-width:0.6;"/> - + + + + + + + + + + - - + + + + + + + + + + - - + + + + + + + + + + + - - + + + + + + + + - - - + + + - + - - - - + - + - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + - + - - - - - - - - - - - - - - - - - - + + + + - - - +" id="HelveticaNeue-108"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - - - - - + + - - - + + - + - + - - + + - + - - - - + + - - - - + - - - - - - - + - - - - + + - + - - - - + - - - - - - - - - + + + + + - + - + + + + + - - - - - - - - - - + - + - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + - + - - - - - + @@ -862,1504 +880,1200 @@ z + + + + + + + + + + + + + + + - - - - - - - - - - + + - - + + + + + + + + + + + - - - - - - - +M 15.40625 -6.5 +L 15.40625 51.703125 +L 6.90625 51.703125 +L 6.90625 -5.09375 +Q 6.90625 -9.09375 5.90625 -10.640625 +Q 4.90625 -12.203125 2.09375 -12.203125 +L 0.296875 -12.203125 +Q -0.09375 -12.203125 -0.4375 -12.140625 +Q -0.796875 -12.09375 -1.296875 -12 +L -1.296875 -19.296875 +Q 0.703125 -19.703125 3 -19.703125 +Q 8.703125 -19.703125 12.046875 -16.546875 +Q 15.40625 -13.40625 15.40625 -6.5 +z +" id="HelveticaNeue-106"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - - + - + - + + + + + + + - - + - + - + + + + + + + + - - + - + - + + + + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + - + + + - + - - - - + + + - + - - - - + + + + + - - - - + + + + + - - - + + + + + - + + + - + - + + + - + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + - - - + + - + - + - - - + + + + - - - - + + + + + + + + - + - + - - - - + + + + + + + - - - - + + + + + + + + + + + + - + + + + + + + - - + + - + - + + + - + - - + + - + - + + + - + - - + + - + - + + + - + - - + + - + - + + + - + - - + + - + - + + + - + - - + + - + - + + + - + - - + + - + - + + + - + - - - - - - - - - + + + + + - - - - - - - - + + + + + + - - - - - - - - + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + - - - - - - - - - - - +" style="fill:none;opacity:0;"/> - - - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + +" style="fill:none;opacity:0;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + +" id="HelveticaNeue-Bold-101"/> - + + + + + + - + +" id="HelveticaNeue-Bold-109"/> - - - - - - - + - +" id="HelveticaNeue-Bold-105"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + - - + + diff --git a/docs/tutorial/tutorial_26_0.svg b/docs/tutorial/tutorial_26_0.svg deleted file mode 100644 index 17d1e5197..000000000 --- a/docs/tutorial/tutorial_26_0.svg +++ /dev/null @@ -1,6927 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_26_2.svg b/docs/tutorial/tutorial_26_2.svg index 6a7fe6479..6d14bd1f4 100644 --- a/docs/tutorial/tutorial_26_2.svg +++ b/docs/tutorial/tutorial_26_2.svg @@ -2,7 +2,7 @@ - + - - - +" id="m2e7a9fc7ce" style="stroke:#000000;stroke-width:0.6;"/> - + @@ -96,58 +96,31 @@ Q 4.203125 38.703125 4.203125 34.796875 z " id="HelveticaNeue-48"/> - + - - + - + - - - - - - - - - - - - - - - - - - - - +" id="HelveticaNeue-46"/> - - - - - - - - - - - - - + + + + - - - - - + + + - - - + - + - - - - - + + + + + + + + + - - - - - + + + - - - + - + - - - - - + + + + + + + + + - - - - - + + + - - - + - + - - - - - + + + + + + + + + - - - - - + + - - - - + - + - - + + - +" id="HelveticaNeue-49"/> - - - - + + - - - - - + + + + + - - - - - - - + - - - - - + + - - - - - - - - + - - - - - + + - + - - - - - - - - + + + + + - - - - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - - - + +" id="HelveticaNeue-105"/> + + - + +" id="HelveticaNeue-99"/> + + + + + - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + + + - + - + - + - - - + + - + - + - - - + + + - - - - + + - + - + - - - + + + - - - + + + + + - + - - - - - + + + + + + + - - + + + + + - + - - - - - + + + + - - + + + + + - + + + + + + + + + + - - + + + + + - + + + + + + + - - + + + + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - + + - + - - - - - - + + + + + - - - - - + + - + - - - - + + + + + - - - - - + + - + - - - - - + + + + + - - - - + - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + + + + + + + + + + - - + - - + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - + - + - - - - + + + + + + + + + + + + + - - + - + - + - - - - + + + + + + + + + + + + - - + - + - + - - - + + + + + + + + + + + + + + - + + + + - + + + + + + + + + + + + + + + + + + + - + + + + - + + + + + + + + + + + + + + + + - + + + + - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - + + - + - - - - - - + + + + + - - - - - + + - + - - - - + + + + + - - - - - + + - + - - - - - + + + + + - - - - - + + - + - - - - - + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + + + + + + - + + + + + + + + + + - - + + + + + - + + + + + + + + + - - + + + + + - + + + + + + + + + + - - + + + + + - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - - - - + + + + + + + - - - + + - + - + - - - + + + - + + - - - + + - + - + - - - - - + + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - + + - + - - - - - - + + + + + - - - - - + + - + - - - - + + + + + - - - - - + + - + - - - - - + + + + + - - - - - + + - + - - - - - + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + - - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + + + + +" id="HelveticaNeue-Bold-97"/> + + - + + - - + + +" id="HelveticaNeue-Bold-102"/> - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_28_0.svg b/docs/tutorial/tutorial_28_0.svg new file mode 100644 index 000000000..079181ef2 --- /dev/null +++ b/docs/tutorial/tutorial_28_0.svg @@ -0,0 +1,6331 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_29_0.svg b/docs/tutorial/tutorial_29_0.svg deleted file mode 100644 index 417e56a60..000000000 --- a/docs/tutorial/tutorial_29_0.svg +++ /dev/null @@ -1,9124 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_31_0.svg b/docs/tutorial/tutorial_31_0.svg new file mode 100644 index 000000000..99cd2b55a --- /dev/null +++ b/docs/tutorial/tutorial_31_0.svg @@ -0,0 +1,5321 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_21_1.svg b/docs/tutorial/tutorial_31_1.svg similarity index 100% rename from docs/tutorial/tutorial_21_1.svg rename to docs/tutorial/tutorial_31_1.svg diff --git a/docs/tutorial/tutorial_32_0.svg b/docs/tutorial/tutorial_32_0.svg index f9214c872..755a0de3d 100644 --- a/docs/tutorial/tutorial_32_0.svg +++ b/docs/tutorial/tutorial_32_0.svg @@ -2,7 +2,7 @@ - + - - - +" id="m0049268f75" style="stroke:#000000;stroke-width:0.6;"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -96,24 +285,24 @@ Q 4.203125 38.703125 4.203125 34.796875 z " id="HelveticaNeue-48"/> - + - - - + + - + - + - + - +" id="HelveticaNeue-50"/> - + - + - - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -387,17 +398,17 @@ z - - + - + - + - + - + @@ -458,17 +469,17 @@ z - - + - + - + - + - + @@ -537,135 +548,149 @@ z - - + - + - + - + - + + + + - + +" id="m5e3c8ad98a" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - - + - +M 50.5 16.40625 +L 42.09375 16.40625 +Q 41 11.296875 37.546875 8.796875 +Q 34.09375 6.296875 28.703125 6.296875 +Q 24.5 6.296875 21.390625 7.6875 +Q 18.296875 9.09375 16.296875 11.4375 +Q 14.296875 13.796875 13.390625 16.84375 +Q 12.5 19.90625 12.59375 23.296875 +L 51.296875 23.296875 +Q 51.5 28 50.453125 33.203125 +Q 49.40625 38.40625 46.65625 42.796875 +Q 43.90625 47.203125 39.34375 50.046875 +Q 34.796875 52.90625 27.90625 52.90625 +Q 22.59375 52.90625 18.140625 50.90625 +Q 13.703125 48.90625 10.453125 45.296875 +Q 7.203125 41.703125 5.390625 36.796875 +Q 3.59375 31.90625 3.59375 26 +Q 3.796875 20.09375 5.34375 15.09375 +Q 6.90625 10.09375 10 6.5 +Q 13.09375 2.90625 17.640625 0.90625 +Q 22.203125 -1.09375 28.40625 -1.09375 +Q 37.203125 -1.09375 43 3.296875 +Q 48.796875 7.703125 50.5 16.40625 +z +" id="HelveticaNeue-101"/> - + - - - - - + + + + + - + - + - + - + - - - - + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - - - + + + + + - - - + + - + - + - - - + + + - + - - - + + - + - + - + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - + + + - + - + - - - + + - + - + - - - + + - + - + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - - + + - + - + + + + + + + + + - - - + + - + - + + + + + + + + + - - + + + + + - + + + + + + + + + - - + + + + + - + + + + + + + + + - - + + + + + - + + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - + + + + + - + + + - + - - - - + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - + - - - + + - + - + - - - - + + + + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + + + + + + + - - - + + - + - + + + + + + + + + - - - + + - + - + - - - - + + + + + - + + + - + - - - - - + + - + - - - + + + + + - + + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + - + - - + + + + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - - + + - - + + - - + + - - + + - + - +" id="HelveticaNeue-Bold-105"/> - - - - + +" id="HelveticaNeue-Bold-104"/> - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + - - + + - - + + diff --git a/docs/tutorial/tutorial_23_0.svg b/docs/tutorial/tutorial_33_0.svg similarity index 100% rename from docs/tutorial/tutorial_23_0.svg rename to docs/tutorial/tutorial_33_0.svg diff --git a/docs/tutorial/tutorial_36_0.svg b/docs/tutorial/tutorial_36_0.svg index cfe28c9e0..17d1e5197 100644 --- a/docs/tutorial/tutorial_36_0.svg +++ b/docs/tutorial/tutorial_36_0.svg @@ -2,7 +2,7 @@ - + - - +" style="fill:#ffffff;"/> - +" id="m4fb5e73385" style="stroke:#000000;stroke-width:0.6;"/> - + @@ -96,245 +96,58 @@ Q 4.203125 38.703125 4.203125 34.796875 z " id="HelveticaNeue-48"/> - + - - + - + - +" id="HelveticaNeue-49"/> - - + + - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + - - - + + - + - + - - + + - +" id="HelveticaNeue-46"/> - - - - + + + + + - - - - - + + + + + - + - - - - - + + + + - - + + + + + - + + + + + + + + + - - + + + + + - + + + + + + + - - + + + + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - + - + - + - + - + - + - + - + - + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - +" style="fill:#ffffff;"/> - - - + + - + - + - + - - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - + - + - - - - - + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - + + + + + + + + + + + + + + + - - + + + + + + + - + - - - - - + + + + + + - - + + + + + - + - - - - - + + + + - - + + + + + - + - - - - - + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - + + + + - - + + + + + - + - - - - - + + + + + - - + + + + + - + - - - - - + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - + + + + + + + + + + + + + + + - - + + + + + + + - + - - - - - + + + + + + - - + + + + + - + - - - - - + + + + - - + + + + + - + - - - - - + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - - - + + - + - + - - - - - - + + + + + - - - + + - + - - - - - - - + - - - - - + + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - + - - - - - + + - - - - - - - - - - + - - - - - + + - - - - - - - - - - + - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - + + + - + - + - - - - - - - + + + + + + + - - - - - + + - + - + - - - + + + - - - - - - + + - + - + - + - + - - - + + - + - + - - - - - - - + + + + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + - - + + - - + - + - +" id="HelveticaNeue-Bold-105"/> + + + - - - + + + + + + +M 5.40625 51.703125 +L 5.40625 -18.09375 +L 19.59375 -18.09375 +L 19.59375 6.40625 +L 19.796875 6.40625 +Q 22.40625 2.59375 26.453125 0.640625 +Q 30.5 -1.296875 35.296875 -1.296875 +Q 41 -1.296875 45.25 0.890625 +Q 49.5 3.09375 52.34375 6.796875 +Q 55.203125 10.5 56.59375 15.296875 +Q 58 20.09375 58 25.296875 +Q 58 30.796875 56.59375 35.84375 +Q 55.203125 40.90625 52.296875 44.703125 +Q 49.40625 48.5 45 50.796875 +Q 40.59375 53.09375 34.5 53.09375 +Q 29.703125 53.09375 25.703125 51.1875 +Q 21.703125 49.296875 19.09375 45.09375 +L 18.90625 45.09375 +L 18.90625 51.703125 +z +" id="HelveticaNeue-Bold-112"/> + - - - - +" id="HelveticaNeue-Bold-102"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_26_1.svg b/docs/tutorial/tutorial_36_1.svg similarity index 100% rename from docs/tutorial/tutorial_26_1.svg rename to docs/tutorial/tutorial_36_1.svg diff --git a/docs/tutorial/tutorial_36_2.svg b/docs/tutorial/tutorial_36_2.svg new file mode 100644 index 000000000..6a7fe6479 --- /dev/null +++ b/docs/tutorial/tutorial_36_2.svg @@ -0,0 +1,6733 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_26_3.svg b/docs/tutorial/tutorial_36_3.svg similarity index 100% rename from docs/tutorial/tutorial_26_3.svg rename to docs/tutorial/tutorial_36_3.svg diff --git a/docs/tutorial/tutorial_27_0.svg b/docs/tutorial/tutorial_37_0.svg similarity index 100% rename from docs/tutorial/tutorial_27_0.svg rename to docs/tutorial/tutorial_37_0.svg diff --git a/docs/tutorial/tutorial_27_1.svg b/docs/tutorial/tutorial_37_1.svg similarity index 100% rename from docs/tutorial/tutorial_27_1.svg rename to docs/tutorial/tutorial_37_1.svg diff --git a/docs/tutorial/tutorial_39_0.svg b/docs/tutorial/tutorial_39_0.svg index 428506bb2..417e56a60 100644 --- a/docs/tutorial/tutorial_39_0.svg +++ b/docs/tutorial/tutorial_39_0.svg @@ -2,7 +2,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - - - - - + - - + - + + + + + - + + + + + + + + + + + + + + + + + - + - + + + + + + + + + + + + + + + + + + + + + + - - + - + + + + + - - + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - +" style="stroke:#ffffff;stroke-linejoin:miter;stroke-width:1.5;"/> + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + + - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + + - - + + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - +M 5.40625 51.703125 +L 5.40625 -18.09375 +L 19.59375 -18.09375 +L 19.59375 6.40625 +L 19.796875 6.40625 +Q 22.40625 2.59375 26.453125 0.640625 +Q 30.5 -1.296875 35.296875 -1.296875 +Q 41 -1.296875 45.25 0.890625 +Q 49.5 3.09375 52.34375 6.796875 +Q 55.203125 10.5 56.59375 15.296875 +Q 58 20.09375 58 25.296875 +Q 58 30.796875 56.59375 35.84375 +Q 55.203125 40.90625 52.296875 44.703125 +Q 49.40625 48.5 45 50.796875 +Q 40.59375 53.09375 34.5 53.09375 +Q 29.703125 53.09375 25.703125 51.1875 +Q 21.703125 49.296875 19.09375 45.09375 +L 18.90625 45.09375 +L 18.90625 51.703125 +z +" id="HelveticaNeue-Bold-112"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_42_0.svg b/docs/tutorial/tutorial_42_0.svg new file mode 100644 index 000000000..f9214c872 --- /dev/null +++ b/docs/tutorial/tutorial_42_0.svg @@ -0,0 +1,2000 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_44_1.svg b/docs/tutorial/tutorial_44_1.svg index 1e2baef4d..85e1ff443 100644 --- a/docs/tutorial/tutorial_44_1.svg +++ b/docs/tutorial/tutorial_44_1.svg @@ -2,7 +2,7 @@ - + - +" style="fill:#dee2e6;"/> - +" style="fill:url(#h49df5de922);"/> - +" id="m5fcc53849d" style="stroke:#000000;stroke-width:1.5;"/> - + - +" id="DejaVuSans-48"/> - - + + - - + - + - - +" id="DejaVuSans-50"/> - - - - + + + - - + - + - +" id="DejaVuSans-52"/> - - - - + + + - - + - + - +" id="DejaVuSans-54"/> - - - - + + + - - + - + - +" id="DejaVuSans-56"/> - - - - + + + - - - - - - - - - - + - - + + - - - - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + + + + + + + + + + + + + + + + + + - - + - + +" id="m6dd9679cca" style="stroke:#1c7ed6;stroke-width:1.5;"/> + + + + + + + + - + - - - + + + + + + + + + + + + + + - - + + + + + + - + - - - - - - + + + + + + + + + + - - + - - - - - - - - - - - - - - + - - - - - - + + + + + + + + + + - - - + + + + + + + - + - - - - - - + + + + + + + + + + - + - - + - - - - - - - + + + + + + + + + + + + + + + - - + + +" id="m13c538a44e" style="stroke:#1c7ed6;stroke-width:1.2;"/> - + + + + + + + + + + + + + + + + + + + + + - + + + + + + - + - + + + + + + - + - + + + + + + - + - + + + + + + - + - + + + + + + - + - + - + + + + + + - + + + + + + - + - + + + + + + - + - + + + + + + - + - + - + + + + + + - + - + - - - + - + - - + + - + - - - + - + - - + + - - - - - - - - - +" id="DejaVuSans-121"/> - - - - - - - - - - - - - + + + + + + + + - - + + + + + + + + + + + + + + + + + - + - + - + - + - +" style="fill:url(#h49df5de922);"/> - - - + + - + - + - + - - + + - - - + + - + - + - - - - - - + + + + + - - - + + - + - + - - - - - - + + + + + - - - + + - + - + - - - - - - + + + + + - - - + + - + - + - - - - - - + + + + + - - - - - + + - + - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + - + - - - - - + + + + + + + + + + - - - + + - + - + - - - - - - - - + + + + + - - - + + - + - + - - - - - - - + + + + - - - + + - + - + - - - - - - + + + + - - - + + - + - + - - - - + + + + - - - + + - + - + - - - - - + + + + - - - - - + + - + - - - - - - + + + + + - - - - - + + - + - - - - - - - + + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + - + + + + + + + + + + - + - + + + + + + + + + + + - + - + + + + + + + + - + - + + + + + + + + - + - + + + + + + + + - + - + + + + + + + + + + + - + + + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +M 9.421875 75.984375 +L 18.40625 75.984375 +L 18.40625 64.59375 +L 9.421875 64.59375 +z +" id="DejaVuSans-105"/> - - - - - - - - - - - - + + + + + + + + + + + + + + + - - - - - + + - - + + - - + + - - + + - - + + - + - + - + +" id="DejaVuSans-Bold-121"/> + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - + + + + + + + + diff --git a/docs/tutorial/tutorial_48_0.svg b/docs/tutorial/tutorial_48_0.svg new file mode 100644 index 000000000..cfe28c9e0 --- /dev/null +++ b/docs/tutorial/tutorial_48_0.svg @@ -0,0 +1,4111 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_49_0.svg b/docs/tutorial/tutorial_49_0.svg deleted file mode 100644 index c65724761..000000000 --- a/docs/tutorial/tutorial_49_0.svg +++ /dev/null @@ -1,5195 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_51_0.svg b/docs/tutorial/tutorial_51_0.svg new file mode 100644 index 000000000..428506bb2 --- /dev/null +++ b/docs/tutorial/tutorial_51_0.svg @@ -0,0 +1,2714 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_41_0.svg b/docs/tutorial/tutorial_53_0.svg similarity index 100% rename from docs/tutorial/tutorial_41_0.svg rename to docs/tutorial/tutorial_53_0.svg diff --git a/docs/tutorial/tutorial_56_1.svg b/docs/tutorial/tutorial_56_1.svg new file mode 100644 index 000000000..1e2baef4d --- /dev/null +++ b/docs/tutorial/tutorial_56_1.svg @@ -0,0 +1,3239 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_45_0.svg b/docs/tutorial/tutorial_57_0.svg similarity index 100% rename from docs/tutorial/tutorial_45_0.svg rename to docs/tutorial/tutorial_57_0.svg diff --git a/docs/tutorial/tutorial_46_0.svg b/docs/tutorial/tutorial_58_0.svg similarity index 100% rename from docs/tutorial/tutorial_46_0.svg rename to docs/tutorial/tutorial_58_0.svg diff --git a/docs/tutorial/tutorial_61_0.svg b/docs/tutorial/tutorial_61_0.svg index 0a3621dfb..c65724761 100644 --- a/docs/tutorial/tutorial_61_0.svg +++ b/docs/tutorial/tutorial_61_0.svg @@ -2,7 +2,7 @@ - + - +" style="fill:#ffffff;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + - + - - + - + - + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + +" id="HelveticaNeue-57"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - + + + + + + + + + + + + - - - - - - - - - - - +" style="fill:#e2f4ff;"/> - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - +" id="HelveticaNeue-101"/> + + + + + + + + - - - - - + + + + + + + + + + + + + + - - - - +" id="HelveticaNeue-118"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + - - - - - - - - - - - + + + + + - - - + + +" style="fill:#e2f4ff;"/> - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" id="HelveticaNeue-52"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - + + - - - - + + - - - - - +" style="fill:#e2f4ff;"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - +" id="HelveticaNeue-58"/> + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" id="HelveticaNeue-56"/> + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - +" style="fill:#e2f4ff;"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + - - - - - + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - +" id="HelveticaNeue-105"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - - - - + + + + + + + + + + + + + - - + + - + - - - - - - + + + + + + + + + + + - - + + - + - - - - - - + + + + + + + + + + + + + + - - + + - + - - - - - - + + + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + - + - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - - - + + + + + + + + - - + + + + + - + - - - - + + + + + + + + - - - - - - - - - + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - + + + + + - + +" id="HelveticaNeue-Bold-101"/> - + +" id="HelveticaNeue-Bold-80"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_64_0.svg b/docs/tutorial/tutorial_64_0.svg deleted file mode 100644 index 003033bec..000000000 --- a/docs/tutorial/tutorial_64_0.svg +++ /dev/null @@ -1,62617 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_52_1.svg b/docs/tutorial/tutorial_64_1.svg similarity index 100% rename from docs/tutorial/tutorial_52_1.svg rename to docs/tutorial/tutorial_64_1.svg diff --git a/docs/tutorial/tutorial_52_2.svg b/docs/tutorial/tutorial_64_2.svg similarity index 100% rename from docs/tutorial/tutorial_52_2.svg rename to docs/tutorial/tutorial_64_2.svg diff --git a/docs/tutorial/tutorial_53_1.svg b/docs/tutorial/tutorial_65_1.svg similarity index 100% rename from docs/tutorial/tutorial_53_1.svg rename to docs/tutorial/tutorial_65_1.svg diff --git a/docs/tutorial/tutorial_67_0.svg b/docs/tutorial/tutorial_67_0.svg index 6ef773e76..e2607e8ff 100644 --- a/docs/tutorial/tutorial_67_0.svg +++ b/docs/tutorial/tutorial_67_0.svg @@ -2,7 +2,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - +" style="fill:#ffffff;"/> - - - - - - + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - +" id="HelveticaNeue-52"/> + + + + + + + - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - - - + + + + + + + + + + + + - - - - - - + + + + + + + - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - + + + + + + - - - - - - - - + + + + + + - - - - - - + + + + + + - - - - - - - - - - - + + + + + + - - - - - - - - + + + + + + - - - - - - - - - - - + + + + + + - - - - - - - - - - - + + + + + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + - - - + - + - + - - + + - - + + - - + + +" style="fill:#ffffff;"/> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + + + - - - - - - - - - - - - - - - - - - - - - + - - - + + - - - + +" id="HelveticaNeue-Bold-110"/> + + + + + + + + + + + + + - - + + - - + + - - + + +" style="fill:#ffffff;"/> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + +" style="fill:#ffffff;"/> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + +" style="fill:#ffffff;"/> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + +" id="HelveticaNeue-49"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - - - - - - - - - - +" style="fill:#ffffff;"/> - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - - + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - + - - + - - - - - - - - + + + + - - - - - + + + + + + + + + + + + + + + + - - - - - - - - + + + + + + + + + + + + + + + - - - - - - - - + + + + + + - - - - - - - - + + + + + + - - - - - - - - + + + + + + - - - - - - - - - + + + + + + - - - - - - - - + + + + + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + + - - - - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + + - - - - - - - - + + + + + + + + + - - - - - - - - - - - + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - - - - - - - - - - + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + - - + + diff --git a/docs/tutorial/tutorial_68_0.svg b/docs/tutorial/tutorial_68_0.svg new file mode 100644 index 000000000..916a52828 --- /dev/null +++ b/docs/tutorial/tutorial_68_0.svg @@ -0,0 +1,13254 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_70_0.svg b/docs/tutorial/tutorial_70_0.svg new file mode 100644 index 000000000..408c23223 --- /dev/null +++ b/docs/tutorial/tutorial_70_0.svg @@ -0,0 +1,3476 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_58_3.svg b/docs/tutorial/tutorial_75_3.svg similarity index 100% rename from docs/tutorial/tutorial_58_3.svg rename to docs/tutorial/tutorial_75_3.svg diff --git a/docs/tutorial/tutorial_58_4.svg b/docs/tutorial/tutorial_75_4.svg similarity index 100% rename from docs/tutorial/tutorial_58_4.svg rename to docs/tutorial/tutorial_75_4.svg diff --git a/docs/tutorial/tutorial_78_0.svg b/docs/tutorial/tutorial_78_0.svg new file mode 100644 index 000000000..0a3621dfb --- /dev/null +++ b/docs/tutorial/tutorial_78_0.svg @@ -0,0 +1,10708 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_61_1.svg b/docs/tutorial/tutorial_78_1.svg similarity index 100% rename from docs/tutorial/tutorial_61_1.svg rename to docs/tutorial/tutorial_78_1.svg diff --git a/docs/tutorial/tutorial_81_0.svg b/docs/tutorial/tutorial_81_0.svg index f55c08d6b..003033bec 100644 --- a/docs/tutorial/tutorial_81_0.svg +++ b/docs/tutorial/tutorial_81_0.svg @@ -2,7 +2,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + - + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - + - + - + - + - - - - + + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" style="fill:#001146;"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - + + - - + + + + + - - - - - - - - - - - - - - - - - - - + + + + + + - - + + - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + - - + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - + + - - - + +" id="HelveticaNeue-Bold-114"/> + - - - + + + + + +" id="HelveticaNeue-Bold-109"/> + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_84_0.svg b/docs/tutorial/tutorial_84_0.svg index 7f8943ef6..6ef773e76 100644 --- a/docs/tutorial/tutorial_84_0.svg +++ b/docs/tutorial/tutorial_84_0.svg @@ -2,7 +2,7 @@ - + - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - +" id="HelveticaNeue-87"/> + + + + + + + - - - - - - - - - - - - - - - - - - - - + + + + + + + + + - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + - - - - - - + + + + + + + + - - - - - - + + + + + + - - - - - - + + + + + + + + + + + - - - - - - + + + + + + + + - - - - - - + + + + + + + + + + + - - - - + + + - + + + + + + + + + + + + - + - + + + - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +" id="HelveticaNeue-120"/> + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +"/> - + - + - + - + - - - - - + + + + - + + + - - + + + - + + + - - - - - - - - - - - - - +"/> - - - + - - - + - - - - + +"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - - + - - - + - - - - + +"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - - + - - - + - - - - + +"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +"/> - - + + - - + + - - + + - - + + - - - - - - - - - - - - - - - + + - - - - + +"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + - - + + - - + + - - + + - - - - + +"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - + - - + - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + - - - - - - + + + + + + + + - - - - - - + + + + + + + + - - - - - - + + + + + + + + - - - - - - + + + + + + + + + - - - - - - + + + + + + + + + - - - - - - + + + + + + + + + - - - - - - + + + + + + + + + - - - - - - + + + + + + + + - - - - - - + + + + + + + + + + + - - + + + + + + + + - - + + + + + + + + - - + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + + + + + + + + + - - +M -1.796875 -6 +L -1.796875 -17.703125 +Q 0.203125 -18.09375 2.703125 -18.09375 +Q 8.09375 -18.09375 11.59375 -17.140625 +Q 15.09375 -16.203125 17.140625 -14.25 +Q 19.203125 -12.296875 20.046875 -9.390625 +Q 20.90625 -6.5 20.90625 -2.5 +L 20.90625 51.703125 +L 6.703125 51.703125 +L 6.703125 -1.796875 +Q 6.703125 -4.703125 5.046875 -5.546875 +Q 3.40625 -6.40625 1.203125 -6.40625 +Q -0.703125 -6.40625 -1.796875 -6 +z +" id="HelveticaNeue-Bold-106"/> + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - + + - - + + diff --git a/docs/tutorial/tutorial_67_1.svg b/docs/tutorial/tutorial_84_1.svg similarity index 100% rename from docs/tutorial/tutorial_67_1.svg rename to docs/tutorial/tutorial_84_1.svg diff --git a/docs/tutorial/tutorial_85_0.svg b/docs/tutorial/tutorial_85_0.svg deleted file mode 100644 index 852bc118a..000000000 --- a/docs/tutorial/tutorial_85_0.svg +++ /dev/null @@ -1,10979 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_70_1.svg b/docs/tutorial/tutorial_87_1.svg similarity index 100% rename from docs/tutorial/tutorial_70_1.svg rename to docs/tutorial/tutorial_87_1.svg diff --git a/docs/tutorial/tutorial_89_0.svg b/docs/tutorial/tutorial_89_0.svg deleted file mode 100644 index c6c9ec360..000000000 --- a/docs/tutorial/tutorial_89_0.svg +++ /dev/null @@ -1,11768 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_73_0.svg b/docs/tutorial/tutorial_90_0.svg similarity index 100% rename from docs/tutorial/tutorial_73_0.svg rename to docs/tutorial/tutorial_90_0.svg diff --git a/docs/tutorial/tutorial_91_0.svg b/docs/tutorial/tutorial_91_0.svg deleted file mode 100644 index 0a1ddda68..000000000 --- a/docs/tutorial/tutorial_91_0.svg +++ /dev/null @@ -1,8595 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_76_0.svg b/docs/tutorial/tutorial_93_0.svg similarity index 100% rename from docs/tutorial/tutorial_76_0.svg rename to docs/tutorial/tutorial_93_0.svg diff --git a/docs/tutorial/tutorial_94_0.svg b/docs/tutorial/tutorial_94_0.svg deleted file mode 100644 index af9bc66d1..000000000 --- a/docs/tutorial/tutorial_94_0.svg +++ /dev/null @@ -1,3839 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial/tutorial_96_0.svg b/docs/tutorial/tutorial_96_0.svg new file mode 100644 index 000000000..f55c08d6b --- /dev/null +++ b/docs/tutorial/tutorial_96_0.svg @@ -0,0 +1,4613 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docs/tutorial/tutorial_97_0.svg b/docs/tutorial/tutorial_97_0.svg deleted file mode 100644 index 9f04d194c..000000000 --- a/docs/tutorial/tutorial_97_0.svg +++ /dev/null @@ -1,5338 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/tutorial1.rst b/docs/tutorial1.rst index 2d50984bf..16c2fbad9 100644 --- a/docs/tutorial1.rst +++ b/docs/tutorial1.rst @@ -183,60 +183,237 @@ is demonstrated in the below example. .. image:: tutorial/tutorial_10_0.svg -The rc object -------------- +Plotting commands +----------------- + +In ProPlot, axes plotting commands like +`~matplotlib.axes.Axes.contourf`, +`~matplotlib.axes.Axes.pcolormesh`, `~matplotlib.axes.Axes.plot` +work just like they do in matplotlib, but with several new features. +There are also a few new plotting commands, like +`~proplot.axes.Axes.heatmap`, `~proplot.axes.Axes.area`, and +`~proplot.axes.Axes.areax`. For details on these features, see +:ref:`Plotting wrappers` and :ref:`Color usage`. -A special object named `~proplot.rctools.rc`, belonging to the -`~proplot.rctools.rc_configurator` class, is created whenever you -import ProPlot. This object gives you advanced control over the look of -your plots – it is your **one-stop shop for changing global settings**. -`~proplot.rctools.rc` can be used to change matplotlib -`rcParams `__ settings, -custom ProPlot :ref:`rcExtraParams` settings, and special -:ref:`rcGlobals` meta-settings. See the `~proplot.rctools` -documentation for more info. +.. code:: ipython3 -To modify a setting for just one subplot, pass it to the -`~proplot.axes.Axes.format` command. To reset everything to the -default state, use `~proplot.rctools.rc_configurator.reset`. To -temporarily modify global settings for a block of code, use -`~proplot.rctools.rc_configurator.context`. + import proplot as plot + f, axs = plot.subplots(axwidth=1.5, ncols=2, nrows=2, share=False) + cycle = plot.Cycle('blues', 5) + data = np.random.rand(10,10) + axs[0].plot(data, cycle=cycle, lw=3) + for i in range(5): + axs[1].scatter(data[:,i], data[:,5+i], s=50, cycle=cycle) + axs[2].pcolormesh(data, cmap='reds', colorbar='b') + axs[3].contourf(data, cmap='reds', colorbar='b') + axs.format(suptitle='Super title', title='Title') + + + +.. image:: tutorial/tutorial_12_0.svg + + +Axes colorbars and legends +-------------------------- + +Drawing colorbars and legends is a much smoother experience with +ProPlot. To draw a colorbar or legend along the outside of an axes, use +the `~proplot.axes.Axes.colorbar` and `~proplot.axes.Axes.legend` +``Axes`` methods with e.g. ``loc='right'``. If you do this multiple +times, the colorbars and legends will be “stacked”. Room for colorbars +and legends is allocated from the space between subplot rows and columns +– it is no longer stolen from the axes. + +To plot data and draw a colorbar or legend in one go, pass e.g. +``colorbar='right'`` to any method wrapped by +`~proplot.wrappers.cmap_wrapper`, or e.g. ``colorbar='right'`` or +``legend='right'`` to any method wrapped by +`~proplot.wrappers.cycle_wrapper`. To draw an *inset* colorbar, use +one of the *inset* locations, e.g. ``colorbar='upper right'`` or +``colorbar='ur'``. Inset colorbars have optional rectangular +backgrounds, just like inset legends. .. code:: ipython3 import proplot as plot import numpy as np - # A bunch of different ways to update settings - plot.rc.reset() - plot.rc.cycle = 'colorblind' - plot.rc.update({'fontname': 'DejaVu Sans'}) - plot.rc['figure.facecolor'] = 'gray3' - plot.rc['axes.facecolor'] = 'gray5' - with plot.rc.context(linewidth=1.5): # above mods are persistent, context mod only applies to figure - f, axs = plot.subplots(ncols=2, aspect=1, width=6, span=False, sharey=2) - # Make plot - N, M = 100, 6 - values = np.arange(1,M+1) - cycle = plot.Cycle('C0', 'C1', M, fade=80) - for i,ax in enumerate(axs): - data = np.cumsum(np.random.rand(N,M)-0.5, axis=0) - lines = ax.plot(data, linewidth=3, cycle=cycle) # see "Changing the color cycle" for details - axs.format(ytickloc='both', ycolor='blue7', - xlabel='x label', ylabel='y label', - yticklabelloc='both', - suptitle='Applying new rc settings', - patch_kw={'hatch':'xxx', 'edgecolor':'w'}) - ay = axs[-1].twinx() - ay.format(ycolor='r', linewidth=1.5, ylabel='secondary axis') - ay.plot((np.random.rand(100)-0.2).cumsum(), color='r', lw=3) + with plot.rc.context(abc=True): + f, axs = plot.subplots(ncols=2, share=0) + # Colorbars + ax = axs[0] + m = ax.heatmap(np.random.rand(10,10), colorbar='t', cmap='dusk') + ax.colorbar(m, loc='r') + ax.colorbar(m, loc='ll', label='colorbar label') + ax.format(title='Axes colorbars', suptitle='Axes colorbars and legends demo') + # Legends + ax = axs[1] + ax.format(title='Axes legends', titlepad='0em') + hs = ax.plot((np.random.rand(10,5)-0.5).cumsum(axis=0), lw=3, legend='t', cycle='sharp', + labels=list('abcde'), legend_kw={'ncols':5, 'frame':False}) + ax.legend(hs, loc='r', ncols=1, frame=False) + ax.legend(hs, loc='ll', label='legend label') + axs.format(xlabel='xlabel', ylabel='ylabel') +.. image:: tutorial/tutorial_14_0.svg + + +.. code:: ipython3 + + import proplot as plot + import numpy as np + f, axs = plot.subplots(nrows=2, share=0, axwidth='4cm', panelpad='1em') + axs.format(suptitle='Stacked colorbars demo') + N = 10 + for j,ax in enumerate(axs): + ax.format(xlabel='data', xlocator=np.linspace(0, 0.8, 5), title=f'Subplot #{j+1}') + for i,(x0,y0,x1,y1,cmap,scale) in enumerate(((0,0.5,1,1,'grays',0.5), (0,0,0.5,0.5,'reds',1), (0.5,0,1,0.5,'blues',2))): + if j == 1 and i == 0: + continue + data = np.random.rand(N,N)*scale + x, y = np.linspace(x0, x1, 11), np.linspace(y0, y1, 11) + m = ax.pcolormesh(x, y, data, cmap=cmap, levels=np.linspace(0,scale,11)) + ax.colorbar(m, loc='l', label=f'dataset #{i+1}') + + + +.. image:: tutorial/tutorial_15_0.svg + + +Figure colorbars and legends +---------------------------- + +To draw a colorbar or legend along the edge of a figure, use the +`~proplot.subplots.Figure.colorbar` or +`~proplot.subplots.Figure.legend` ``Figure`` methods. The colorbar or +legend will be aligned between edges of the subplot grid, instead of the +figure bounds. + +To draw a colorbar or legend beneath particular row(s) and column(s) of +the subplot grid, use the ``row``, ``rows``, ``col``, or ``cols`` +keyword arguments. Pass an integer to draw the colorbar or legend beside +a single row or column, or pass a tuple to draw it beside a range of +rows or columns. + +.. code:: ipython3 + + import proplot as plot + import numpy as np + f, axs = plot.subplots(ncols=3, nrows=3, axwidth=1.2) + m = axs.pcolormesh(np.random.rand(20,20), cmap='grays', levels=np.linspace(0,1,11), extend='both')[0] + axs.format(suptitle='Figure colorbars and legends demo', abc=True, abcloc='l', abcformat='a.', xlabel='xlabel', ylabel='ylabel') + f.colorbar(m, label='label', ticks=0.5, loc='b', col=1) + f.colorbar(m, label='label', ticks=0.2, loc='b', cols=(2,3)) + f.colorbar(m, label='label', ticks=0.1, loc='r', length=0.7) + + + + + + + +.. image:: tutorial/tutorial_17_1.svg + + +.. code:: ipython3 + + import proplot as plot + import numpy as np + f, axs = plot.subplots(ncols=4, axwidth=1.3, share=0, wspace=0.3) + data = (np.random.rand(50,50)-0.1).cumsum(axis=0) + m = axs[:2].contourf(data, cmap='grays', extend='both') + cycle = plot.colors('grays', 5) + hs = [] + for abc,color in zip('ABCDEF',cycle): + h = axs[2:].plot(np.random.rand(10), lw=3, color=color, label=f'line {abc}') + hs.extend(h[0]) + f.colorbar(m[0], length=0.8, label='label', loc='b', cols=(1,2)) + f.legend(hs, ncols=5, label='label', frame=True, loc='b', cols=(3,4)) + axs.format(suptitle='Figure colorbars and legends demo', abc=True, abcloc='ul', abcformat='A') + for ax,title in zip(axs, ['2D dataset #1', '2D dataset #2', 'Line set #1', 'Line set #2']): + ax.format(xlabel='xlabel', title=title) + + + +.. image:: tutorial/tutorial_18_0.svg +New colorbar and legend features +-------------------------------- +The `~proplot.subplots.Figure` and `~proplot.axes.Axes` ``colorbar`` +and ``legend`` methods are wrapped by +`~proplot.wrappers.colorbar_wrapper` and +`~proplot.wrappers.legend_wrapper`, which add several new features. -.. image:: tutorial/tutorial_12_1.svg +`~proplot.wrappers.colorbar_wrapper` can draw colorbars from *lists of +colors* or *lists of artists* by passing a list instead of a “mappable” +object – a colormap is constructed from the corresponding colors +on-the-fly. To change outline, divider, tick location, tick label, and +colorbar label settings, just pass the appropriate keyword arg to +`~proplot.wrappers.colorbar_wrapper`. + +`~proplot.wrappers.legend_wrapper` can draw legends with *centered +legend rows*, either by passing ``center=True`` or by passing *list of +lists* of plot handles. This is accomplished by stacking multiple +single-row, horizontally centered legends, then manually adding an +encompassing legend frame. You can also switch between row-major and +column-major order for legend entries (the new default is row-major), +and modify legend text properties and handle properties. + +.. code:: ipython3 + + import proplot as plot + import numpy as np + f, axs = plot.subplots(share=0, ncols=2) + ax = axs[0] + data = 1 + (np.random.rand(12,10)-0.45).cumsum(axis=0) + cycle = plot.Cycle('algae') + hs = ax.plot(data, lw=4, cycle=cycle, colorbar='lr', colorbar_kw={'length':'14em', 'label':'numeric values'}) + ax.colorbar(hs, loc='t', values=np.linspace(0.5,9.5,10)*2, label='alt numeric values', ticks=2) + ax = axs[1] + m = ax.contourf(data.T, extend='both', cmap='algae') + f.colorbar(m, length=0.6, loc='b', label='flipped tick location', tickloc='top', grid=True) + ax.colorbar(m, loc='ul', length=1, ticks=0.5, tickminor=True, extendrect=True, + label='changing colors', labelcolor='gray7', labelweight='bold', + linewidth=1, edgecolor='gray7', ticklabelcolor='gray7', alpha=0.5) + axs.format(suptitle='Colorbar formatting demo', xlabel='xlabel', ylabel='ylabel') + + + +.. image:: tutorial/tutorial_21_0.svg + + +.. code:: ipython3 + + import proplot as plot + import numpy as np + plot.rc.cycle = 'contrast' + labels = ['a', 'bb', 'ccc', 'dddd', 'eeeee'] + f, axs = plot.subplots(ncols=2, span=False, share=1) + hs1, hs2 = [], [] + # Plot lines and add to legends on-the-fly + for i,label in enumerate(labels): + data = (np.random.rand(20)-0.45).cumsum(axis=0) + h1 = axs[0].plot(data, lw=4, label=label, legend='ul', + legend_kw={'order':'F', 'title':'column major'}) # add to legend in upper left + hs1.extend(h1) + h2 = axs[1].plot(data, lw=4, label=label, legend='r', cycle='floral', + legend_kw={'ncols':1, 'frame':False, 'title':'no frame'}) # add to legend in right panel + hs2.extend(h2) + # Outer legends + ax = axs[0] + ax.legend(hs1, loc='b', ncols=3, linewidth=2, title='row major', order='C', + edgecolor='gray4', facecolor='gray2') + ax = axs[1] + ax.legend(hs2, loc='b', ncols=3, center=True, title='centered legend', + handlelength=1) # also works! + axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Legend formatting demo') + + + +.. image:: tutorial/tutorial_22_0.svg Pandas and xarray integration @@ -301,7 +478,7 @@ and :ref:`On-the-fly axes panels`. -.. image:: tutorial/tutorial_16_2.svg +.. image:: tutorial/tutorial_26_2.svg .. code:: ipython3 @@ -338,7 +515,7 @@ and :ref:`On-the-fly axes panels`. -.. image:: tutorial/tutorial_18_0.svg +.. image:: tutorial/tutorial_28_0.svg Automatic subplot spacing @@ -383,11 +560,11 @@ instead. -.. image:: tutorial/tutorial_21_0.svg +.. image:: tutorial/tutorial_31_0.svg -.. image:: tutorial/tutorial_21_1.svg +.. image:: tutorial/tutorial_31_1.svg .. code:: ipython3 @@ -403,7 +580,7 @@ instead. -.. image:: tutorial/tutorial_22_0.svg +.. image:: tutorial/tutorial_32_0.svg .. code:: ipython3 @@ -421,7 +598,7 @@ instead. -.. image:: tutorial/tutorial_23_0.svg +.. image:: tutorial/tutorial_33_0.svg Axis sharing and spanning @@ -454,19 +631,19 @@ example for details. -.. image:: tutorial/tutorial_26_0.svg +.. image:: tutorial/tutorial_36_0.svg -.. image:: tutorial/tutorial_26_1.svg +.. image:: tutorial/tutorial_36_1.svg -.. image:: tutorial/tutorial_26_2.svg +.. image:: tutorial/tutorial_36_2.svg -.. image:: tutorial/tutorial_26_3.svg +.. image:: tutorial/tutorial_36_3.svg .. code:: ipython3 @@ -484,11 +661,11 @@ example for details. -.. image:: tutorial/tutorial_27_0.svg +.. image:: tutorial/tutorial_37_0.svg -.. image:: tutorial/tutorial_27_1.svg +.. image:: tutorial/tutorial_37_1.svg A-b-c subplot labels @@ -512,7 +689,7 @@ the ``abc.format`` `~proplot.rctools.rc` option. See -.. image:: tutorial/tutorial_29_0.svg +.. image:: tutorial/tutorial_39_0.svg Arbitrary physical units @@ -535,6 +712,62 @@ millimeters, and pixels). -.. image:: tutorial/tutorial_32_0.svg +.. image:: tutorial/tutorial_42_0.svg + + +The rc object +------------- + +A special object named `~proplot.rctools.rc`, belonging to the +`~proplot.rctools.rc_configurator` class, is created whenever you +import ProPlot. This object gives you advanced control over the look of +your plots – it is your **one-stop shop for changing global settings**. +`~proplot.rctools.rc` can be used to change matplotlib +`rcParams `__ settings, +custom ProPlot :ref:`rcExtraParams` settings, and special +:ref:`rcGlobals` meta-settings. See the `~proplot.rctools` +documentation for more info. + +To modify a setting for just one subplot, pass it to the +`~proplot.axes.Axes.format` command. To reset everything to the +default state, use `~proplot.rctools.rc_configurator.reset`. To +temporarily modify global settings for a block of code, use +`~proplot.rctools.rc_configurator.context`. + +.. code:: ipython3 + + import proplot as plot + import numpy as np + # A bunch of different ways to update settings + plot.rc.reset() + plot.rc.cycle = 'colorblind' + plot.rc.update({'fontname': 'DejaVu Sans'}) + plot.rc['figure.facecolor'] = 'gray3' + plot.rc['axes.facecolor'] = 'gray5' + with plot.rc.context(linewidth=1.5): # above mods are persistent, context mod only applies to figure + f, axs = plot.subplots(ncols=2, aspect=1, width=6, span=False, sharey=2) + # Make plot + N, M = 100, 6 + values = np.arange(1,M+1) + cycle = plot.Cycle('C0', 'C1', M, fade=80) + for i,ax in enumerate(axs): + data = np.cumsum(np.random.rand(N,M)-0.5, axis=0) + lines = ax.plot(data, linewidth=3, cycle=cycle) # see "Changing the color cycle" for details + axs.format(ytickloc='both', ycolor='blue7', + xlabel='x label', ylabel='y label', + yticklabelloc='both', + suptitle='Applying new rc settings', + patch_kw={'hatch':'xxx', 'edgecolor':'w'}) + ay = axs[-1].twinx() + ay.format(ycolor='r', linewidth=1.5, ylabel='secondary axis') + ay.plot((np.random.rand(100)-0.2).cumsum(), color='r', lw=3) + + + + + + + +.. image:: tutorial/tutorial_44_1.svg diff --git a/docs/tutorial2.rst b/docs/tutorial2.rst index 225ce838a..32a04c07e 100644 --- a/docs/tutorial2.rst +++ b/docs/tutorial2.rst @@ -43,7 +43,7 @@ usually what you’ll want in this context. See -.. image:: tutorial/tutorial_36_0.svg +.. image:: tutorial/tutorial_48_0.svg Axis tick label formatting @@ -72,7 +72,7 @@ some data range*, as demonstrated below. See -.. image:: tutorial/tutorial_39_0.svg +.. image:: tutorial/tutorial_51_0.svg ProPlot also lets you easily change the axis formatter with @@ -107,7 +107,7 @@ See `~proplot.axes.CartesianAxes.format` and -.. image:: tutorial/tutorial_41_0.svg +.. image:: tutorial/tutorial_53_0.svg New and old axis scales @@ -157,7 +157,7 @@ labeling spectral coordinates (this is more useful with the -.. image:: tutorial/tutorial_44_1.svg +.. image:: tutorial/tutorial_56_1.svg .. code:: ipython3 @@ -187,7 +187,7 @@ labeling spectral coordinates (this is more useful with the -.. image:: tutorial/tutorial_45_0.svg +.. image:: tutorial/tutorial_57_0.svg .. code:: ipython3 @@ -227,7 +227,7 @@ labeling spectral coordinates (this is more useful with the -.. image:: tutorial/tutorial_46_0.svg +.. image:: tutorial/tutorial_58_0.svg Datetime axis formatting @@ -271,7 +271,7 @@ details. -.. image:: tutorial/tutorial_49_0.svg +.. image:: tutorial/tutorial_61_0.svg Dual unit axes @@ -323,11 +323,11 @@ pass the name of any registered “axis scale” to the ``xscale`` or -.. image:: tutorial/tutorial_52_1.svg +.. image:: tutorial/tutorial_64_1.svg -.. image:: tutorial/tutorial_52_2.svg +.. image:: tutorial/tutorial_64_2.svg .. code:: ipython3 @@ -358,6 +358,94 @@ pass the name of any registered “axis scale” to the ``xscale`` or -.. image:: tutorial/tutorial_53_1.svg +.. image:: tutorial/tutorial_65_1.svg + + +Panel axes +---------- + +It is common to need “panels” for plotting secondary 1-dimensional +datasets or summary statistics along the sides of axes. With ProPlot, +you can generate “panels” using the `~proplot.axes.Axes.panel` or +`~proplot.axes.Axes.panel_axes` commands. The axes returned by panels +are instances of `~proplot.axes.CartesianAxes`. + +To generate “stacked” panels, call `~proplot.axes.Axes.panel` or +`~proplot.axes.Axes.panel_axes` more than once. To include panels when +centering spanning axis labels and super titles, pass +``includepanels=True`` to `~proplot.subplots.subplots`. + +.. code:: ipython3 + + import proplot as plot + f, axs = plot.subplots(axwidth=1.2, nrows=2, ncols=2, share=0) + for ax,side in zip(axs,'tlbr'): + ax.panel_axes(side) + axs.format(title='Title', suptitle='Panel axes demo', collabels=['Column 1','Column 2'], + abcloc='ul', titleloc='uc', xlabel='xlabel', ylabel='ylabel', abc=True, top=False) + axs.format(xlim=(0,1), ylim=(0,1), ylocator=plot.arange(0.2,0.8,0.2), xlocator=plot.arange(0.2,0.8,0.2)) + + + +.. image:: tutorial/tutorial_67_0.svg + + +.. code:: ipython3 + + import proplot as plot + import numpy as np + data = (np.random.rand(20,20)-0.1).cumsum(axis=1) + f, axs = plot.subplots(axwidth=1.5, nrows=2, ncols=2, share=0, panelpad=0.1, includepanels=True) + maxs = axs.panel('r', space=0) + saxs = axs.panel('r', space=0, share=False) + axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Panel axes demo') + for i,ax in enumerate(axs): + ax.format(title=f'Dataset {i+1}') + axs.contourf(data, cmap='glacial', levels=plot.arange(-1,11), + colorbar='b', colorbar_kw={'label':'cbar'}, extend='both') + maxs.plot(data.mean(axis=1), np.arange(20), color='gray7') + maxs.format(title='Mean') + saxs.plot(data.std(axis=1), np.arange(20), color='gray7', ls='--') + saxs.format(title='Stdev') + + + +.. image:: tutorial/tutorial_68_0.svg + + +Inset axes +---------- + +`Inset +axes `__ +in ProPlot can be generated with the `~proplot.axes.Axes.inset` or +`~proplot.axes.Axes.inset_axes` command. The generated axes are +instances of `~proplot.axes.CartesianAxes`, and therefore can be +modified with the `~proplot.axes.CartesianAxes.format` command. +Passing ``zoom=True`` to `~proplot.axes.Axes.inset` draws a “zoom +indication” with `~matplotlib.axes.Axes.indicate_inset_zoom`, and the +“zoom indication” lines are *updated* when the axis limits of the parent +axes change. To modify the “zoom indication” line properties, simply use +the ``zoom_kw`` argument. + +.. code:: ipython3 + + import proplot as plot + import numpy as np + N = 20 + f, ax = plot.subplots() + x, y = np.arange(10), np.arange(10) + data = np.random.rand(10,10) + m = ax.pcolormesh(data, cmap='Grays', levels=N) + ax.colorbar(m, loc='b', label='label') + ax.format(xlabel='xlabel', ylabel='ylabel') + axi = ax.inset([5,5,4,4], transform='data', zoom=True, zoom_kw={'color':'red', 'lw':2}) + axi.format(xlim=(2,4), ylim=(2,4), color='red', linewidth=1.5, ticklabelweight='bold') + axi.pcolormesh(data, cmap='Grays', levels=N) + ax.format(suptitle='Inet axes demo') + + + +.. image:: tutorial/tutorial_70_0.svg diff --git a/docs/tutorial3.rst b/docs/tutorial3.rst index a91111358..ecbdd0d0c 100644 --- a/docs/tutorial3.rst +++ b/docs/tutorial3.rst @@ -56,11 +56,11 @@ the `cartopy.crs.Projection` classes, e.g. ``lon_0`` instead of -.. image:: tutorial/tutorial_58_3.svg +.. image:: tutorial/tutorial_75_3.svg -.. image:: tutorial/tutorial_58_4.svg +.. image:: tutorial/tutorial_75_4.svg Plotting geophysical data @@ -111,11 +111,11 @@ These features are powered by the `~proplot.wrappers.cartopy_gridfix`, -.. image:: tutorial/tutorial_61_0.svg +.. image:: tutorial/tutorial_78_0.svg -.. image:: tutorial/tutorial_61_1.svg +.. image:: tutorial/tutorial_78_1.svg Formatting projection axes @@ -152,7 +152,7 @@ subplot titles, a-b-c labels, and figure titles as before. -.. image:: tutorial/tutorial_64_0.svg +.. image:: tutorial/tutorial_81_0.svg Zooming into projections @@ -193,11 +193,11 @@ any of the ``boundinglat``, ``llcrnrlon``, ``llcrnrlat``, ``urcrnrlon``, -.. image:: tutorial/tutorial_67_0.svg +.. image:: tutorial/tutorial_84_0.svg -.. image:: tutorial/tutorial_67_1.svg +.. image:: tutorial/tutorial_84_1.svg Registered cartopy projections @@ -234,7 +234,7 @@ Lambert Azimuthal Equal-Area, and Gnomic projections (i.e. -.. image:: tutorial/tutorial_70_1.svg +.. image:: tutorial/tutorial_87_1.svg Registered basemap projections @@ -264,7 +264,7 @@ args to `~mpl_toolkits.basemap.Basemap` if you fail to specify them. -.. image:: tutorial/tutorial_73_0.svg +.. image:: tutorial/tutorial_90_0.svg Polar projections @@ -300,6 +300,77 @@ axes, just pass e.g. ``proj='polar'`` or ``proj={1:'polar'}`` to -.. image:: tutorial/tutorial_76_0.svg +.. image:: tutorial/tutorial_93_0.svg + + +It is common to need colorbars and legends along the outside edge of +*individual axes* or on the inner edge of the *figure*. It is also +common to need “panels” for plotting secondary 1-dimensional datasets or +summary statistics next to a larger subplot. ProPlot satisfies both of +these needs with the `~proplot.axes.PanelAxes` class, which can be +generated with the `~proplot.subplots.subplots` and +`~proplot.axes.Axes.panel_axes` functions. + +`~proplot.axes.PanelAxes` have special +`~proplot.axes.PanelAxes.colorbar` and +`~proplot.axes.PanelAxes.legend` methods. +`~proplot.axes.PanelAxes.colorbar` *fills* the panel with a colorbar – +that is, the panel is used as the ``cax`` argument in the call to +`~matplotlib.figure.Figure.colorbar`, and its default width is +changed. `~proplot.axes.PanelAxes.legend` *fills* the panel with a +legend – that is, a legend is drawn in the center, and the axes +background and spines are hidden. + +On-the-fly panels are a great way to draw colorbars and legends along +the edges of axes. There are three ways to generate and *fill* an +on-the-fly axes panel. + +1. Pass ``colorbar`` to any method wrapped by + `~proplot.wrappers.cmap_wrapper`, or pass ``colorbar`` or + ``legend`` to any method wrapped by + `~proplot.wrappers.cycle_wrapper`. The argument is the panel + location, e.g. ``colorbar='left'`` or ``colorbar='l'``. To specify + panel settings, use the ``panel_kw`` keyword arg. +2. Pass ``loc`` to the `~proplot.axes.Axes.colorbar` or + `~proplot.axes.Axes.legend` ``Axes`` methods. Again, the argument + is the panel location, e.g. ``loc='left'`` or ``loc='l'``. This is + what approach #1 does internally. To specify panel settings, use the + ``panel_kw`` keyword arg. +3. Directly call the `~proplot.axes.Axes.panel_axes` method, e.g. + ``pax = ax.panel('l', **kwargs)``, and then call the + `~proplot.axes.PanelAxes.colorbar` or + `~proplot.axes.PanelAxes.legend` ``PanelAxes`` methods on ``pax``. + This is what the approach #2 does internally. + +No matter the combination of axes panels in your subplot grid, the +layout will stay aligned. To modify default panel settings, use the +`~proplot.rctools.rc` object or create a custom ``.proplotrc`` file +(see the `~proplot.rctools` documentation for details). + +.. code:: ipython3 + + import proplot as plot + import numpy as np + with plot.rc.context(abc=True): + f, axs = plot.subplots(ncols=2, tight=True, share=0) + ax = axs[0] + m = ax.heatmap(np.random.rand(10,10), colorbar='t', cmap='dusk') + ax.colorbar(m, loc='r') + ax.format(title='On-the-fly colorbars', suptitle='On-the-fly panels demo') + ax = axs[1] + ax.format(title='On-the-fly legends', titlepad='0em') + hs = ax.plot((np.random.rand(10,5)-0.5).cumsum(axis=0), lw=3, legend='t', cycle='sharp', + labels=list('abcde'), legend_kw={'ncols':5, 'frame':False}) + ax.legend(hs, loc='r', ncols=1, frame=False) + # Calling the panel method + for ax in axs: + pax = ax.panel('b', share=True) + pax.plot(np.random.rand(10,4), cycle_kw={'linestyle':('-','--','-.',':')}) + # ax.bpanel.plot(...) # also works! + axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Super title') + + + +.. image:: tutorial/tutorial_96_0.svg diff --git a/docs/tutorial4.rst b/docs/tutorial4.rst index bdc8bbd43..d4701e6c9 100644 --- a/docs/tutorial4.rst +++ b/docs/tutorial4.rst @@ -1,357 +1,647 @@ -Panel axes -========== - -It is common to need colorbars and legends along the outside edge of -*individual axes* or on the inner edge of the *figure*. It is also -common to need “panels” for plotting secondary 1-dimensional datasets or -summary statistics next to a larger subplot. ProPlot satisfies both of -these needs with the `~proplot.axes.PanelAxes` class, which can be -generated with the `~proplot.subplots.subplots` and -`~proplot.axes.Axes.panel_axes` functions. - -`~proplot.axes.PanelAxes` have special -`~proplot.axes.PanelAxes.colorbar` and -`~proplot.axes.PanelAxes.legend` methods. -`~proplot.axes.PanelAxes.colorbar` *fills* the panel with a colorbar – -that is, the panel is used as the ``cax`` argument in the call to -`~matplotlib.figure.Figure.colorbar`, and its default width is -changed. `~proplot.axes.PanelAxes.legend` *fills* the panel with a -legend – that is, a legend is drawn in the center, and the axes -background and spines are hidden. - -On-the-fly panels ------------------ - -On-the-fly panels are a great way to draw colorbars and legends along -the edges of axes. There are three ways to generate and *fill* an -on-the-fly axes panel. - -1. Pass ``colorbar`` to any method wrapped by - `~proplot.wrappers.cmap_wrapper`, or pass ``colorbar`` or - ``legend`` to any method wrapped by - `~proplot.wrappers.cycle_wrapper`. The argument is the panel - location, e.g. ``colorbar='left'`` or ``colorbar='l'``. To specify - panel settings, use the ``panel_kw`` keyword arg. -2. Pass ``loc`` to the `~proplot.axes.Axes.colorbar` or - `~proplot.axes.Axes.legend` ``Axes`` methods. Again, the argument - is the panel location, e.g. ``loc='left'`` or ``loc='l'``. This is - what approach #1 does internally. To specify panel settings, use the - ``panel_kw`` keyword arg. -3. Directly call the `~proplot.axes.Axes.panel_axes` method, e.g. - ``pax = ax.panel('l', **kwargs)``, and then call the - `~proplot.axes.PanelAxes.colorbar` or - `~proplot.axes.PanelAxes.legend` ``PanelAxes`` methods on ``pax``. - This is what the approach #2 does internally. - -No matter the combination of axes panels in your subplot grid, the -layout will stay aligned. To modify default panel settings, use the -`~proplot.rctools.rc` object or create a custom ``.proplotrc`` file -(see the `~proplot.rctools` documentation for details). +Color usage +=========== + +ProPlot isn’t just an alternative to `~matplotlib.pyplot`. It also +adds some neat features to help you use colors effectively in your +figures, and integrates palettes from several online data visualization +tools. + +First things first, ProPlot makes a distinction between *colormaps* and +*color cycles*. + +- A *colormap* is a palette constructed by sampling some *smooth, + linear* function between two end colors. Colormaps are generally used + for 2-D or 3-D plots, where the color serves as an extra “dimension”. + This is implemented in matplotlib with the + `~matplotlib.colors.LinearSegmentedColormap` class, and also with + the special ProPlot + `~proplot.styletools.PerceptuallyUniformColormap` subclass (see + :ref:`Making your own colormaps`). +- A *color cycle* is a palette composed of a *jumbled set* of distinct + colors. Interpolation between these colors does not make sense. Color + cycles are generally used with line plots, bar plots, and other plot + elements. They are conceptually implemented in matplotlib with the + `~matplotlib.colors.ListedColormap` class (although it is often + improperly used). ProPlot uses this class to register color cycles, + and the color cycles are “applied” by globally or axes-locally + modifying the `property + cycler `__. + *Colormaps* can also be cut up and used as color cycles (see + :ref:`Making your own color cycles`). + +This section documents the colormaps and cycles registered after +importing ProPlot, explains how to make custom colormaps and cycles, and +shows how to apply them to your plots using axes methods wrapped by +`~proplot.wrappers.cmap_wrapper` or +`~proplot.wrappers.cycle_wrapper`. + +Registered colormaps +-------------------- + +On import, ProPlot registers a few sample +`~proplot.styletools.PerceptuallyUniformColormap` colormaps (see +:ref:`Perceptually uniform colormaps`) plus a ton of other colormaps +from other online data viz projects. Use +`~proplot.styletools.show_cmaps` to generate a table of registered +maps, as shown below. The figure is broken down into the following +sections: + +- “User” colormaps, i.e. colormaps saved to your ``~/.proplot/cmaps`` + folder. A great way to save colormaps to this folder is using the + `~proplot.styletools.Colormap` function. See + :ref:`Making your own colormaps` for details. +- Matplotlib and seaborn original colormaps. +- ProPlot colormaps belonging to the + `~proplot.styletools.PerceptuallyUniformColormap` class. See the + :ref:`Perceptually uniform colormaps` section. +- Miscellaneous diverging colormaps. +- `cmOcean `__ colormaps, originally + intended for oceanographic visualizations but useful for all + scientific fields. +- `ColorBrewer `__ colormaps, included with + matplotlib by default. +- Colormaps from the + `SciVisColor `__ online + interactive tool. There are so many of these maps because they are + intended to be *merged* with one another – suitable for complex + datasets with complex statistical distributions. + +ProPlot removes some default matplotlib colormaps with erratic color +transitions. Note that colormap and color cycle identification is now +flexible: names are *case-insensitive* (e.g. ``'Viridis'``, +``'viridis'``, and ``'ViRiDiS'`` are equivalent) and can be specified in +their “reversed” form (e.g. ``'BuRd'`` is equivalent to ``'RdBu_r'``). +See `~proplot.styletools.CmapDict` for more info. .. code:: ipython3 import proplot as plot - import numpy as np - with plot.rc.context(abc=True): - f, axs = plot.subplots(ncols=2, tight=True, share=0) - ax = axs[0] - m = ax.heatmap(np.random.rand(10,10), colorbar='t', cmap='dusk') - ax.colorbar(m, loc='r') - ax.format(title='On-the-fly colorbars', suptitle='On-the-fly panels demo') - ax = axs[1] - ax.format(title='On-the-fly legends', titlepad='0em') - hs = ax.plot((np.random.rand(10,5)-0.5).cumsum(axis=0), lw=3, legend='t', cycle='sharp', - labels=list('abcde'), legend_kw={'ncols':5, 'frame':False}) - ax.legend(hs, loc='r', ncols=1, frame=False) - # Calling the panel method - for ax in axs: - pax = ax.panel('b', share=True) - pax.plot(np.random.rand(10,4), cycle_kw={'linestyle':('-','--','-.',':')}) - # ax.bpanel.plot(...) # also works! - axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Super title') + f = plot.show_cmaps() + + + +.. image:: tutorial/tutorial_101_0.svg +Perceptually uniform colormaps +------------------------------ -.. image:: tutorial/tutorial_81_0.svg +ProPlot’s custom colormaps are instances of the new +`~proplot.styletools.PerceptuallyUniformColormap` class (see +:ref:`Registered colormaps` for a table). +`~proplot.styletools.PerceptuallyUniformColormap` objects generate +colors by interpolating between coordinates in any of three possible +“perceptually uniform” colorspaces: + +- **HCL**: A purely perceptually uniform colorspace, where colors are + broken down into “hue” (color, range 0-360), “chroma” (saturation, + range 0-100), and “luminance” (brightness, range 0-100). +- **HPLuv**: Hue and luminance are identical to HCL, but 100 saturation + is scaled to be the *minimum maximum saturation* across all hues for + a given luminance. HPLuv is more appropriate for multi-hue colormaps. +- **HSLuv**: Hue and luminance are identical to HCL, but 100 saturation + is scaled to be the *maximum possible saturation* for a given hue and + luminance. HSLuv is more appropriate for single-hue colormaps – + saturation banding can occur when crossing hue thresholds in this + space. + +HCL is the only “purely” perceptually uniform colorspace. But +interpolating between coordinates in this space can result in +“impossible” colors – colors that, when translated from HCL back into +RGB, result in RGB channels greater than 1. HSLuv and HPLuv help resolve +this issue by respectively *scaling* and *clipping* the +highest-saturation colors across different hues and luminances. See +`this page `__ for more info. + +To plot arbitrary cross-sections of these colorspaces, use +`~proplot.styletools.show_colorspaces`. The blacked out regions +represent “impossible” colors. + +.. code:: ipython3 + + import proplot as plot + f = plot.show_colorspaces(luminance=50) -Bulk axes panels ----------------- -If you want to plot stuff on panels in a large subplot array, generating -each panel on-the-fly would be cumbersome. That’s why -`~proplot.subplots.subplots` allows you to generate axes panels in -*bulk* with the ``axpanel`` or ``axpanels`` keyword args. To modify -panel properties, use the ``axpanel_kw`` or ``axpanels_kw`` dictionary -keyword args. See `~proplot.subplots.subplots` for details. +.. image:: tutorial/tutorial_104_0.svg -The below examples demonstrate a few more panel features. To draw panels -“flush” against the subplot, use the ``bflush``, ``tflush``, ``lflush``, -and ``rflush`` keyword args. If you want to disable “axis sharing” with -the parent subplot (see :ref:`Axis sharing and spanning`), use the -``bshare``, ``tshare``, ``rshare``, and ``lshare`` keyword args. See -`~proplot.axes.Axes.panel` for details. .. code:: ipython3 import proplot as plot - f, axs = plot.subplots(axwidth=1.5, nrows=2, ncols=2, - axpanels={1:'t', 2:'l', 3:'b', 4:'r'}, - tight=True, share=0) - axs.format(title='Title', suptitle='Bulk axes panels demo', collabels=['Column 1','Column 2'], - abcloc='ul', titleloc='uc', xlabel='xlabel', ylabel='ylabel', abc=True, top=False) - axs.format(xlim=(0,1), ylim=(0,1), ylocator=plot.arange(0.2,0.8,0.2), xlocator=plot.arange(0.2,0.8,0.2)) + f = plot.show_colorspaces(saturation=60) -.. image:: tutorial/tutorial_84_0.svg +.. image:: tutorial/tutorial_105_0.svg +.. code:: ipython3 + + import proplot as plot + f = plot.show_colorspaces(hue=0) + + + +.. image:: tutorial/tutorial_106_0.svg + + +To see how any colormap varies with respect to each channel, use the +`~proplot.styletools.cmap_breakdown` function. Below, we do this for +the “magma”, “rocket”, and ProPlot “Fire” colormaps. The first two are +nicely-designed `~matplotlib.colors.LinearSegmentedColormap` maps, and +the last one is a `~proplot.styletools.PerceptuallyUniformColormap`. +They are all roughly linear across the hue and luminance channels, but +not the chroma channel (top row). “Fire” is linear in the HSL scaling of +the chroma channel (bottom left), while other ProPlot colormaps are +linear in the HPL scaling of the chroma channel (bottom right). + +.. code:: ipython3 + + import proplot as plot + f = plot.show_channels('magma', 'rocket', 'fire', axwidth=1.2, minhue=-180, rgb=False) + + + +.. image:: tutorial/tutorial_108_0.svg + + +Making your own colormaps +------------------------- + +You can make new colormaps with ProPlot’s on-the-fly colormap generator +`~proplot.styletools.Colormap`. Every command that accepts a ``cmap`` +argument (see `~proplot.wrappers.cmap_wrapper`) is passed to +`~proplot.styletools.Colormap`, and `~proplot.styletools.Colormap` +keyword args can be specified with ``cmap_kw``. If you want to save your +own colormap into the ``~/.proplot/cmaps`` folder, simply use +``save=True``. Colormaps in this folder are loaded every time you import +ProPlot. See `~proplot.styletools.Colormap` and +`~proplot.wrappers.cmap_wrapper` for details. + +To build monochromatic +`~proplot.styletools.PerceptuallyUniformColormap` maps from arbitrary +colors, just pass a color name, hex string, or RGB tuple to +`~proplot.styletools.Colormap`. The colormap colors will vary from the +specified color to some shade near white (controlled by the ``fade`` +keyword arg). The default is to fade to pure white. The first plot shows +several of these maps merged into one, and the second is just one map. + .. code:: ipython3 import proplot as plot import numpy as np - plot.rc.reset() - f, axs = plot.subplots(axwidth=1.7, nrows=2, ncols=2, share=0, panelpad=0.1, - axpanels='r', axpanels_kw={'share':False, 'space':0}) - axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Bulk axes panels demo') - for i,ax in enumerate(axs): - ax.format(title=f'Dataset {i+1}') - data = (np.random.rand(20,20)-0.1).cumsum(axis=1) - m = axs.contourf(data, cmap='glacial', levels=plot.arange(-1,11), - colorbar='b', colorbar_kw={'label':'cbar'}) - axs.rpanel.plot(data.mean(axis=1), np.arange(20), color='k') - axs.rpanel.format(title='Mean') + f, axs = plot.subplots(ncols=2, axwidth=2, aspect=1, bottom=0.1) + data = np.random.rand(50,50).cumsum(axis=1) + cmap1 = plot.Colormap('brick red_r', 'denim_r', 'warm gray_r', fade=90, name='tricolor') + m = axs[0].contourf(data, cmap=cmap1, levels=12) + m = axs[1].contourf(data, cmap='ocean blue', cmap_kw={'name':'ocean blue'}) + cmap2 = m.cmap + axs.format(xticks='none', yticks='none', suptitle='Monochromatic PerceptuallyUniformColormaps') + for ax,title in zip(axs, ['Three monochromatic colormaps', 'One monochromatic colormap']): + ax.format(title=title) + f = plot.show_channels(cmap1, cmap2, axwidth=1.2, rgb=False) -.. image:: tutorial/tutorial_85_0.svg +.. image:: tutorial/tutorial_112_0.svg -Global figure panels --------------------- -ProPlot also supports “figure” panels. These panels are generally filled -with colorbars and legends as *global* references for content that -appears in more than one subplot. Figure panels are declared with the -``panel``, ``colorbar``, ``legend``, ``panels``, ``colorbars``, and -``legends`` keyword args. They can extend across entire sides of the -figure, or across arbitrary contiguous rows and columns of subplots, -using the ``barray``, ``rarray``, or ``larray`` keyword args. +.. image:: tutorial/tutorial_112_1.svg + -Figure panel axes are stored on the `~proplot.subplots.Figure` -instance as the attributes ``bottompanel``, ``leftpanel``, and -``rightpanel`` and the shorthands ``bpanel``, ``lpanel``, and -``rpanel``. See `~proplot.subplots.subplots` for details. +To generate `~proplot.styletools.PerceptuallyUniformColormap` maps, +you can pass a *dictionary* to `~proplot.styletools.Colormap`, which +calls the `~proplot.styletools.PerceptuallyUniformColormap.from_hsl` +static method, or pass a *list of colors* to +`~proplot.styletools.Colormap`, which calls the +`~proplot.styletools.PerceptuallyUniformColormap.from_list` static +method. + +`~proplot.styletools.PerceptuallyUniformColormap.from_list` +interpolates between the listed colors in a perceptually uniform +colorspace (see :ref:`Perceptually uniform colormaps`). +`~proplot.styletools.PerceptuallyUniformColormap.from_hsl` draws lines +between channel values specified by the keyword args ``'hue'``, +``'saturation'``, and ``'luminance'``. The values can be numbers, color +strings, or lists thereof. Numbers indicate the channel value. For color +strings, the channel value is *inferred* from the specified color. You +can end any color string with ``+N`` or ``-N`` to *offset* the channel +value by the number ``N``, as shown below. .. code:: ipython3 import proplot as plot import numpy as np - f, axs = plot.subplots(ncols=3, nrows=3, axwidth=1.2, panel='br', barray=[1,2,2]) - m = axs.pcolormesh(np.random.rand(20,20), cmap='grays', levels=np.linspace(0,1,11), extend='both')[0] - axs.format(suptitle='Figure panels demo', abc=True, abcloc='l', abcformat='a.', xlabel='xlabel', ylabel='ylabel') - f.bpanel[0].colorbar(m, label='label', ticks=0.5) - f.bpanel[1].colorbar(m, label='label', ticks=0.2) - f.rpanel.colorbar(m, label='label', ticks=0.1, length=0.7) + f, axs = plot.subplots(ncols=3, span=False, axwidth=2, aspect=1.5) + ax = axs[0] + # From dicts + data = np.random.rand(10,15) + cmap1 = plot.Colormap({'hue':['red-90', 'red+90'], 'saturation':[50, 70, 30], 'luminance':[20, 100]}, name='Matter', space='hcl') + m = ax.pcolormesh(data, cmap=cmap1) + ax.format(xlabel='x axis', ylabel='y axis', title='From channel values', + suptitle='Building your own PerceptuallyUniformColormaps') + ax = axs[1] + cmap2 = plot.Colormap({'hue':['red', 'red-720'], 'saturation':[80,20], 'luminance':[20, 100]}, name='cubehelix', space='hpl') + m = ax.pcolormesh(data, cmap=cmap2) + ax.format(xlabel='x axis', ylabel='y axis', title='From channel values') + # From list + ax = axs[2] + m = ax.pcolormesh(data, cmap=('maroon', 'goldenrod'), cmap_kw={'name':'reddish'}) + cmap3 = m.cmap + ax.format(title='From list of colors') + # Breakdowns + f = plot.show_channels(cmap1, cmap2, cmap3, minhue=-180, axwidth=1.2, rgb=False) + +.. image:: tutorial/tutorial_114_0.svg +.. image:: tutorial/tutorial_114_1.svg -.. image:: tutorial/tutorial_88_1.svg +Merging and modifying colormaps +------------------------------- +`~proplot.styletools.Colormap` also lets you merge arbitrary colormaps +and modify existing colormaps. To merge colormaps, simply pass multiple +arguments to the `~proplot.styletools.Colormap` constructor. This +makes it easy to create complex +`SciVisColor `__-style +colormaps, which may be desirable for complex datasets with funky +statistical distributions. The below reconstructs the colormap from +`this +example `__. .. code:: ipython3 import proplot as plot import numpy as np - f, axs = plot.subplots(ncols=4, axwidth=1.3, panel='b', barray=[1,1,2,2], share=0, wspace=0.3) - data = (np.random.rand(50,50)-0.1).cumsum(axis=0) - m = axs[:2].contourf(data, cmap='grays', extend='both') - cycle = plot.colors('grays', 5) - hs = [] - for abc,color in zip('ABCDEF',cycle): - h = axs[2:].plot(np.random.rand(10), lw=3, color=color, label=f'line {abc}') - hs.extend(h[0]) - f.bpanel[0].colorbar(m[0], length=0.8, label='label') - f.bpanel[1].legend(hs, ncols=5, label='label', frame=True) - axs.format(suptitle='Figure panels demo', abc=True, abcloc='ul', abcformat='A') - for ax,title in zip(axs, ['2D dataset #1', '2D dataset #2', 'Line set #1', 'Line set #2']): - ax.format(xlabel='xlabel', title=title) + f, axs = plot.subplots(ncols=2, axwidth=2, panels='b', span=False) + data = np.random.rand(100,100).cumsum(axis=1) + # Make colormap, save as "test1.json" + cmap = plot.Colormap('Green1_r', 'Orange5', 'Blue1_r', 'Blue6', name='test1', save=True) + m = axs[0].contourf(data, cmap=cmap, levels=100) + f.bpanel[0].colorbar(m, locator='none') + # Make colormap, save as "test2.json" + cmap = plot.Colormap('Green1_r', 'Orange5', 'Blue1_r', 'Blue6', ratios=(1,3,5,10), name='test2', save=True) + m = axs[1].contourf(data, cmap=cmap, levels=100) + f.bpanel[1].colorbar(m, locator='none') + axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Merging existing colormaps') + for ax,title in zip(axs, ['Evenly spaced', 'Matching SciVisColor example']): + ax.format(title=title) -.. image:: tutorial/tutorial_89_0.svg +.. image:: tutorial/tutorial_117_1.svg -Stacked panels --------------- -You can draw *stacks* of figure and axes panels by passing the -``lstack``, ``bstack``, ``rstack``, and ``tstack`` keyword args to -`~proplot.axes.Axes.panel`. This is useful when you need multiple -*global* colorbars, when using more than one colormap inside a *single -subplot*, or when you need multiple panels for displaying different -statistics. The spacing between stacked panels is adjusted automatically -to account for axis and tick labels. See `~proplot.subplots.subplots` -and `~proplot.subplots.Figure.add_subplot_and_panels` for details. - -You can access individual panels in a stack by *indexing* the panel -attribute. The default order is row-major, from top-left to -bottom-right. For example, ``ax.lpanel[1]`` gives you a left panel, -second from the left. If you are stacking *figure* panels and have -different panels on each row and column (see -:ref:`Global figure panels`), you can use 2D indexing. For example, -``fig.bpanel[1,0]`` gives you a panel in the first column, second from -the top. +To modify a diverging colormap by cutting out some central colors, pass +the ``cut`` keyword arg to `~proplot.styletools.Colormap`. This is +great when you want to have a sharper cutoff between negative and +positive values. To cut out colors from the left or right of a colormap, +pass the ``left`` and ``right`` keyword args to +`~proplot.styletools.Colormap`. + +To rotate a cyclic colormap, pass the ``shift`` argument to +`~proplot.styletools.Colormap`. Cyclic colormaps are colormaps for +which ``cyclic=True`` was passed to `~proplot.styletools.Colormap` on +construction. ProPlot ensures the colors at the ends of these maps are +distinct, so that levels don’t blur together. .. code:: ipython3 import proplot as plot import numpy as np - f, axs = plot.subplots(nrows=2, axwidth='4cm', share=0) - axs.panel_axes('l', stack=3) # subplots(..., axpanels='l') also works - axs.panel_axes('r', stack=2, space=0, sep=0, width=0.5) # subplots(..., axpanels='r') also works - axs[0].format(title='Stacked panels demo', titleweight='bold') - # Draw stuff in axes - N = 10 - for ax in axs: - # Colormap data - # Specify colorbar location with colorbar=('l', index) where index is the stack index - ax.format(xlabel='data', xlocator=np.linspace(0, 0.8, 5)) - for i,(x0,y0,x1,y1,cmap,scale) in enumerate(((0,0.5,1,1,'grays',0.5), (0,0,0.5,0.5,'reds',1), (0.5,0,1,0.5,'blues',2))): - data = np.random.rand(N,N)*scale - x, y = np.linspace(x0, x1, 11), np.linspace(y0, y1, 11) - ax.pcolormesh(x, y, data, cmap=cmap, levels=np.linspace(0,scale,11), colorbar=('l',i)) - # ax.bpanel[i].colorbar(m) # also works - # Plot data - n = 20 - for i,pax in enumerate(ax.rpanel): - data = (np.random.rand(n,n)-0.5).cumsum(axis=0) - data = (data.mean(axis=1) if i==0 else data.std(axis=1)) - label = ('mean' if i==0 else 'stdev') - pax.plot(data, np.linspace(0,1,n), lw=2, color='k') - pax.format(yticklen=0, xlabel=label, xlocator=0.5) - - - -.. image:: tutorial/tutorial_91_0.svg - - -Inset colorbars ---------------- - -As seen above, `~proplot.axes.Axes` and `~proplot.axes.PanelAxes` -have their own colorbar methods. Calling ``PanelAxes`` -`~proplot.axes.PanelAxes.colorbar` fills the panel with a colorbar, -but calling `~proplot.axes.Axes` ``PanelAxes.colorbar`` draws an -*inset* colorbar. You can also draw inset colorbars on panel axes by -passing ``fill=False`` to ``PanelAxes`` -`~proplot.axes.PanelAxes.colorbar`. + f, axs = plot.subplots([[1,1,2,2,3,3],[0,4,4,5,5,0]], axwidth=1.5) + data = np.random.rand(50,50).cumsum(axis=0) - 50 + # Cutting central colors + for ax,cut in zip(axs[:3],(0, 0.1, 0.2)): + m = ax.contourf(data, cmap='Div', cmap_kw={'cut':cut}, levels=13) + ax.format(xlabel='xlabel', ylabel='ylabel', title=f'cut = {cut}', + suptitle='Slicing existing colormaps') + ax.colorbar(m, loc='b', locator='null') + # Cutting left and right + for ax,cut in zip(axs[3:],(0.2,0.8)): + if cut<0.5: + title, cmap, cmap_kw = f'left={cut}', 'grays', {'left':cut} + else: + title, cmap, cmap_kw = f'right={cut}', 'grays', {'right':cut} + ax.contourf(data, cmap=cmap, cmap_kw=cmap_kw, colorbar='b', colorbar_kw={'locator':'null'}) + ax.format(xlabel='xlabel', ylabel='ylabel', title=title) + # Rotating cyclic + f, axs = plot.subplots(ncols=3, axwidth=1.5) + data = (np.random.rand(50,50)-0.48).cumsum(axis=1).cumsum(axis=0) - 50 + for ax,shift in zip(axs,(0, 90, 180)): + m = ax.contourf(data, cmap='twilight', cmap_kw={'shift':shift}, levels=12) + ax.format(xlabel='x axis', ylabel='y axis', title=f'shift = {shift}', + suptitle='Rotating cyclic colormaps') + ax.colorbar(m, loc='b', locator='null') + + + +.. image:: tutorial/tutorial_119_0.svg + + + +.. image:: tutorial/tutorial_119_1.svg + + +You can also change the “gamma” of any +`~proplot.styletools.PerceptuallyUniformColormap` map on-the-fly. The +“gamma” controls how the luminance and saturation channels vary between +segments of the colormap. A gamma larger than ``1`` emphasizes high +luminance, low saturation colors, and a gamma smaller than ``1`` +emphasizes low luminance, high saturation colors. See +`~proplot.styletools.PerceptuallyUniformColormap` for details. .. code:: ipython3 import proplot as plot import numpy as np - f, ax = plot.subplots() - data = (np.random.rand(20,20)).cumsum(axis=0) - m = ax.contourf(data, extend='both', levels=np.linspace(0,10,11), cmap='marine') - ax.format(xlabel='xlabel', ylabel='ylabel', xlim=(0,19), ylim=(0,19)) - ax.colorbar(m, ticks=2, label='data label', frame=True) - ax.colorbar(m, ticks=2, loc='lower left', frame=False) - ax.colorbar(m, loc='b', label='standard outer colorbar', length=0.9) - ax.format(suptitle='Inset colorbars demo') + name = 'boreal' + # Illustrations + f, axs = plot.subplots(ncols=3, axwidth=1.5, aspect=1) + data = np.random.rand(10,10).cumsum(axis=1) + cmaps = [] + for ax,gamma in zip(axs,(0.8, 1.0, 1.4)): + cmap = plot.Colormap(name, gamma=gamma) + cmap.name = f'gamma={gamma}' + cmaps.append(cmap) + m = ax.pcolormesh(data, cmap=cmap, levels=10, extend='both') + ax.colorbar(m, loc='r', locator='none') + ax.format(title=f'gamma = {gamma}', xlabel='x axis', ylabel='y axis', suptitle='Modifying existing PerceptuallyUniformColormaps') + # Breakdowns + f = plot.show_channels(*cmaps, axwidth=1.2, rgb=False) -.. image:: tutorial/tutorial_94_0.svg +.. image:: tutorial/tutorial_121_0.svg -Misc colorbar features ----------------------- -``PanelAxes`` `~proplot.axes.PanelAxes.colorbar` and ``Axes`` -`~proplot.axes.PanelAxes.colorbar` are both wrapped by -`~proplot.wrappers.colorbar_wrapper`, which adds several new features. +.. image:: tutorial/tutorial_121_1.svg + + +Adding online colormaps +----------------------- + +There are plenty of online interactive tools for generating perceptually +uniform colormaps, including +`HCLWizard `__, +`Chroma.js `__, +`SciVisColor `__, and `HCL +picker `__. + +To add colormaps downloaded from any of these sources, save the colormap +data to a file in your ``~/.proplot/cmaps`` folder, then call +`~proplot.styletools.register_cmaps`. The file should be named +``name.ext``, where ``name`` is the registered colormap name and ``ext`` +is the file extension. See `~proplot.styletools.register_cmaps` for +valid file extensions. + +Registered color cycles +----------------------- + +Use `~proplot.styletools.show_cycles` to generate a table of the color +cycles registered by default and loaded from your ``~/.proplot/cycles`` +folder. You can make your own color cycles using the +`~proplot.styletools.Cycle` constructor function. See +:ref:`Colormaps, cycles, colors, and fonts` for more on the +differences between colormaps and color cycles. + +.. code:: ipython3 + + import proplot as plot + f = plot.show_cycles() + + -`~proplot.wrappers.colorbar_wrapper` can draw colorbars from *lists of -colors* or *lists of artists* by passing a list instead of a “mappable” -object – a colormap is constructed from the corresponding colors -on-the-fly. To change outline, divider, tick location, tick label, and -colorbar label settings, just pass the appropriate keyword arg to -`~proplot.wrappers.colorbar_wrapper`. The below example demos the -various keyword args accepted by this wrapper. +.. image:: tutorial/tutorial_126_0.svg + + +Making your own color cycles +---------------------------- + +You can make new color cycles with ProPlot’s on-the-fly property cycler +generator `~proplot.styletools.Cycle`. ProPlot lets you specify a +property cycle by passing ``cycle`` to plotting commands like +`~matplotlib.axes.Axes.plot` and `~matplotlib.axes.Axes.scatter` +(see `~proplot.wrappers.cycle_wrapper`), which is passed to +`~proplot.styletools.Cycle`, and `~proplot.styletools.Cycle` keyword +args can be specified with ``cycle_kw``. If you want to save your own +color cycle into the ``~/.proplot/cycles`` folder, simply pass +``save=True`` to `~proplot.styletools.Cycle`. Color cycles in this +folder are loaded every time you import ProPlot. If you want to change +the global property cycler, use the ``plot.rc.cycle`` setting (see the +`~proplot.rctools` documentation). .. code:: ipython3 import proplot as plot import numpy as np - f, axs = plot.subplots(share=0, ncols=2, panel='b') + data = (np.random.rand(12,12)-0.45).cumsum(axis=0) + plot.rc.cycle = 'contrast' + lw = 5 + f, axs = plot.subplots(ncols=3, axwidth=1.7) + # Here the default cycle is used ax = axs[0] - data = 1 + (np.random.rand(12,10)-0.45).cumsum(axis=0) - cycle = plot.Cycle('algae') - hs = ax.plot(data, lw=4, cycle=cycle, colorbar='lr', colorbar_kw={'length':'14em', 'label':'numeric values'}) - ax.colorbar(hs, loc='t', values=np.linspace(0.5,9.5,10)*2, label='alt numeric values', ticks=2) + ax.plot(data, lw=lw) + # Note that specifying "cycle" does not reset the color cycle ax = axs[1] - m = ax.contourf(data.T, extend='both', cmap='algae') - f.bpanel.colorbar(m, length=0.6, label='flipped tick location', tickloc='top', grid=True) - ax.colorbar(m, loc='ul', length=1, ticks=0.5, tickminor=True, extendrect=True, - label='changing colors', labelcolor='gray7', labelweight='bold', - linewidth=1, edgecolor='gray7', ticklabelcolor='gray7', alpha=0.5) - axs.format(suptitle='Colorbar formatting demo', xlabel='xlabel', ylabel='ylabel') + ax.plot(data, cycle='qual2', lw=lw) + ax = axs[2] + for i in range(data.shape[1]): + ax.plot(data[:,i], cycle='qual2', lw=lw) + # Format + axs.format(suptitle='Local and global color cycles demo') -.. image:: tutorial/tutorial_97_0.svg +.. image:: tutorial/tutorial_129_0.svg -Misc legend features --------------------- +Colormaps or combinations thereof can be used as sources for making +color cycles. Just pass colormap name(s) to the +`~proplot.styletools.Cycle` constructor, with the last positional +argument indicating the number of samples you want to draw. To exclude +near-white colors on the end of a colormap, pass e.g. ``left=x`` to +`~proplot.styletools.Cycle` (or supply a plotting command with e.g. +``cycle_kw={'left':x}``). See `~proplot.styletools.Colormap` for +details. + +.. code:: ipython3 + + import proplot as plot + import numpy as np + f, axs = plot.subplots(ncols=2, panels='b', share=0, axwidth=2.2, aspect=1.5) + data = (20*np.random.rand(10,21)-10).cumsum(axis=0) + # Example 1 + ax = axs[0] + lines = ax.plot(data[:,:5], cycle='purples', cycle_kw={'left':0.3}, lw=5) + f.bpanel[0].colorbar(lines, values=np.arange(0,len(lines)), label='clabel') + ax.format(title='Simple cycle') + # Example 2 + ax = axs[1] + cycle = plot.Cycle('blues', 'reds', 'oranges', 21, left=[0.1]*3) + lines = ax.plot(data, cycle=cycle, lw=5) + f.bpanel[1].colorbar(lines, values=np.arange(0,len(lines)), locator=2, label='clabel') + ax.format(title='Complex cycle', suptitle='Color cycles from colormaps demo') + + + +.. image:: tutorial/tutorial_131_0.svg -``PanelAxes`` `~proplot.axes.PanelAxes.legend` and ``Axes`` -`~proplot.axes.PanelAxes.legend` are both wrapped by -`~proplot.wrappers.legend_wrapper`, which adds several new features. -`~proplot.wrappers.legend_wrapper` can draw legends with *centered -legend rows*, either by passing ``center=True`` or by passing *list of -lists* of plot handles. This is accomplished by stacking multiple -single-row, horizontally centered legends, then manually adding an -encompassing legend frame. You can also switch between row-major and -column-major order for legend entries (the new default is row-major), -and modify legend text properties and handle properties. See -`~proplot.wrappers.legend_wrapper` for details. +`~proplot.styletools.Cycle` can also generate cyclers that change +properties other than color. Below, a single-color dash style cycler is +constructed and applied to the axes locally. To apply it globally, +simply use ``plot.rc['axes.prop_cycle'] = cycle``. .. code:: ipython3 import proplot as plot import numpy as np - plot.rc.cycle = 'contrast' - labels = ['a', 'bb', 'ccc', 'dddd', 'eeeee'] - f, axs = plot.subplots(ncols=2, span=False, share=1) - hs1, hs2 = [], [] - # Plot lines and add to legends on-the-fly - for i,label in enumerate(labels): - data = (np.random.rand(20)-0.45).cumsum(axis=0) - h1 = axs[0].plot(data, lw=4, label=label, legend='ul', - legend_kw={'order':'F', 'title':'column major'}) # add to legend in upper left - hs1.extend(h1) - h2 = axs[1].plot(data, lw=4, label=label, legend='r', cycle='floral', - legend_kw={'ncols':1, 'frame':False, 'title':'no frame'}) # add to legend in right panel - hs2.extend(h2) - # Outer legends + import pandas as pd + f, ax = plot.subplots(axwidth=3, aspect=1.5) + data = (np.random.rand(20,4)-0.5).cumsum(axis=0) + data = pd.DataFrame(data, columns=pd.Index(['a','b','c','d'], name='label')) + ax.format(suptitle='Plot without color cycle') + cycle = plot.Cycle(dashes=[(1,0.5),(1,1.5),(3,0.5),(3,1.5)]) + obj = ax.plot(data, lw=3, cycle=cycle, legend='ul', legend_kw={'ncols':2, 'handlelength':3}) + + + +.. image:: tutorial/tutorial_133_0.svg + + +Adding online color cycles +-------------------------- + +There are plenty of online interactive tools for generating and testing +color cycles, including `i want +hue `__, +`coolers `__, and `viz +palette `__. + +To add color cycles downloaded from any of these sources, save the cycle +data to a file in your ``~/.proplot/cycles`` folder, then call +`~proplot.styletools.register_cycles`. The file should be named +``name.ext``, where ``name`` is the registered cycle name and ``ext`` is +the file extension. See `~proplot.styletools.register_cmaps` for valid +file extensions. + +Registered color names +---------------------- + +ProPlot defines new color names from the `XKCD “color +survey” `__, +official `Crayola crayon +colors `__, +and from the `“Open color” `__ +Github project. This was inspired by +`seaborn `__. +Use `~proplot.styletools.show_colors` to generate tables of these +colors, as shown below. Note that the native matplotlib `CSS4 named +colors `__ are +still registered, but I encourage using colors from the tables instead. + +To reduce the number of registered color names to a more manageable +size, XKCD and Crayola colors must have *sufficiently distinct +coordinates* in the HCL perceptually uniform colorspace before they are +added to ProPlot. This makes it a bit easier to pick out colors from a +table generated with `~proplot.styletools.show_colors`. Similar names +were also cleaned up – for example, “reddish” and “reddy” are changed to +“red”. + +.. code:: ipython3 + + import proplot as plot + f = plot.show_colors() + + + +.. image:: tutorial/tutorial_138_0.svg + + + +.. image:: tutorial/tutorial_138_1.svg + + +Individual color sampling +------------------------- + +If you want to draw an individual color from a smooth colormap or a +color cycle, use ``color=(cmapname, position)`` or +``color=(cyclename, index)`` with any command that accepts the ``color`` +keyword! The ``position`` should be between 0 and 1, while the ``index`` +is the index on the list of colors in the cycle. This feature is powered +by the `~proplot.styletools.ColorCacheDict` class. + +.. code:: ipython3 + + import proplot as plot + import numpy as np + plot.rc.reset() + f, axs = plot.subplots(nrows=2, aspect=2, axwidth=3, share=0) + # Drawing from colormap ax = axs[0] - ax.legend(hs1, loc='b', ncols=3, linewidth=2, title='row major', order='C', - edgecolor='gray4', facecolor='gray2') + cmap = 'deep' + m = ax.pcolormesh([[0],[1]], cmap=cmap, N=1000) + idxs = plot.arange(0,1,0.2) + np.random.shuffle(idxs) + for idx in idxs: + h = ax.plot((np.random.rand(20)-0.4).cumsum(), lw=5, color=(cmap, idx), + label=f'idx {idx:.1f}', legend='r', legend_kw={'ncols':1}) + ax.colorbar(m, loc='ul', locator=0.2, label='colormap') + ax.format(title='Drawing from the Solar colormap', grid=True) + # Drawing from color cycle ax = axs[1] - ax.legend(hs2, loc='b', ncols=3, center=True, title='centered legend', - handlelength=1) # also works! - axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Legend formatting demo') + idxs = np.arange(6) + np.random.shuffle(idxs) + for idx in idxs: + h = ax.plot((np.random.rand(20)-0.4).cumsum(), lw=5, color=('qual1', idx), + label=f'idx {idx:.0f}', legend='r', legend_kw={'ncols':1}) + ax.format(title='Drawing from the ggplot color cycle') + axs.format(xlocator='null', abc=True, abcloc='ur', abcformat='A.', + suptitle='Getting individual colors from colormaps and cycles') + + + +.. image:: tutorial/tutorial_141_0.svg + + +Font selection +-------------- + +DejaVu Sans is the default matplotlib font, but it’s not very +aesthetically pleasing. ProPlot adds a bunch of sans-serif fonts so that +you have them on every workstation, introduces a +`~proplot.styletools.show_fonts` command to display them (see below), +and makes Helvetica the default, as in MATLAB. Generally speaking, +simple, clean sans-serif fonts are more appropriate for figures than +serif fonts. + +You can register your own fonts by adding ``.ttf`` and ``.otf`` files to +the ``~/.proplot/fonts`` directory and calling +`~proplot.styletools.register_fonts` (which is also called on import). +To change the default font, use the `~proplot.rctools.rc` object or +modify your ``~/.proplotrc``. See the `~proplot.styletools` and +`~proplot.rctools` documentation for more info. + +.. code:: ipython3 + + import proplot as plot + plot.rc.reset() + f = plot.show_fonts() -.. image:: tutorial/tutorial_100_0.svg +.. image:: tutorial/tutorial_144_0.svg diff --git a/docs/tutorial5.rst b/docs/tutorial5.rst index d8c95c1f3..3e0ebd4a5 100644 --- a/docs/tutorial5.rst +++ b/docs/tutorial5.rst @@ -1,647 +1,431 @@ -Color usage -=========== - -ProPlot isn’t just an alternative to `~matplotlib.pyplot`. It also -adds some neat features to help you use colors effectively in your -figures, and integrates palettes from several online data visualization -tools. - -First things first, ProPlot makes a distinction between *colormaps* and -*color cycles*. - -- A *colormap* is a palette constructed by sampling some *smooth, - linear* function between two end colors. Colormaps are generally used - for 2-D or 3-D plots, where the color serves as an extra “dimension”. - This is implemented in matplotlib with the - `~matplotlib.colors.LinearSegmentedColormap` class, and also with - the special ProPlot - `~proplot.styletools.PerceptuallyUniformColormap` subclass (see - :ref:`Making your own colormaps`). -- A *color cycle* is a palette composed of a *jumbled set* of distinct - colors. Interpolation between these colors does not make sense. Color - cycles are generally used with line plots, bar plots, and other plot - elements. They are conceptually implemented in matplotlib with the - `~matplotlib.colors.ListedColormap` class (although it is often - improperly used). ProPlot uses this class to register color cycles, - and the color cycles are “applied” by globally or axes-locally - modifying the `property - cycler `__. - *Colormaps* can also be cut up and used as color cycles (see - :ref:`Making your own color cycles`). - -This section documents the colormaps and cycles registered after -importing ProPlot, explains how to make custom colormaps and cycles, and -shows how to apply them to your plots using axes methods wrapped by -`~proplot.wrappers.cmap_wrapper` or -`~proplot.wrappers.cycle_wrapper`. - -Registered colormaps --------------------- - -On import, ProPlot registers a few sample -`~proplot.styletools.PerceptuallyUniformColormap` colormaps (see -:ref:`Perceptually uniform colormaps`) plus a ton of other colormaps -from other online data viz projects. Use -`~proplot.styletools.show_cmaps` to generate a table of registered -maps, as shown below. The figure is broken down into the following -sections: - -- “User” colormaps, i.e. colormaps saved to your ``~/.proplot/cmaps`` - folder. A great way to save colormaps to this folder is using the - `~proplot.styletools.Colormap` function. See - :ref:`Making your own colormaps` for details. -- Matplotlib and seaborn original colormaps. -- ProPlot colormaps belonging to the - `~proplot.styletools.PerceptuallyUniformColormap` class. See the - :ref:`Perceptually uniform colormaps` section. -- Miscellaneous diverging colormaps. -- `cmOcean `__ colormaps, originally - intended for oceanographic visualizations but useful for all - scientific fields. -- `ColorBrewer `__ colormaps, included with - matplotlib by default. -- Colormaps from the - `SciVisColor `__ online - interactive tool. There are so many of these maps because they are - intended to be *merged* with one another – suitable for complex - datasets with complex statistical distributions. - -ProPlot removes some default matplotlib colormaps with erratic color -transitions. Note that colormap and color cycle identification is now -flexible: names are *case-insensitive* (e.g. ``'Viridis'``, -``'viridis'``, and ``'ViRiDiS'`` are equivalent) and can be specified in -their “reversed” form (e.g. ``'BuRd'`` is equivalent to ``'RdBu_r'``). -See `~proplot.styletools.CmapDict` for more info. - -.. code:: ipython3 - - import proplot as plot - f = plot.show_cmaps() - - - -.. image:: tutorial/tutorial_105_0.svg - - -Perceptually uniform colormaps ------------------------------- - -ProPlot’s custom colormaps are instances of the new -`~proplot.styletools.PerceptuallyUniformColormap` class (see -:ref:`Registered colormaps` for a table). -`~proplot.styletools.PerceptuallyUniformColormap` objects generate -colors by interpolating between coordinates in any of three possible -“perceptually uniform” colorspaces: - -- **HCL**: A purely perceptually uniform colorspace, where colors are - broken down into “hue” (color, range 0-360), “chroma” (saturation, - range 0-100), and “luminance” (brightness, range 0-100). -- **HPLuv**: Hue and luminance are identical to HCL, but 100 saturation - is scaled to be the *minimum maximum saturation* across all hues for - a given luminance. HPLuv is more appropriate for multi-hue colormaps. -- **HSLuv**: Hue and luminance are identical to HCL, but 100 saturation - is scaled to be the *maximum possible saturation* for a given hue and - luminance. HSLuv is more appropriate for single-hue colormaps – - saturation banding can occur when crossing hue thresholds in this - space. - -HCL is the only “purely” perceptually uniform colorspace. But -interpolating between coordinates in this space can result in -“impossible” colors – colors that, when translated from HCL back into -RGB, result in RGB channels greater than 1. HSLuv and HPLuv help resolve -this issue by respectively *scaling* and *clipping* the -highest-saturation colors across different hues and luminances. See -`this page `__ for more info. +Plotting wrappers +================= + +New features have been added to various matplotlib plotting commands +thanks to a set of wrapper functions. These features are a strict +*superset* of the existing matplotlib API – if you want, you can use +plotting commands exactly as you always have. This section documents +these wrapper functions. For details, see the `~proplot.axes` +documentation. + +You should also see :ref:`Making your own colormaps` and +:ref:`Making your own color cycles`, which explain how +`~proplot.wrappers.cmap_wrapper` and +`~proplot.wrappers.cycle_wrapper` can be used to create and apply new +colormaps and property cyclers on-the-fly. + +Normalizers and levels +---------------------- -To plot arbitrary cross-sections of these colorspaces, use -`~proplot.styletools.show_colorspaces`. The blacked out regions -represent “impossible” colors. +`~proplot.wrappers.cmap_wrapper` assigns the +`~proplot.styletools.BinNorm` “meta-normalizer” as the data normalizer +for all plotting commands involving colormaps. This permits discrete +``levels`` even for commands like `~matplotlib.axes.Axes.pcolor` and +`~matplotlib.axes.Axes.pcolormesh`. `~proplot.styletools.BinNorm` +also ensures that colorbar colors span the entire colormap range, +independent of the ``extend`` setting, and that color levels on the ends +of colorbars for “cyclic” colormaps are distinct. .. code:: ipython3 import proplot as plot - f = plot.show_colorspaces(luminance=50) + import numpy as np + f, axs = plot.subplots(ncols=2, axwidth=2) + cmap = 'spectral' + data = (np.random.rand(15,15)-0.5).cumsum(axis=0) + axs.format(suptitle='Pcolor with levels demo') + ax = axs[0] + ax.pcolor(data, cmap=cmap, N=200, symmetric=True, colorbar='l', colorbar_kw={'locator':0.5}) + ax.format(title='Ambiguous values', yformatter='null') + ax = axs[1] + ax.pcolor(data, cmap=cmap, N=8, symmetric=True, colorbar='r') + ax.format(title='Discernible values') -.. image:: tutorial/tutorial_108_0.svg +.. image:: tutorial/tutorial_149_0.svg .. code:: ipython3 import proplot as plot - f = plot.show_colorspaces(saturation=60) + import numpy as np + f, axs = plot.subplots(ncols=5, axwidth=2, ref=1, wratios=(5,3,3,3,3)) + axs.format(suptitle='Demo of colorbar color-range standardization') + levels = plot.arange(0,360,45) + data = (20*(np.random.rand(20,20) - 0.4).cumsum(axis=0).cumsum(axis=1)) % 360 + ax = axs[0] + ax.pcolormesh(data, levels=levels, cmap='phase', extend='neither', colorbar='b') + ax.format(title='Cyclic map with separate ends') + for ax,extend in zip(axs[1:], ('min','max','neither','both')): + ax.pcolormesh(data[:,:10], levels=levels, cmap='oxy', extend=extend, colorbar='b', colorbar_kw={'locator':90}) + ax.format(title=f'Map with extend={extend}') -.. image:: tutorial/tutorial_109_0.svg +.. image:: tutorial/tutorial_150_0.svg +If you pass unevenly spaced ``levels``, the +`~proplot.styletools.LinearSegmentedNorm` normalizer is applied by +default. This results in even color gradations across *indices* of the +level list, no matter their spacing. To use an arbitrary colormap +normalizer, just pass ``norm`` and optionally ``norm_kw`` to a command +wrapped by `~proplot.wrappers.cmap_wrapper`. These arguments are +passed to the `~proplot.styletools.Norm` constructor. + .. code:: ipython3 import proplot as plot - f = plot.show_colorspaces(hue=0) + import numpy as np + f, axs = plot.subplots(ncols=2, axwidth=2.5, aspect=1.5) + data = 10**(2*np.random.rand(20,20).cumsum(axis=0)/7) + ticks = [5, 10, 20, 50, 100, 200, 500, 1000] + for i,(norm,title) in enumerate(zip(('linear','segments'),('Linear normalizer','LinearSegmentedNorm'))): + m = axs[i].contourf(data, levels=ticks, extend='both', cmap='Mako', norm=norm, colorbar='b') + axs[i].format(title=title) + axs.format(suptitle='Level normalizers demo') -.. image:: tutorial/tutorial_110_0.svg +.. image:: tutorial/tutorial_152_0.svg -To see how any colormap varies with respect to each channel, use the -`~proplot.styletools.cmap_breakdown` function. Below, we do this for -the “magma”, “rocket”, and ProPlot “Fire” colormaps. The first two are -nicely-designed `~matplotlib.colors.LinearSegmentedColormap` maps, and -the last one is a `~proplot.styletools.PerceptuallyUniformColormap`. -They are all roughly linear across the hue and luminance channels, but -not the chroma channel (top row). “Fire” is linear in the HSL scaling of -the chroma channel (bottom left), while other ProPlot colormaps are -linear in the HPL scaling of the chroma channel (bottom right). +Finally, there is a new `~proplot.styletools.MidpointNorm` class that +warps your colormap so that its midpoint lies on some central data +value, no matter the minimum and maximum colormap colors. Again, to use +an arbitrary colormap normalizer, just pass ``norm`` and optionally +``norm_kw`` to a command wrapped by `~proplot.wrappers.cmap_wrapper`. +These arguments are passed to the `~proplot.styletools.Norm` +constructor. .. code:: ipython3 import proplot as plot - f = plot.show_channels('magma', 'rocket', 'fire', axwidth=1.2, minhue=-180, rgb=False) - - - -.. image:: tutorial/tutorial_112_0.svg - - -Making your own colormaps -------------------------- - -You can make new colormaps with ProPlot’s on-the-fly colormap generator -`~proplot.styletools.Colormap`. Every command that accepts a ``cmap`` -argument (see `~proplot.wrappers.cmap_wrapper`) is passed to -`~proplot.styletools.Colormap`, and `~proplot.styletools.Colormap` -keyword args can be specified with ``cmap_kw``. If you want to save your -own colormap into the ``~/.proplot/cmaps`` folder, simply use -``save=True``. Colormaps in this folder are loaded every time you import -ProPlot. See `~proplot.styletools.Colormap` and + import numpy as np + data1 = (np.random.rand(20,20) - 0.43).cumsum(axis=0) + data2 = (np.random.rand(20,20) - 0.57).cumsum(axis=0) + f, axs = plot.subplots(ncols=2, axwidth=2.5, aspect=1.5) + cmap = plot.Colormap('Moisture', cut=0.1) + axs.format(suptitle='Midpoint normalizer demo') + axs[0].contourf(data1, norm='midpoint', cmap=cmap, colorbar='b') + axs[0].format(title='Skewed positive data') + axs[1].contourf(data2, norm='midpoint', cmap=cmap, colorbar='b') + axs[1].format(title='Skewed negative data') + + + +.. image:: tutorial/tutorial_154_0.svg + + +Heatmaps and labels +------------------- + +The new `~proplot.axes.Axes.heatmap` command calls +`~matplotlib.axes.Axes.pcolormesh` and applies default formatting that +is suitable for heatmaps: no gridlines, no minor ticks, and major ticks +at the center of each box. Among other things, this is useful for +displaying autocorrelation matrices (see below). + +You can also add labels to `~matplotlib.axes.Axes.pcolor`, +`~matplotlib.axes.Axes.pcolormesh`, `~proplot.axes.Axes.heatmap`, +`~matplotlib.axes.Axes.contour`, and +`~matplotlib.axes.Axes.contourf` plots, thanks to +`~proplot.wrappers.cmap_wrapper`. Just pass the ``labels=True`` +keyword argument, and ProPlot will draw contour labels with +`~matplotlib.axes.Axes.clabel` or grid box labels with +`~matplotlib.axes.Axes.text`. Label colors are automatically chosen +based on the luminance of the underlying box or contour color. The label +text objects can be changed with the ``labels_kw`` dictionary keyword +arg and the ``precision`` keyword arg. See `~proplot.wrappers.cmap_wrapper` for details. -To build monochromatic -`~proplot.styletools.PerceptuallyUniformColormap` maps from arbitrary -colors, just pass a color name, hex string, or RGB tuple to -`~proplot.styletools.Colormap`. The colormap colors will vary from the -specified color to some shade near white (controlled by the ``fade`` -keyword arg). The default is to fade to pure white. The first plot shows -several of these maps merged into one, and the second is just one map. - .. code:: ipython3 import proplot as plot + import pandas as pd import numpy as np - f, axs = plot.subplots(ncols=2, axwidth=2, aspect=1, bottom=0.1) - data = np.random.rand(50,50).cumsum(axis=1) - cmap1 = plot.Colormap('brick red_r', 'denim_r', 'warm gray_r', fade=90, name='tricolor') - m = axs[0].contourf(data, cmap=cmap1, levels=12) - m = axs[1].contourf(data, cmap='ocean blue', cmap_kw={'name':'ocean blue'}) - cmap2 = m.cmap - axs.format(xticks='none', yticks='none', suptitle='Monochromatic PerceptuallyUniformColormaps') - for ax,title in zip(axs, ['Three monochromatic colormaps', 'One monochromatic colormap']): - ax.format(title=title) - f = plot.show_channels(cmap1, cmap2, axwidth=1.2, rgb=False) + # Heatmap with labels + f, axs = plot.subplots(ncols=2, axwidth=2, span=False, share=1) + data = np.random.rand(6,6) + data = pd.DataFrame(data, index=pd.Index(['a','b','c','d','e','f'])) + axs.format(suptitle='Labels demo') + ax = axs[0] + m = ax.heatmap(data, cmap='rocket', labels=True, precision=2, labels_kw={'weight':'bold'}) + ax.format(xlabel='xlabel', ylabel='ylabel', title='Heatmap plot with labels') + # Filled contours with labels + ax = axs[1] + m = ax.contourf(data.cumsum(axis=0), labels=True, cmap='rocket', labels_kw={'weight':'bold'}) + ax.format(xlabel='xlabel', ylabel='ylabel', title='Contourf plot with labels') + # Cross-correlation matrix + f, ax = plot.subplots(axwidth=3) + data = np.random.normal(size=(10,10)).cumsum(axis=0) + data = (data - data.mean(axis=0)) / data.std(axis=0) + data = (data.T @ data) / data.shape[0] + data[np.tril_indices(data.shape[0], -1)] = np.nan # empty boxes + data = pd.DataFrame(data, columns=list('abcdefghij'), index=list('abcdefghij')) + m = ax.heatmap(data, cmap='ColdHot', vmin=-1, vmax=1, N=100, + labels=True, labels_kw={'size':7, 'weight':'bold'}) + ax.format(title='Cross-correlation matrix', alpha=0, linewidth=0, + xloc='top', yloc='right', yreverse=True) -.. image:: tutorial/tutorial_116_0.svg +.. image:: tutorial/tutorial_157_0.svg -.. image:: tutorial/tutorial_116_1.svg +.. image:: tutorial/tutorial_157_1.svg -To generate `~proplot.styletools.PerceptuallyUniformColormap` maps, -you can pass a *dictionary* to `~proplot.styletools.Colormap`, which -calls the `~proplot.styletools.PerceptuallyUniformColormap.from_hsl` -static method, or pass a *list of colors* to -`~proplot.styletools.Colormap`, which calls the -`~proplot.styletools.PerceptuallyUniformColormap.from_list` static -method. +Easy error bars +--------------- -`~proplot.styletools.PerceptuallyUniformColormap.from_list` -interpolates between the listed colors in a perceptually uniform -colorspace (see :ref:`Perceptually uniform colormaps`). -`~proplot.styletools.PerceptuallyUniformColormap.from_hsl` draws lines -between channel values specified by the keyword args ``'hue'``, -``'saturation'``, and ``'luminance'``. The values can be numbers, color -strings, or lists thereof. Numbers indicate the channel value. For color -strings, the channel value is *inferred* from the specified color. You -can end any color string with ``+N`` or ``-N`` to *offset* the channel -value by the number ``N``, as shown below. +Thanks to the `~proplot.wrappers.add_errorbars` wrapper, you can now +add error bars when using the `~matplotlib.axes.Axes.plot`, +`~matplotlib.axes.Axes.scatter`, `~matplotlib.axes.Axes.bar`, +`~matplotlib.axes.Axes.barh`, and `~matplotlib.axes.Axes.violinplot` +methods. If you pass 2D arrays of data to these commands with +``means=True`` or ``medians=True``, the *means or medians* of each +column are drawn as points, lines, or bars, and error bars represent the +*spread* in each column. You can draw both thin “bars” with optional +whiskers, and thick “boxes” overlayed on top of these bars. You can also +pass error bar coordinates manually with the ``bardata`` and ``boxdata`` +keyword args. See `~proplot.wrappers.add_errorbars` for details. .. code:: ipython3 import proplot as plot import numpy as np - f, axs = plot.subplots(ncols=3, span=False, axwidth=2, aspect=1.5) + import pandas as pd + plot.rc['title.loc'] = 'uc' + plot.rc['axes.ymargin'] = plot.rc['axes.xmargin'] = 0.05 + data = np.random.rand(20,8).cumsum(axis=0).cumsum(axis=1)[:,::-1] + 20*np.random.normal(size=(20,8)) + 30 + f, axs = plot.subplots(nrows=3, aspect=1.5, axwidth=3, share=0, hratios=(2,1,1)) + axs.format(suptitle='Error bars with various plotting commands') + # Asking add_errorbars to calculate bars ax = axs[0] - # From dicts - data = np.random.rand(10,15) - cmap1 = plot.Colormap({'hue':['red-90', 'red+90'], 'saturation':[50, 70, 30], 'luminance':[20, 100]}, name='Matter', space='hcl') - m = ax.pcolormesh(data, cmap=cmap1) - ax.format(xlabel='x axis', ylabel='y axis', title='From channel values', - suptitle='Building your own PerceptuallyUniformColormaps') + obj = ax.barh(data, color='red orange', means=True) + ax.format(title='Column statistics') + # Showing a standard deviation range instead of percentile range ax = axs[1] - cmap2 = plot.Colormap({'hue':['red', 'red-720'], 'saturation':[80,20], 'luminance':[20, 100]}, name='cubehelix', space='hpl') - m = ax.pcolormesh(data, cmap=cmap2) - ax.format(xlabel='x axis', ylabel='y axis', title='From channel values') - # From list + ax.scatter(data, color='k', marker='x', markersize=50, barcolor='gray5', + medians=True, barstd=True, barrange=(-1,1), barzorder=0, boxes=False, capsize=2) + # Supplying error bar data manually ax = axs[2] - m = ax.pcolormesh(data, cmap=('maroon', 'goldenrod'), cmap_kw={'name':'reddish'}) - cmap3 = m.cmap - ax.format(title='From list of colors') - # Breakdowns - f = plot.show_channels(cmap1, cmap2, cmap3, minhue=-180, axwidth=1.2, rgb=False) + boxdata = np.percentile(data, (25,75), axis=0) + bardata = np.percentile(data, (5,95), axis=0) + ax.plot(data.mean(axis=0), boxes=False, marker='o', markersize=5, + edgecolor='k', color='cerulean', boxdata=boxdata, bardata=bardata) + # Formatting + axs[0].format(ylabel='column number', title='Bar plot', ygrid=False) + axs[1].format(title='Scatter plot') + axs[2].format(title='Line plot') + axs[1:].format(xlabel='column number', xticks=1, xgrid=False) -.. image:: tutorial/tutorial_118_0.svg +.. image:: tutorial/tutorial_160_0.svg +Area plots +---------- -.. image:: tutorial/tutorial_118_1.svg +Make area plots with the convenient aliases `~proplot.axes.Axes.area` +and `~proplot.axes.Axes.areax`. These point to the +`~matplotlib.axes.Axes.fill_between` and +`~matplotlib.axes.Axes.fill_betweenx` methods, which are wrapped with +`~proplot.wrappers.fill_between_wrapper` and +`~proplot.wrappers.fill_betweenx_wrapper`. - -Merging and modifying colormaps -------------------------------- - -`~proplot.styletools.Colormap` also lets you merge arbitrary colormaps -and modify existing colormaps. To merge colormaps, simply pass multiple -arguments to the `~proplot.styletools.Colormap` constructor. This -makes it easy to create complex -`SciVisColor `__-style -colormaps, which may be desirable for complex datasets with funky -statistical distributions. The below reconstructs the colormap from -`this -example `__. +The wrappers enable “stacking” successive columns of a 2D input array +like in `pandas`. They also add a new “``negpos``” keyword for +creating area plots that change color when the fill boundaries cross +each other. The most common use case for this is highlighting negative +and positive area underneath a line, as shown below. .. code:: ipython3 import proplot as plot import numpy as np - f, axs = plot.subplots(ncols=2, axwidth=2, panels='b', span=False) - data = np.random.rand(100,100).cumsum(axis=1) - # Make colormap, save as "test1.json" - cmap = plot.Colormap('Green1_r', 'Orange5', 'Blue1_r', 'Blue6', name='test1', save=True) - m = axs[0].contourf(data, cmap=cmap, levels=100) - f.bpanel[0].colorbar(m, locator='none') - # Make colormap, save as "test2.json" - cmap = plot.Colormap('Green1_r', 'Orange5', 'Blue1_r', 'Blue6', ratios=(1,3,5,10), name='test2', save=True) - m = axs[1].contourf(data, cmap=cmap, levels=100) - f.bpanel[1].colorbar(m, locator='none') - axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Merging existing colormaps') - for ax,title in zip(axs, ['Evenly spaced', 'Matching SciVisColor example']): - ax.format(title=title) - + plot.rc.reset() + plot.rc.margin = 0 + f, axs = plot.subplots(array=[[1,2],[3,3]], hratios=(1,0.8), share=0) + axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Area plot demo') + data = np.random.rand(5,3).cumsum(axis=0) + cycle = ('gray3', 'gray5', 'gray7') + ax = axs[0] + ax.areax(np.arange(5), data, data + np.random.rand(5)[:,None], cycle=cycle, alpha=0.5, + legend='uc', legend_kw={'center':True, 'ncols':2, 'labels':['z','y','qqqq']}, + ) + ax.format(title='Fill between columns') + ax = axs[1] + ax.area(np.arange(5), data, stacked=True, cycle=cycle, alpha=0.8, + legend='ul', legend_kw={'center':True, 'ncols':2, 'labels':['z','y','qqqq']}, + ) + ax.format(title='Stack between columns') + ax = axs[2] + data = 5*(np.random.rand(20)-0.5) + ax.area(data, negpos=True, negcolor='blue7', poscolor='red7') + ax.format(title='Negative and positive data', xlabel='xlabel', ylabel='ylabel') + axs.format(grid=False) -.. image:: tutorial/tutorial_121_1.svg +.. image:: tutorial/tutorial_163_0.svg -To modify a diverging colormap by cutting out some central colors, pass -the ``cut`` keyword arg to `~proplot.styletools.Colormap`. This is -great when you want to have a sharper cutoff between negative and -positive values. To cut out colors from the left or right of a colormap, -pass the ``left`` and ``right`` keyword args to -`~proplot.styletools.Colormap`. +Bar plots +--------- -To rotate a cyclic colormap, pass the ``shift`` argument to -`~proplot.styletools.Colormap`. Cyclic colormaps are colormaps for -which ``cyclic=True`` was passed to `~proplot.styletools.Colormap` on -construction. ProPlot ensures the colors at the ends of these maps are -distinct, so that levels don’t blur together. +`~proplot.wrappers.bar_wrapper` and +`~proplot.wrappers.cycle_wrapper` make it easier to generate useful +bar plots. You can now pass 2D arrays to `~matplotlib.axes.Axes.bar` +or `~matplotlib.axes.Axes.barh`, and columns of data will be grouped +or stacked together. And if *x* coordinates are not provided, default +coordinates are applied, just like with `~matplotlib.axes.Axes.plot`. +See `~proplot.wrappers.bar_wrapper` for details. .. code:: ipython3 import proplot as plot import numpy as np - f, axs = plot.subplots([[1,1,2,2,3,3],[0,4,4,5,5,0]], axwidth=1.5) - data = np.random.rand(50,50).cumsum(axis=0) - 50 - # Cutting central colors - for ax,cut in zip(axs[:3],(0, 0.1, 0.2)): - m = ax.contourf(data, cmap='Div', cmap_kw={'cut':cut}, levels=13) - ax.format(xlabel='xlabel', ylabel='ylabel', title=f'cut = {cut}', - suptitle='Slicing existing colormaps') - ax.colorbar(m, loc='b', locator='null') - # Cutting left and right - for ax,cut in zip(axs[3:],(0.2,0.8)): - if cut<0.5: - title, cmap, cmap_kw = f'left={cut}', 'grays', {'left':cut} - else: - title, cmap, cmap_kw = f'right={cut}', 'grays', {'right':cut} - ax.contourf(data, cmap=cmap, cmap_kw=cmap_kw, colorbar='b', colorbar_kw={'locator':'null'}) - ax.format(xlabel='xlabel', ylabel='ylabel', title=title) - # Rotating cyclic - f, axs = plot.subplots(ncols=3, axwidth=1.5) - data = (np.random.rand(50,50)-0.48).cumsum(axis=1).cumsum(axis=0) - 50 - for ax,shift in zip(axs,(0, 90, 180)): - m = ax.contourf(data, cmap='twilight', cmap_kw={'shift':shift}, levels=12) - ax.format(xlabel='x axis', ylabel='y axis', title=f'shift = {shift}', - suptitle='Rotating cyclic colormaps') - ax.colorbar(m, loc='b', locator='null') - - - -.. image:: tutorial/tutorial_123_0.svg - - - -.. image:: tutorial/tutorial_123_1.svg - - -You can also change the “gamma” of any -`~proplot.styletools.PerceptuallyUniformColormap` map on-the-fly. The -“gamma” controls how the luminance and saturation channels vary between -segments of the colormap. A gamma larger than ``1`` emphasizes high -luminance, low saturation colors, and a gamma smaller than ``1`` -emphasizes low luminance, high saturation colors. See -`~proplot.styletools.PerceptuallyUniformColormap` for details. - -.. code:: ipython3 - - import proplot as plot - import numpy as np - name = 'boreal' - # Illustrations - f, axs = plot.subplots(ncols=3, axwidth=1.5, aspect=1) - data = np.random.rand(10,10).cumsum(axis=1) - cmaps = [] - for ax,gamma in zip(axs,(0.8, 1.0, 1.4)): - cmap = plot.Colormap(name, gamma=gamma) - cmap.name = f'gamma={gamma}' - cmaps.append(cmap) - m = ax.pcolormesh(data, cmap=cmap, levels=10, extend='both') - ax.colorbar(m, loc='r', locator='none') - ax.format(title=f'gamma = {gamma}', xlabel='x axis', ylabel='y axis', suptitle='Modifying existing PerceptuallyUniformColormaps') - # Breakdowns - f = plot.show_channels(*cmaps, axwidth=1.2, rgb=False) - - - -.. image:: tutorial/tutorial_125_0.svg - - - -.. image:: tutorial/tutorial_125_1.svg - - -Adding online colormaps ------------------------ - -There are plenty of online interactive tools for generating perceptually -uniform colormaps, including -`HCLWizard `__, -`Chroma.js `__, -`SciVisColor `__, and `HCL -picker `__. - -To add colormaps downloaded from any of these sources, save the colormap -data to a file in your ``~/.proplot/cmaps`` folder, then call -`~proplot.styletools.register_cmaps`. The file should be named -``name.ext``, where ``name`` is the registered colormap name and ``ext`` -is the file extension. See `~proplot.styletools.register_cmaps` for -valid file extensions. - -Registered color cycles ------------------------ - -Use `~proplot.styletools.show_cycles` to generate a table of the color -cycles registered by default and loaded from your ``~/.proplot/cycles`` -folder. You can make your own color cycles using the -`~proplot.styletools.Cycle` constructor function. See -:ref:`Colormaps, cycles, colors, and fonts` for more on the -differences between colormaps and color cycles. - -.. code:: ipython3 - - import proplot as plot - f = plot.show_cycles() + import pandas as pd + plot.rc.titleloc = 'uc' + plot.rc.margin = 0.05 + f, axs = plot.subplots(nrows=2, aspect=2, axwidth=3.5, share=0, hratios=(3,2)) + data = np.random.rand(5,5).cumsum(axis=0).cumsum(axis=1)[:,::-1] + data = pd.DataFrame(data, columns=pd.Index(np.arange(1,6), name='column'), index=pd.Index(['a','b','c','d','e'], name='row idx')) + ax = axs[0] + obj = ax.bar(data, cycle='Reds', colorbar='ul', edgecolor='red9', colorbar_kw={'frameon':False}) + ax.format(xlocator=1, xminorlocator=0.5, ytickminor=False, title='Side-by-side', suptitle='Bar plot wrapper demo') + ax = axs[1] + obj = ax.barh(data.iloc[::-1,:], cycle='Blues', legend='ur', edgecolor='blue9', stacked=True) + ax.format(title='Stacked') + axs.format(grid=False) -.. image:: tutorial/tutorial_130_0.svg +.. image:: tutorial/tutorial_166_0.svg -Making your own color cycles ----------------------------- +Box plots +--------- -You can make new color cycles with ProPlot’s on-the-fly property cycler -generator `~proplot.styletools.Cycle`. ProPlot lets you specify a -property cycle by passing ``cycle`` to plotting commands like -`~matplotlib.axes.Axes.plot` and `~matplotlib.axes.Axes.scatter` -(see `~proplot.wrappers.cycle_wrapper`), which is passed to -`~proplot.styletools.Cycle`, and `~proplot.styletools.Cycle` keyword -args can be specified with ``cycle_kw``. If you want to save your own -color cycle into the ``~/.proplot/cycles`` folder, simply pass -``save=True`` to `~proplot.styletools.Cycle`. Color cycles in this -folder are loaded every time you import ProPlot. If you want to change -the global property cycler, use the ``plot.rc.cycle`` setting (see the -`~proplot.rctools` documentation). +`~matplotlib.axes.Axes.boxplot` and +`~matplotlib.axes.Axes.violinplot` are now wrapped with +`~proplot.wrappers.boxplot_wrapper`, +`~proplot.wrappers.violinplot_wrapper`, and +`~proplot.wrappers.cycle_wrapper`, making it much easier to plot +distributions of data with aesthetically pleasing default settings and +automatic axis labeling. .. code:: ipython3 import proplot as plot import numpy as np - data = (np.random.rand(12,12)-0.45).cumsum(axis=0) - plot.rc.cycle = 'contrast' - lw = 5 - f, axs = plot.subplots(ncols=3, axwidth=1.7) - # Here the default cycle is used + import pandas as pd + N = 500 + f, axs = plot.subplots(ncols=2) + data = np.random.normal(size=(N,5)) + 2*(np.random.rand(N,5)-0.5)*np.arange(5) + data = pd.DataFrame(data, columns=pd.Index(['a','b','c','d','e'], name='xlabel')) ax = axs[0] - ax.plot(data, lw=lw) - # Note that specifying "cycle" does not reset the color cycle + obj1 = ax.boxplot(data, lw=0.7, marker='x', fillcolor='gray5', medianlw=1, mediancolor='k')#, boxprops={'color':'C0'})#, labels=data.columns) + ax.format(title='Box plots', titleloc='uc') ax = axs[1] - ax.plot(data, cycle='qual2', lw=lw) - ax = axs[2] - for i in range(data.shape[1]): - ax.plot(data[:,i], cycle='qual2', lw=lw) - # Format - axs.format(suptitle='Local and global color cycles demo') + obj2 = ax.violinplot(data, lw=0.7, fillcolor='gray7', points=500, bw_method=0.3, means=True) + ax.format(title='Violin plots', titleloc='uc') + axs.format(ymargin=0.1, xmargin=0.1, grid=False, suptitle='Boxes and violins demo') + -.. image:: tutorial/tutorial_133_0.svg +.. image:: tutorial/tutorial_169_1.svg -Colormaps or combinations thereof can be used as sources for making -color cycles. Just pass colormap name(s) to the -`~proplot.styletools.Cycle` constructor, with the last positional -argument indicating the number of samples you want to draw. To exclude -near-white colors on the end of a colormap, pass e.g. ``left=x`` to -`~proplot.styletools.Cycle` (or supply a plotting command with e.g. -``cycle_kw={'left':x}``). See `~proplot.styletools.Colormap` for -details. +Parametric plots +---------------- + +`~matplotlib.axes.Axes.plot` now accepts a ``cmap`` keyword – this +lets you draw line collections that map individual segments of the line +to individual colors. This can be useful for drawing “parametric” plots, +where you want to indicate the time or some other coordinate at each +point on the line. See `~proplot.axes.Axes.cmapline` for details. .. code:: ipython3 import proplot as plot import numpy as np - f, axs = plot.subplots(ncols=2, panels='b', share=0, axwidth=2.2, aspect=1.5) - data = (20*np.random.rand(10,21)-10).cumsum(axis=0) - # Example 1 + plot.rc.reset() + N = 50 + cmap = 'IceFire' + values = np.linspace(-N/2, N/2, N) + f, axs = plot.subplots(share=0, ncols=2, wratios=(2,1), axwidth='6cm', aspect=(2,1)) ax = axs[0] - lines = ax.plot(data[:,:5], cycle='purples', cycle_kw={'left':0.3}, lw=5) - f.bpanel[0].colorbar(lines, values=np.arange(0,len(lines)), label='clabel') - ax.format(title='Simple cycle') - # Example 2 + m = ax.plot((np.random.rand(N)-0.5).cumsum(), np.random.rand(N), cmap=cmap, values=values, lw=7, extend='both') + ax.format(xlabel='xlabel', ylabel='ylabel', title='Line with smooth color gradations', titleweight='bold') + ax.colorbar(m, loc='b', label='parametric coordinate', locator=5) + N = 12 ax = axs[1] - cycle = plot.Cycle('blues', 'reds', 'oranges', 21, left=[0.1]*3) - lines = ax.plot(data, cycle=cycle, lw=5) - f.bpanel[1].colorbar(lines, values=np.arange(0,len(lines)), locator=2, label='clabel') - ax.format(title='Complex cycle', suptitle='Color cycles from colormaps demo') - + values = np.linspace(-N/2, N/2 - 1, N) + radii = np.linspace(1,0.2,N) + angles = np.linspace(0,4*np.pi,N) + x = radii*np.cos(1.4*angles) + y = radii*np.sin(1.4*angles) + m = ax.plot(x, y, values=values, linewidth=15, interp=False, cmap=cmap) + ax.format(xlim=(-1,1), ylim=(-1,1), title='With step gradations', titleweight='bold', xlabel='cosine angle', ylabel='sine angle') + ax.colorbar(m, loc='b', maxn=10, label=f'parametric coordinate') -.. image:: tutorial/tutorial_135_0.svg -`~proplot.styletools.Cycle` can also generate cyclers that change -properties other than color. Below, a single-color dash style cycler is -constructed and applied to the axes locally. To apply it globally, -simply use ``plot.rc['axes.prop_cycle'] = cycle``. -.. code:: ipython3 - - import proplot as plot - import numpy as np - import pandas as pd - f, ax = plot.subplots(axwidth=3, aspect=1.5) - data = (np.random.rand(20,4)-0.5).cumsum(axis=0) - data = pd.DataFrame(data, columns=pd.Index(['a','b','c','d'], name='label')) - ax.format(suptitle='Plot without color cycle') - cycle = plot.Cycle(dashes=[(1,0.5),(1,1.5),(3,0.5),(3,1.5)]) - obj = ax.plot(data, lw=3, cycle=cycle, legend='ul', legend_kw={'ncols':2, 'handlelength':3}) +.. image:: tutorial/tutorial_172_1.svg -.. image:: tutorial/tutorial_137_0.svg - -Adding online color cycles --------------------------- - -There are plenty of online interactive tools for generating and testing -color cycles, including `i want -hue `__, -`coolers `__, and `viz -palette `__. - -To add color cycles downloaded from any of these sources, save the cycle -data to a file in your ``~/.proplot/cycles`` folder, then call -`~proplot.styletools.register_cycles`. The file should be named -``name.ext``, where ``name`` is the registered cycle name and ``ext`` is -the file extension. See `~proplot.styletools.register_cmaps` for valid -file extensions. - -Registered color names +Misc plot enhancements ---------------------- -ProPlot defines new color names from the `XKCD “color -survey” `__, -official `Crayola crayon -colors `__, -and from the `“Open color” `__ -Github project. This was inspired by -`seaborn `__. -Use `~proplot.styletools.show_colors` to generate tables of these -colors, as shown below. Note that the native matplotlib `CSS4 named -colors `__ are -still registered, but I encourage using colors from the tables instead. - -To reduce the number of registered color names to a more manageable -size, XKCD and Crayola colors must have *sufficiently distinct -coordinates* in the HCL perceptually uniform colorspace before they are -added to ProPlot. This makes it a bit easier to pick out colors from a -table generated with `~proplot.styletools.show_colors`. Similar names -were also cleaned up – for example, “reddish” and “reddy” are changed to -“red”. - -.. code:: ipython3 - - import proplot as plot - f = plot.show_colors() - - - -.. image:: tutorial/tutorial_142_0.svg - - - -.. image:: tutorial/tutorial_142_1.svg - - -Individual color sampling -------------------------- - -If you want to draw an individual color from a smooth colormap or a -color cycle, use ``color=(cmapname, position)`` or -``color=(cyclename, index)`` with any command that accepts the ``color`` -keyword! The ``position`` should be between 0 and 1, while the ``index`` -is the index on the list of colors in the cycle. This feature is powered -by the `~proplot.styletools.ColorCacheDict` class. +Thanks to `~proplot.wrappers.scatter_wrapper` and +`~proplot.wrappers.cycle_wrapper`, `~matplotlib.axes.Axes.scatter` +now accepts 2D arrays, just like `~matplotlib.axes.Axes.plot`, and +successive calls to `~matplotlib.axes.Axes.scatter` can apply property +cycle keys other than ``color`` – for example, ``marker`` and +``markersize``. `~matplotlib.axes.Axes.scatter` also now optionally +accepts keywords that look like the `~matplotlib.axes.Axes.plot` +keywords, which is a bit less confusing. You can also pass colormaps to +`~matplotlib.axes.Axes.scatter` just as with matplotlib. + +I am also considering supporting 2D array input and property cycle +iteration for more obscure matplotlib plotting commands like +`~matplotlib.axes.Axes.stem`, `~matplotlib.axes.Axes.step`, +`~matplotlib.axes.Axes.vlines`, and `~matplotlib.axes.Axes.hlines`. +Stay tuned! .. code:: ipython3 import proplot as plot import numpy as np + import pandas as pd plot.rc.reset() - f, axs = plot.subplots(nrows=2, aspect=2, axwidth=3, share=0) - # Drawing from colormap + f, axs = plot.subplots(ncols=2, share=1) + x = (np.random.rand(20)-0).cumsum() + data = (np.random.rand(20,4)-0.5).cumsum(axis=0) + data = pd.DataFrame(data, columns=pd.Index(['a','b','c','d'], name='label')) + # Scatter demo ax = axs[0] - cmap = 'deep' - m = ax.pcolormesh([[0],[1]], cmap=cmap, N=1000) - idxs = plot.arange(0,1,0.2) - np.random.shuffle(idxs) - for idx in idxs: - h = ax.plot((np.random.rand(20)-0.4).cumsum(), lw=5, color=(cmap, idx), - label=f'idx {idx:.1f}', legend='r', legend_kw={'ncols':1}) - ax.colorbar(m, loc='ul', locator=0.2, label='colormap') - ax.format(title='Drawing from the Solar colormap', grid=True) - # Drawing from color cycle + ax.format(title='New prop cycle properties', suptitle='Scatter plot demo') + obj = ax.scatter(x, data, legend='ul', cycle='warm', legend_kw={'ncols':2}, + cycle_kw={'marker':['x','o','x','o'], 'markersize':[5,10,20,30]}) ax = axs[1] - idxs = np.arange(6) - np.random.shuffle(idxs) - for idx in idxs: - h = ax.plot((np.random.rand(20)-0.4).cumsum(), lw=5, color=('qual1', idx), - label=f'idx {idx:.0f}', legend='r', legend_kw={'ncols':1}) - ax.format(title='Drawing from the ggplot color cycle') - axs.format(xlocator='null', abc=True, abcloc='ur', abcformat='A.', - suptitle='Getting individual colors from colormaps and cycles') - - - -.. image:: tutorial/tutorial_145_0.svg - - -Font selection --------------- - -DejaVu Sans is the default matplotlib font, but it’s not very -aesthetically pleasing. ProPlot adds a bunch of sans-serif fonts so that -you have them on every workstation, introduces a -`~proplot.styletools.show_fonts` command to display them (see below), -and makes Helvetica the default, as in MATLAB. Generally speaking, -simple, clean sans-serif fonts are more appropriate for figures than -serif fonts. - -You can register your own fonts by adding ``.ttf`` and ``.otf`` files to -the ``~/.proplot/fonts`` directory and calling -`~proplot.styletools.register_fonts` (which is also called on import). -To change the default font, use the `~proplot.rctools.rc` object or -modify your ``~/.proplotrc``. See the `~proplot.styletools` and -`~proplot.rctools` documentation for more info. - -.. code:: ipython3 - - import proplot as plot - plot.rc.reset() - f = plot.show_fonts() - - + ax.format(title='Scatter plot with cmap') + data = (np.random.rand(2,100)-0.5) + obj = ax.scatter(*data, color=data.sum(axis=0), size=np.random.rand(100), smin=3, smax=30, + marker='o', cmap='dusk', colorbar='lr', colorbar_kw={'locator':0.5, 'label':'label'}) + axs.format(xlabel='xlabel', ylabel='ylabel') -.. image:: tutorial/tutorial_148_0.svg +.. image:: tutorial/tutorial_175_0.svg diff --git a/proplot/axes.py b/proplot/axes.py index 0daf52bfe..7dea565b7 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -1158,7 +1158,8 @@ def legend(self, *args, loc=None, width=None, space=None, **kwargs): self._panel_filled = True # Try to make handles and stuff flush against the axes edge kwargs.setdefault('borderaxespad', 0) - if not kwargs.get('frameon', rc['legend.frameon']): + frameon = _notNone(kwargs.get('frame', None), kwargs.get('frameon', None), rc['legend.frameon']) + if not frameon: kwargs.setdefault('borderpad', 0) # Apply legend location side = self._panel_side @@ -1267,7 +1268,9 @@ def inset_axes(self, bounds, *, transform=None, zorder=5, ax.indicate_inset_zoom(**zoom_kw) return ax - def indicate_inset_zoom(self, alpha=None, linewidth=None, color=None, edgecolor=None, **kwargs): + def indicate_inset_zoom(self, alpha=None, + lw=None, linewidth=None, + color=None, edgecolor=None, **kwargs): """ Called automatically when using `~Axes.inset` with ``zoom=True``. Like `~matplotlib.axes.Axes.indicate_inset_zoom`, but *refreshes* the @@ -1279,11 +1282,9 @@ def indicate_inset_zoom(self, alpha=None, linewidth=None, color=None, edgecolor= ---------- alpha : float, optional The transparency of the zoom box fill. - linewidth : float, optional + lw, linewidth : float, optional The width of the zoom lines and box outline in points. - color : color-spec, optional - The color of the zoom box fill. - edgecolor : color-spec, optional + color, edgecolor : color-spec, optional The color of the zoom lines and box outline. **kwargs Passed to `~matplotlib.axes.Axes.indicate_inset`. @@ -1291,16 +1292,15 @@ def indicate_inset_zoom(self, alpha=None, linewidth=None, color=None, edgecolor= # Should be called from the inset axes parent = self._inset_parent alpha = alpha or 1.0 - linewidth = linewidth or rc['axes.linewidth'] - edgecolor = color or edgecolor or rc['axes.edgecolor'] + linewidth = _notNone(lw, linewidth, rc['axes.linewidth'], names=('lw', 'linewidth')) + edgecolor = _notNone(color, edgecolor, rc['axes.edgecolor'], names=('color', 'edgecolor')) if not parent: raise ValueError(f'{self} is not an inset axes.') - xlim = self.get_xlim() - ylim = self.get_ylim() + xlim, ylim = self.get_xlim(), self.get_ylim() rect = (xlim[0], ylim[0], xlim[1] - xlim[0], ylim[1] - ylim[0]) - # Call inset - kwargs.update({'linewidth':linewidth, 'edgecolor':edgecolor, 'alpha':alpha}) - rectpatch, connects = parent.indicate_inset(rect, self, **kwargs) + # Call indicate_inset + rectpatch, connects = parent.indicate_inset(rect, self, + linewidth=linewidth, edgecolor=edgecolor, alpha=alpha, **kwargs) # Adopt properties from old one if self._inset_zoom_data: rectpatch_old, connects_old = self._inset_zoom_data @@ -1309,6 +1309,7 @@ def indicate_inset_zoom(self, alpha=None, linewidth=None, color=None, edgecolor= for line,line_old in zip(connects,connects_old): visible = line.get_visible() line.update_from(line_old) + line.set_linewidth(line_old.get_linewidth()) line.set_visible(visible) line_old.set_visible(False) # Format zoom data diff --git a/proplot/styletools.py b/proplot/styletools.py index 57f69b639..a990e98ae 100644 --- a/proplot/styletools.py +++ b/proplot/styletools.py @@ -322,8 +322,12 @@ def __getitem__(self, key): pass else: if isinstance(cmap, mcolors.ListedColormap): + if not 0 <= rgb[1] < len(cmap.colors): + raise ValueError(f'Color cycle sample for {rgb[0]!r} cycle must be between 0 and {len(cmap.colors)-1}, got {rgb[1]}.') rgb = cmap.colors[rgb[1]] # draw color from the list of colors, using index else: + if not 0 <= rgb[1] <= 1: + raise ValueError(f'Colormap sample for {rgb[0]!r} colormap must be between 0 and 1, got {rgb[1]}.') rgb = cmap(rgb[1]) # interpolate color from colormap, using key in range 0-1 rgba = mcolors.to_rgba(rgb, alpha) return rgba diff --git a/proplot/subplots.py b/proplot/subplots.py index c8be29cc1..2c38a97f5 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -684,7 +684,7 @@ class Figure(mfigure.Figure): may be automatically scaled to preserve subplot aspect ratios.""" def __init__(self, tight=None, - pad=None, axpad=None, panelpad=None, + pad=None, axpad=None, panelpad=None, includepanels=False, autoformat=True, ref=1, order='C', # documented in subplots but needed here subplots_kw=None, gridspec_kw=None, subplots_orig_kw=None, @@ -707,6 +707,9 @@ def __init__(self, Padding between subplots and axes panels, and between "stacked" panels. If float, units are inches. If string, units are interpreted by `~proplot.utils.units`. + includepanels : bool, optional + Whether to include panels when centering spanning *x* axis labels, + *y* axis labels, and figure "super titles". Defaults to ``False``. autoformat : bool, optional Whether to automatically format the axes when a `~pandas.Series`, `~pandas.DataFrame` or `~xarray.DataArray` is passed to a plotting @@ -736,6 +739,7 @@ def __init__(self, self._panelpad = units(_notNone(panelpad, rc['subplots.panelpad'])) self._auto_format = autoformat self._auto_tight_layout = _notNone(tight, rc['tight']) + self._include_panels = includepanels self._order = order # used for configuring panel axes_grids self._ref_num = ref self._axes_main = [] @@ -777,14 +781,20 @@ def _add_axes_panel(self, ax, side, filled=False, **kwargs): if s in 'lr': iratio = (col1 - offset if s == 'l' else col2 + offset) idx1 = slice(row1, row2 + 1) - idx2 = max(0, iratio) + idx2 = iratio else: iratio = (row1 - offset if s == 't' else row2 + offset) - idx1 = max(0, iratio) + idx1 = iratio idx2 = slice(col1, col2 + 1) + gridspec_prev = self._gridspec_main gridspec = self._insert_row_column(side, iratio, width, space, space_orig, figure=False, ) + if gridspec is not gridspec_prev: + if s == 't': + idx1 += 1 + elif s == 'l': + idx2 += 1 # Draw and setup panel with self._unlock(): @@ -1242,6 +1252,8 @@ def _insert_row_column(self, side, idx, for ax in axs: # Get old index # NOTE: Endpoints are inclusive, not exclusive! + if not hasattr(ax, 'get_subplotspec'): + continue if s in 'lr': inserts = (None, None, idx, idx) else: @@ -1274,7 +1286,10 @@ def _get_align_coord(self, side, axs): `x` can be ``'x'`` or ``'y'``.""" # Get position in figure relative coordinates s = side[0] - x = ('x' if s in 'lr' else 'y') + x = ('y' if s in 'lr' else 'x') + extra = ('tb' if s in 'lr' else 'lr') + if self._include_panels: + axs = [iax for ax in axs for iax in ax._iter_panels(extra)] ranges = np.array([ax._range_gridspec(x) for ax in axs]) min_, max_ = ranges[:,0].min(), ranges[:,1].max() axlo = axs[np.where(ranges[:,0] == min_)[0][0]] @@ -1287,6 +1302,7 @@ def _get_align_coord(self, side, axs): pos = (lobox.y1 + hibox.y0)/2 # 'lo' is actually on top, highest up in gridspec # Return axis suitable for spanning position spanax = axs[(np.argmin(ranges[:,0]) + np.argmax(ranges[:,1]))//2] + spanax = spanax._panel_parent or spanax return pos, spanax def _get_align_axes(self, side): @@ -1690,7 +1706,7 @@ def subplots(array=None, ncols=1, nrows=1, align=None, alignx=None, aligny=None, share=None, sharex=None, sharey=None, basemap=False, proj=None, projection=None, proj_kw=None, projection_kw=None, - autoformat=True, + autoformat=True, includepanels=False, ): """ Analogous to `matplotlib.pyplot.subplots`, creates a figure with a single @@ -1836,6 +1852,9 @@ def subplots(array=None, ncols=1, nrows=1, pad, axpad, panelpad : float or str, optional Padding for automatic tight layout adjustments. See `Figure` for details. + includepanels : bool, optional + Whether to include panels when calculating the position of certain + spanning labels. See `Figure` for details. autoformat : bool, optional Whether to automatically format axes when special datasets are passed to plotting commands. See `Figure` for details. @@ -2039,6 +2058,7 @@ def subplots(array=None, ncols=1, nrows=1, ) fig = plt.figure(FigureClass=Figure, tight=tight, figsize=figsize, ref=ref, pad=pad, axpad=axpad, panelpad=panelpad, autoformat=autoformat, + includepanels=includepanels, subplots_orig_kw=subplots_orig_kw, subplots_kw=subplots_kw, gridspec_kw=gridspec_kw) gridspec = fig._gridspec_main From acc905caa9ea8c62a48bdc96d16901b3651cc17c Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 16:45:55 -0600 Subject: [PATCH 19/28] Remove duplicate 'Plotting wrappers' docs --- docs/index.rst | 1 - docs/tutorial1.rst | 4 +- docs/tutorial6.rst | 431 --------------------------------------------- 3 files changed, 2 insertions(+), 434 deletions(-) delete mode 100644 docs/tutorial6.rst diff --git a/docs/index.rst b/docs/index.rst index eeace746f..e7c00b839 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -96,7 +96,6 @@ To get started, check out the :ref:`Introduction`. tutorial3 tutorial4 tutorial5 - tutorial6 .. toctree:: :hidden: diff --git a/docs/tutorial1.rst b/docs/tutorial1.rst index 16c2fbad9..a0024bd20 100644 --- a/docs/tutorial1.rst +++ b/docs/tutorial1.rst @@ -529,8 +529,8 @@ between content in adjacent subplots, is automatically adjusted. ProPlot introduces a new tight layout algorithm that permits *variable figure dimensions* and *variable spacing* between subplot rows and columns (see `~proplot.subplots.FlexibleGridSpecBase`). This allows -the algorithm to preserve *subplot aspect ratios, panel widths, and -optionally, subplot physical dimensions*, all without producing extra +the algorithm to preserve subplot aspect ratios, panel widths, and +optionally, subplot physical dimensions, all without producing extra whitespace. The algorithm is also more robust to complex geometry. To turn it off, pass ``tight=False`` to `~proplot.subplots.subplots`. If you explicitly pass a spacing argument to diff --git a/docs/tutorial6.rst b/docs/tutorial6.rst deleted file mode 100644 index 8fd58ceb2..000000000 --- a/docs/tutorial6.rst +++ /dev/null @@ -1,431 +0,0 @@ -Plotting wrappers -================= - -New features have been added to various matplotlib plotting commands -thanks to a set of wrapper functions. These features are a strict -*superset* of the existing matplotlib API – if you want, you can use -plotting commands exactly as you always have. This section documents -these wrapper functions. For details, see the `~proplot.axes` -documentation. - -You should also see :ref:`Making your own colormaps` and -:ref:`Making your own color cycles`, which explain how -`~proplot.wrappers.cmap_wrapper` and -`~proplot.wrappers.cycle_wrapper` can be used to create and apply new -colormaps and property cyclers on-the-fly. - -Normalizers and levels ----------------------- - -`~proplot.wrappers.cmap_wrapper` assigns the -`~proplot.styletools.BinNorm` “meta-normalizer” as the data normalizer -for all plotting commands involving colormaps. This permits discrete -``levels`` even for commands like `~matplotlib.axes.Axes.pcolor` and -`~matplotlib.axes.Axes.pcolormesh`. `~proplot.styletools.BinNorm` -also ensures that colorbar colors span the entire colormap range, -independent of the ``extend`` setting, and that color levels on the ends -of colorbars for “cyclic” colormaps are distinct. - -.. code:: ipython3 - - import proplot as plot - import numpy as np - f, axs = plot.subplots(ncols=2, axwidth=2) - cmap = 'spectral' - data = (np.random.rand(15,15)-0.5).cumsum(axis=0) - axs.format(suptitle='Pcolor with levels demo') - ax = axs[0] - ax.pcolor(data, cmap=cmap, N=200, symmetric=True, colorbar='l', colorbar_kw={'locator':0.5}) - ax.format(title='Ambiguous values', yformatter='null') - ax = axs[1] - ax.pcolor(data, cmap=cmap, N=8, symmetric=True, colorbar='r') - ax.format(title='Discernible values') - - - -.. image:: tutorial/tutorial_153_0.svg - - -.. code:: ipython3 - - import proplot as plot - import numpy as np - f, axs = plot.subplots(ncols=5, axwidth=2, ref=1, wratios=(5,3,3,3,3)) - axs.format(suptitle='Demo of colorbar color-range standardization') - levels = plot.arange(0,360,45) - data = (20*(np.random.rand(20,20) - 0.4).cumsum(axis=0).cumsum(axis=1)) % 360 - ax = axs[0] - ax.pcolormesh(data, levels=levels, cmap='phase', extend='neither', colorbar='b') - ax.format(title='Cyclic map with separate ends') - for ax,extend in zip(axs[1:], ('min','max','neither','both')): - ax.pcolormesh(data[:,:10], levels=levels, cmap='oxy', extend=extend, colorbar='b', colorbar_kw={'locator':90}) - ax.format(title=f'Map with extend={extend}') - - - -.. image:: tutorial/tutorial_154_0.svg - - -If you pass unevenly spaced ``levels``, the -`~proplot.styletools.LinearSegmentedNorm` normalizer is applied by -default. This results in even color gradations across *indices* of the -level list, no matter their spacing. To use an arbitrary colormap -normalizer, just pass ``norm`` and optionally ``norm_kw`` to a command -wrapped by `~proplot.wrappers.cmap_wrapper`. These arguments are -passed to the `~proplot.styletools.Norm` constructor. - -.. code:: ipython3 - - import proplot as plot - import numpy as np - f, axs = plot.subplots(ncols=2, axwidth=2.5, aspect=1.5) - data = 10**(2*np.random.rand(20,20).cumsum(axis=0)/7) - ticks = [5, 10, 20, 50, 100, 200, 500, 1000] - for i,(norm,title) in enumerate(zip(('linear','segments'),('Linear normalizer','LinearSegmentedNorm'))): - m = axs[i].contourf(data, levels=ticks, extend='both', cmap='Mako', norm=norm, colorbar='b') - axs[i].format(title=title) - axs.format(suptitle='Level normalizers demo') - - - -.. image:: tutorial/tutorial_156_0.svg - - -Finally, there is a new `~proplot.styletools.MidpointNorm` class that -warps your colormap so that its midpoint lies on some central data -value, no matter the minimum and maximum colormap colors. Again, to use -an arbitrary colormap normalizer, just pass ``norm`` and optionally -``norm_kw`` to a command wrapped by `~proplot.wrappers.cmap_wrapper`. -These arguments are passed to the `~proplot.styletools.Norm` -constructor. - -.. code:: ipython3 - - import proplot as plot - import numpy as np - data1 = (np.random.rand(20,20) - 0.43).cumsum(axis=0) - data2 = (np.random.rand(20,20) - 0.57).cumsum(axis=0) - f, axs = plot.subplots(ncols=2, axwidth=2.5, aspect=1.5) - cmap = plot.Colormap('Moisture', cut=0.1) - axs.format(suptitle='Midpoint normalizer demo') - axs[0].contourf(data1, norm='midpoint', cmap=cmap, colorbar='b') - axs[0].format(title='Skewed positive data') - axs[1].contourf(data2, norm='midpoint', cmap=cmap, colorbar='b') - axs[1].format(title='Skewed negative data') - - - -.. image:: tutorial/tutorial_158_0.svg - - -Heatmaps and labels -------------------- - -The new `~proplot.axes.Axes.heatmap` command calls -`~matplotlib.axes.Axes.pcolormesh` and applies default formatting that -is suitable for heatmaps: no gridlines, no minor ticks, and major ticks -at the center of each box. Among other things, this is useful for -displaying autocorrelation matrices (see below). - -You can also add labels to `~matplotlib.axes.Axes.pcolor`, -`~matplotlib.axes.Axes.pcolormesh`, `~proplot.axes.Axes.heatmap`, -`~matplotlib.axes.Axes.contour`, and -`~matplotlib.axes.Axes.contourf` plots, thanks to -`~proplot.wrappers.cmap_wrapper`. Just pass the ``labels=True`` -keyword argument, and ProPlot will draw contour labels with -`~matplotlib.axes.Axes.clabel` or grid box labels with -`~matplotlib.axes.Axes.text`. Label colors are automatically chosen -based on the luminance of the underlying box or contour color. The label -text objects can be changed with the ``labels_kw`` dictionary keyword -arg and the ``precision`` keyword arg. See -`~proplot.wrappers.cmap_wrapper` for details. - -.. code:: ipython3 - - import proplot as plot - import pandas as pd - import numpy as np - # Heatmap with labels - f, axs = plot.subplots(ncols=2, axwidth=2, span=False, share=1) - data = np.random.rand(6,6) - data = pd.DataFrame(data, index=pd.Index(['a','b','c','d','e','f'])) - axs.format(suptitle='Labels demo') - ax = axs[0] - m = ax.heatmap(data, cmap='rocket', labels=True, precision=2, labels_kw={'weight':'bold'}) - ax.format(xlabel='xlabel', ylabel='ylabel', title='Heatmap plot with labels') - # Filled contours with labels - ax = axs[1] - m = ax.contourf(data.cumsum(axis=0), labels=True, cmap='rocket', labels_kw={'weight':'bold'}) - ax.format(xlabel='xlabel', ylabel='ylabel', title='Contourf plot with labels') - # Cross-correlation matrix - f, ax = plot.subplots(axwidth=3) - data = np.random.normal(size=(10,10)).cumsum(axis=0) - data = (data - data.mean(axis=0)) / data.std(axis=0) - data = (data.T @ data) / data.shape[0] - data[np.tril_indices(data.shape[0], -1)] = np.nan # empty boxes - data = pd.DataFrame(data, columns=list('abcdefghij'), index=list('abcdefghij')) - m = ax.heatmap(data, cmap='ColdHot', vmin=-1, vmax=1, N=100, - labels=True, labels_kw={'size':7, 'weight':'bold'}) - ax.format(title='Cross-correlation matrix', alpha=0, linewidth=0, - xloc='top', yloc='right', yreverse=True) - - - -.. image:: tutorial/tutorial_161_0.svg - - - -.. image:: tutorial/tutorial_161_1.svg - - -Easy error bars ---------------- - -Thanks to the `~proplot.wrappers.add_errorbars` wrapper, you can now -add error bars when using the `~matplotlib.axes.Axes.plot`, -`~matplotlib.axes.Axes.scatter`, `~matplotlib.axes.Axes.bar`, -`~matplotlib.axes.Axes.barh`, and `~matplotlib.axes.Axes.violinplot` -methods. If you pass 2D arrays of data to these commands with -``means=True`` or ``medians=True``, the *means or medians* of each -column are drawn as points, lines, or bars, and error bars represent the -*spread* in each column. You can draw both thin “bars” with optional -whiskers, and thick “boxes” overlayed on top of these bars. You can also -pass error bar coordinates manually with the ``bardata`` and ``boxdata`` -keyword args. See `~proplot.wrappers.add_errorbars` for details. - -.. code:: ipython3 - - import proplot as plot - import numpy as np - import pandas as pd - plot.rc['title.loc'] = 'uc' - plot.rc['axes.ymargin'] = plot.rc['axes.xmargin'] = 0.05 - data = np.random.rand(20,8).cumsum(axis=0).cumsum(axis=1)[:,::-1] + 20*np.random.normal(size=(20,8)) + 30 - f, axs = plot.subplots(nrows=3, aspect=1.5, axwidth=3, share=0, hratios=(2,1,1)) - axs.format(suptitle='Error bars with various plotting commands') - # Asking add_errorbars to calculate bars - ax = axs[0] - obj = ax.barh(data, color='red orange', means=True) - ax.format(title='Column statistics') - # Showing a standard deviation range instead of percentile range - ax = axs[1] - ax.scatter(data, color='k', marker='x', markersize=50, barcolor='gray5', - medians=True, barstd=True, barrange=(-1,1), barzorder=0, boxes=False, capsize=2) - # Supplying error bar data manually - ax = axs[2] - boxdata = np.percentile(data, (25,75), axis=0) - bardata = np.percentile(data, (5,95), axis=0) - ax.plot(data.mean(axis=0), boxes=False, marker='o', markersize=5, - edgecolor='k', color='cerulean', boxdata=boxdata, bardata=bardata) - # Formatting - axs[0].format(ylabel='column number', title='Bar plot', ygrid=False) - axs[1].format(title='Scatter plot') - axs[2].format(title='Line plot') - axs[1:].format(xlabel='column number', xticks=1, xgrid=False) - - - -.. image:: tutorial/tutorial_164_0.svg - - -Area plots ----------- - -Make area plots with the convenient aliases `~proplot.axes.Axes.area` -and `~proplot.axes.Axes.areax`. These point to the -`~matplotlib.axes.Axes.fill_between` and -`~matplotlib.axes.Axes.fill_betweenx` methods, which are wrapped with -`~proplot.wrappers.fill_between_wrapper` and -`~proplot.wrappers.fill_betweenx_wrapper`. - -The wrappers enable “stacking” successive columns of a 2D input array -like in `pandas`. They also add a new “``negpos``” keyword for -creating area plots that change color when the fill boundaries cross -each other. The most common use case for this is highlighting negative -and positive area underneath a line, as shown below. - -.. code:: ipython3 - - import proplot as plot - import numpy as np - plot.rc.reset() - plot.rc.margin = 0 - f, axs = plot.subplots(array=[[1,2],[3,3]], hratios=(1,0.8), share=0) - axs.format(xlabel='xlabel', ylabel='ylabel', suptitle='Area plot demo') - data = np.random.rand(5,3).cumsum(axis=0) - cycle = ('gray3', 'gray5', 'gray7') - ax = axs[0] - ax.areax(np.arange(5), data, data + np.random.rand(5)[:,None], cycle=cycle, alpha=0.5, - legend='uc', legend_kw={'center':True, 'ncols':2, 'labels':['z','y','qqqq']}, - ) - ax.format(title='Fill between columns') - ax = axs[1] - ax.area(np.arange(5), data, stacked=True, cycle=cycle, alpha=0.8, - legend='ul', legend_kw={'center':True, 'ncols':2, 'labels':['z','y','qqqq']}, - ) - ax.format(title='Stack between columns') - ax = axs[2] - data = 5*(np.random.rand(20)-0.5) - ax.area(data, negpos=True, negcolor='blue7', poscolor='red7') - ax.format(title='Negative and positive data', xlabel='xlabel', ylabel='ylabel') - axs.format(grid=False) - - - -.. image:: tutorial/tutorial_167_0.svg - - -Bar plots ---------- - -`~proplot.wrappers.bar_wrapper` and -`~proplot.wrappers.cycle_wrapper` make it easier to generate useful -bar plots. You can now pass 2D arrays to `~matplotlib.axes.Axes.bar` -or `~matplotlib.axes.Axes.barh`, and columns of data will be grouped -or stacked together. And if *x* coordinates are not provided, default -coordinates are applied, just like with `~matplotlib.axes.Axes.plot`. -See `~proplot.wrappers.bar_wrapper` for details. - -.. code:: ipython3 - - import proplot as plot - import numpy as np - import pandas as pd - plot.rc.titleloc = 'uc' - plot.rc.margin = 0.05 - f, axs = plot.subplots(nrows=2, aspect=2, axwidth=3.5, share=0, hratios=(3,2)) - data = np.random.rand(5,5).cumsum(axis=0).cumsum(axis=1)[:,::-1] - data = pd.DataFrame(data, columns=pd.Index(np.arange(1,6), name='column'), index=pd.Index(['a','b','c','d','e'], name='row idx')) - ax = axs[0] - obj = ax.bar(data, cycle='Reds', colorbar='ul', edgecolor='red9', colorbar_kw={'frameon':False}) - ax.format(xlocator=1, xminorlocator=0.5, ytickminor=False, title='Side-by-side', suptitle='Bar plot wrapper demo') - ax = axs[1] - obj = ax.barh(data.iloc[::-1,:], cycle='Blues', legend='ur', edgecolor='blue9', stacked=True) - ax.format(title='Stacked') - axs.format(grid=False) - - - -.. image:: tutorial/tutorial_170_0.svg - - -Box plots ---------- - -`~matplotlib.axes.Axes.boxplot` and -`~matplotlib.axes.Axes.violinplot` are now wrapped with -`~proplot.wrappers.boxplot_wrapper`, -`~proplot.wrappers.violinplot_wrapper`, and -`~proplot.wrappers.cycle_wrapper`, making it much easier to plot -distributions of data with aesthetically pleasing default settings and -automatic axis labeling. - -.. code:: ipython3 - - import proplot as plot - import numpy as np - import pandas as pd - N = 500 - f, axs = plot.subplots(ncols=2) - data = np.random.normal(size=(N,5)) + 2*(np.random.rand(N,5)-0.5)*np.arange(5) - data = pd.DataFrame(data, columns=pd.Index(['a','b','c','d','e'], name='xlabel')) - ax = axs[0] - obj1 = ax.boxplot(data, lw=0.7, marker='x', fillcolor='gray5', medianlw=1, mediancolor='k')#, boxprops={'color':'C0'})#, labels=data.columns) - ax.format(title='Box plots', titleloc='uc') - ax = axs[1] - obj2 = ax.violinplot(data, lw=0.7, fillcolor='gray7', points=500, bw_method=0.3, means=True) - ax.format(title='Violin plots', titleloc='uc') - axs.format(ymargin=0.1, xmargin=0.1, grid=False, suptitle='Boxes and violins demo') - - - - -.. image:: tutorial/tutorial_173_1.svg - - -Parametric plots ----------------- - -`~matplotlib.axes.Axes.plot` now accepts a ``cmap`` keyword – this -lets you draw line collections that map individual segments of the line -to individual colors. This can be useful for drawing “parametric” plots, -where you want to indicate the time or some other coordinate at each -point on the line. See `~proplot.axes.Axes.cmapline` for details. - -.. code:: ipython3 - - import proplot as plot - import numpy as np - plot.rc.reset() - N = 50 - cmap = 'IceFire' - values = np.linspace(-N/2, N/2, N) - f, axs = plot.subplots(share=0, ncols=2, wratios=(2,1), axwidth='6cm', aspect=(2,1)) - ax = axs[0] - m = ax.plot((np.random.rand(N)-0.5).cumsum(), np.random.rand(N), cmap=cmap, values=values, lw=7, extend='both') - ax.format(xlabel='xlabel', ylabel='ylabel', title='Line with smooth color gradations', titleweight='bold') - ax.colorbar(m, loc='b', label='parametric coordinate', locator=5) - N = 12 - ax = axs[1] - values = np.linspace(-N/2, N/2 - 1, N) - radii = np.linspace(1,0.2,N) - angles = np.linspace(0,4*np.pi,N) - x = radii*np.cos(1.4*angles) - y = radii*np.sin(1.4*angles) - m = ax.plot(x, y, values=values, linewidth=15, interp=False, cmap=cmap) - ax.format(xlim=(-1,1), ylim=(-1,1), title='With step gradations', titleweight='bold', xlabel='cosine angle', ylabel='sine angle') - ax.colorbar(m, loc='b', maxn=10, label=f'parametric coordinate') - - - - - - - -.. image:: tutorial/tutorial_176_1.svg - - -Misc plot enhancements ----------------------- - -Thanks to `~proplot.wrappers.scatter_wrapper` and -`~proplot.wrappers.cycle_wrapper`, `~matplotlib.axes.Axes.scatter` -now accepts 2D arrays, just like `~matplotlib.axes.Axes.plot`, and -successive calls to `~matplotlib.axes.Axes.scatter` can apply property -cycle keys other than ``color`` – for example, ``marker`` and -``markersize``. `~matplotlib.axes.Axes.scatter` also now optionally -accepts keywords that look like the `~matplotlib.axes.Axes.plot` -keywords, which is a bit less confusing. You can also pass colormaps to -`~matplotlib.axes.Axes.scatter` just as with matplotlib. - -I am also considering supporting 2D array input and property cycle -iteration for more obscure matplotlib plotting commands like -`~matplotlib.axes.Axes.stem`, `~matplotlib.axes.Axes.step`, -`~matplotlib.axes.Axes.vlines`, and `~matplotlib.axes.Axes.hlines`. -Stay tuned! - -.. code:: ipython3 - - import proplot as plot - import numpy as np - import pandas as pd - plot.rc.reset() - f, axs = plot.subplots(ncols=2, share=1) - x = (np.random.rand(20)-0).cumsum() - data = (np.random.rand(20,4)-0.5).cumsum(axis=0) - data = pd.DataFrame(data, columns=pd.Index(['a','b','c','d'], name='label')) - # Scatter demo - ax = axs[0] - ax.format(title='New prop cycle properties', suptitle='Scatter plot demo') - obj = ax.scatter(x, data, legend='ul', cycle='warm', legend_kw={'ncols':2}, - cycle_kw={'marker':['x','o','x','o'], 'markersize':[5,10,20,30]}) - ax = axs[1] - ax.format(title='Scatter plot with cmap') - data = (np.random.rand(2,100)-0.5) - obj = ax.scatter(*data, color=data.sum(axis=0), size=np.random.rand(100), smin=3, smax=30, - marker='o', cmap='dusk', colorbar='lr', colorbar_kw={'locator':0.5, 'label':'label'}) - axs.format(xlabel='xlabel', ylabel='ylabel') - - - -.. image:: tutorial/tutorial_179_0.svg From c2ae60073540c8e9a2a3ac7c0a5f9f38d1eab7b1 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 19:04:26 -0600 Subject: [PATCH 20/28] All caps constants --- proplot/__init__.py | 16 ++-- proplot/axes.py | 39 +++++---- proplot/projs.py | 34 ++++---- proplot/rctools.py | 68 +++++++-------- proplot/styletools.py | 187 +++++++++++++++++++++--------------------- proplot/subplots.py | 12 +-- proplot/utils.py | 14 ++-- proplot/wrappers.py | 81 +++++++++--------- 8 files changed, 231 insertions(+), 220 deletions(-) diff --git a/proplot/__init__.py b/proplot/__init__.py index d25e0a6c1..6cd0429b2 100644 --- a/proplot/__init__.py +++ b/proplot/__init__.py @@ -36,36 +36,36 @@ def _warning_proplot(message, category, filename, lineno, line=None): # of other modules last, and loads styletools early so we can try to update # TTFPATH before the fontManager is loaded by other matplotlib modules from .utils import * # misc stuff, debug mode -if _debug: +if DEBUG: import time t = time.clock() t0 = t from .styletools import * # colors and fonts -if _debug: +if DEBUG: print(f'styletools: {time.clock() - t}') t = time.clock() from .rctools import * # custom configuration implementation -if _debug: +if DEBUG: print(f'rctools: {time.clock() - t}') t = time.clock() from .axistools import * # locators, normalizers, and formatters -if _debug: +if DEBUG: print(f'axistools: {time.clock() - t}') t = time.clock() from .wrappers import * # wrappers -if _debug: +if DEBUG: print(f'wrappers: {time.clock() - t}') t = time.clock() from .projs import * # projections and whatnot -if _debug: +if DEBUG: print(f'projs: {time.clock() - t}') t = time.clock() from .axes import * # axes classes -if _debug: +if DEBUG: print(f'axes: {time.clock() - t}') t = time.clock() from .subplots import * # subplots and figure class -if _debug: +if DEBUG: print(f'subplots: {time.clock() - t}') t = time.clock() print(f'total time: {time.clock() - t0}') diff --git a/proplot/axes.py b/proplot/axes.py index 7dea565b7..28e3f04d4 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -51,7 +51,7 @@ import matplotlib.gridspec as mgridspec import matplotlib.transforms as mtransforms import matplotlib.collections as mcollections -from .rctools import rc, _rc_names_nodots +from .rctools import rc, RC_NAMES_NODOTS from . import utils, projs, axistools, wrappers from .utils import _notNone, units __all__ = [ @@ -63,13 +63,13 @@ ] # Translator for inset colorbars and legends -_side_translate = { +SIDE_TRANSLATE = { 'l':'left', 'r':'right', 'b':'bottom', 't':'top', } -_loc_translate = { +LOC_TRANSLATE = { None:None, 'l':'left', 'r':'right', @@ -99,13 +99,13 @@ } # Helper function -_abc_string = 'abcdefghijklmnopqrstuvwxyz' +ABC_STRING = 'abcdefghijklmnopqrstuvwxyz' def _abc(i): """Function for a-b-c labeling, returns a...z...aa...zz...aaa...zzz.""" if i < 26: - return _abc_string[i] + return ABC_STRING[i] else: - return _abc(i - 26) + _abc_string[i % 26] # sexy sexy recursion + return _abc(i - 26) + ABC_STRING[i % 26] # sexy sexy recursion # Import mapping toolbox try: @@ -192,8 +192,9 @@ def __init__(self, *args, number=None, @wrappers._expand_methods_list def __getattribute__(self, attr, *args): - """Applies the `~proplot.wrappers.text_wrapper` wrapper and disables - the redundant methods `_disabled_methods`.""" + """Disables the redundant methods `DISABLED_METHODS` with useful + error messages, and applies the `~proplot.wrappers.text_wrapper` + wrapper.""" obj = object.__getattribute__(self, attr, *args) for message,attrs in wrappers._disabled_methods.items(): if attr in attrs: @@ -254,7 +255,7 @@ def _get_title_props(self, abc=False, loc=None): cache = False # Above axes - loc = _loc_translate.get(loc, loc) + loc = LOC_TRANSLATE.get(loc, loc) if loc in ('top','bottom'): raise ValueError(f'Invalid title location {loc!r}.') elif loc in ('left','right','center'): @@ -298,7 +299,7 @@ def _loc_translate(loc, **kwargs): if loc is True: loc = None elif isinstance(loc, (str, Integral)): - loc = _loc_translate.get(loc, loc) # may still be invalid + loc = LOC_TRANSLATE.get(loc, loc) # may still be invalid return loc def _make_inset_locator(self, bounds, trans): @@ -340,7 +341,7 @@ def _reassign_suplabel(self, side): # this is called on the main axes *or* on the relevant panel itself # TODO: Mixed figure panels with super labels? How does that work? s = side[0] - side = _side_translate[s] + side = SIDE_TRANSLATE[s] if s == self._panel_side: ax = self._panel_parent else: @@ -588,7 +589,7 @@ def context(self, *, mode=2, rc_kw=None, **kwargs): kw = {} # for format rc_kw = rc_kw or {} for key,value in kwargs.items(): - key_fixed = _rc_names_nodots.get(key, None) + key_fixed = RC_NAMES_NODOTS.get(key, None) if key_fixed is None: kw[key] = value else: @@ -801,6 +802,11 @@ def areax(self, *args, **kwargs): `~proplot.wrappers.fill_betweenx_wrapper`.""" return self.fill_betweenx(*args, **kwargs) + def boxes(self, *args, **kwargs): + """Alias for `~matplotlib.axes.Axes.boxplot`, which is wrapped by + `~proplot.wrappers.boxplot_wrapper`.""" + return self.boxplot(*args, **kwargs) + def cmapline(self, *args, values=None, cmap=None, norm=None, interp=0, **kwargs): @@ -1349,6 +1355,11 @@ def panel_axes(self, side, **kwargs): """ return self.figure._add_axes_panel(self, side, **kwargs) + def violins(self, *args, **kwargs): + """Alias for `~matplotlib.axes.Axes.violinplot`, which is wrapped by + `~proplot.wrappers.violinplot_wrapper`.""" + return self.violinplot(*args, **kwargs) + panel = panel_axes """Alias for `~Axes.panel_axes`.""" inset = inset_axes @@ -2268,8 +2279,8 @@ def __init__(self, *args, **kwargs): # just to disable docstring inheritence @wrappers._expand_methods_list def __getattribute__(self, attr, *args): - """Disables the methods `_map_disabled_methods`, which are inappropriate - for map projections.""" + """Disables the methods `MAP_DISABLED_METHODS`, which are + inappropriate for map projections.""" if attr in wrappers._map_disabled_methods: raise AttributeError(f'Invalid plotting function {attr!r} for map projection axes.') return super().__getattribute__(attr, *args) diff --git a/proplot/projs.py b/proplot/projs.py index 1946b2ad5..b11f517bd 100644 --- a/proplot/projs.py +++ b/proplot/projs.py @@ -146,11 +146,11 @@ def Proj(name, basemap=False, **kwargs): # Basemap if basemap: import mpl_toolkits.basemap as mbasemap # verify package is available - name = _basemap_cyl.get(name, name) + name = BASEMAP_TRANSLATE.get(name, name) kwproj = basemap_rc.get(name, {}) kwproj.update(kwargs) kwproj.setdefault('fix_aspect', True) - if name in _basemap_circles: + if name[:2] in ('np', 'sp'): kwproj.setdefault('round', True) if name == 'geos': # fix non-conda installed basemap issue: https://github.com/matplotlib/basemap/issues/361 kwproj.setdefault('rsphere', (6378137.00,6356752.3142)) @@ -161,7 +161,7 @@ def Proj(name, basemap=False, **kwargs): # Cartopy else: import cartopy.crs as ccrs # verify package is available - kwargs = {_crs_translate.get(key, key): value for key,value in kwargs.items()} + kwargs = {CARTOPY_CRS_TRANSLATE.get(key, key): value for key,value in kwargs.items()} crs = cartopy_projs.get(name, None) if name == 'geos': # fix common mistake kwargs.pop('central_latitude', None) @@ -269,15 +269,19 @@ def __init__(self, central_longitude=0.0, globe=None): super().__init__(central_latitude=-90, central_longitude=central_longitude, globe=globe) -# Basemap stuff -_basemap_circles = ( - 'npstere', 'spstere', 'nplaea', - 'splaea', 'npaeqd', 'spaeqd', - ) -_basemap_cyl = { # aliases for 'cyl', that match PROJ4 name and common name +# Hidden constants +BASEMAP_TRANSLATE = { 'eqc': 'cyl', 'pcarree': 'cyl', } +CARTOPY_CRS_TRANSLATE = { # add to this + 'lat_0': 'central_latitude', + 'lon_0': 'central_longitude', + 'lat_min': 'min_latitude', + 'lat_max': 'max_latitude', + } + +# Documented constants basemap_rc = { # note either llcrn/urcrnr args (all 4) can be specified, or width and height can be specified 'eck4': {'lon_0':0}, 'geos': {'lon_0':0}, @@ -310,13 +314,6 @@ def __init__(self, central_longitude=0.0, globe=None): `~mpl_toolkits.basemap` will raise an error if you don't provide them, so ProPlot imposes some sensible default behavior.""" -# Cartopy stuff -_crs_translate = { # add to this - 'lat_0': 'central_latitude', - 'lon_0': 'central_longitude', - 'lat_min': 'min_latitude', - 'lat_max': 'max_latitude', - } cartopy_projs = {} """Mapping of "projection names" to cartopy `~cartopy.crs.Projection` classes.""" if _cartopy_installed: @@ -360,12 +357,12 @@ def __init__(self, central_longitude=0.0, globe=None): 'merc': 'Mercator', 'mill': 'Miller', 'moll': 'Mollweide', - 'npstere': 'NorthPolarStereo', # north/south pole stuff not in PROJ.4 + 'npstere': 'NorthPolarStereo', # np/sp stuff not in PROJ.4 'nsper': 'NearsidePerspective', 'ortho': 'Orthographic', 'osgb': 'OSGB', # UK; not in basemap or PROJ.4 'osni': 'OSNI', # Ireland; not in basemap or PROJ.4 - 'pcarree': 'PlateCarree', # common alt name + 'pcarree': 'PlateCarree', # common alternate name 'robin': 'Robinson', 'rotpole': 'RotatedPole', 'sinu': 'Sinusoidal', @@ -381,4 +378,3 @@ def __init__(self, central_longitude=0.0, globe=None): cartopy_projs[_name] = _class if _unavail: warnings.warn(f'Cartopy projection(s) {", ".join(_unavail)} are unavailable. Consider updating to cartopy >= 0.17.0.') - diff --git a/proplot/rctools.py b/proplot/rctools.py index ff9fa96fc..9d2c275b3 100644 --- a/proplot/rctools.py +++ b/proplot/rctools.py @@ -192,7 +192,7 @@ # TODO: Add 'style' setting that overrides .proplotrc # Adapted from seaborn; see: https://github.com/mwaskom/seaborn/blob/master/seaborn/rcmod.py from . import utils -from .utils import _counter, _timer, _debug +from .utils import _counter, _timer, DEBUG import re import os import sys @@ -201,11 +201,11 @@ import warnings import matplotlib.colors as mcolors import matplotlib.cm as mcm -if _debug: +if DEBUG: import time t = time.clock() import matplotlib.pyplot as plt -if _debug: +if DEBUG: print(f'pyplot: {time.clock() - t}') try: import IPython @@ -222,15 +222,15 @@ # Get default font # WARNING: Had issues with Helvetica Neue on Linux, weirdly some characters # failed to render/printed nonsense, but Helvetica was fine. -_user_rc = os.path.join(os.path.expanduser("~"), '.proplotrc') -_default_rc = os.path.join(os.path.dirname(__file__), '.proplotrc') # or parent, but that makes pip install distribution hard -_default_font = 'Helvetica' if sys.platform == 'linux' else 'Helvetica Neue' # says 'darwin' on mac -if not os.path.exists(_default_rc): +USER_RC = os.path.join(os.path.expanduser("~"), '.proplotrc') +DEFAULT_RC = os.path.join(os.path.dirname(__file__), '.proplotrc') +DEFAULT_FONT = 'Helvetica' if sys.platform == 'linux' else 'Helvetica Neue' +if not os.path.exists(DEFAULT_RC): raise ValueError('Default configuration file does not exist.') # "Global" settings and the lower-level settings they change # NOTE: This whole section, declaring dictionaries and sets, takes 1ms -_rcGlobals_children = { +RCGLOBALS_CHILDREN = { 'abc': [], 'span': [], 'share': [], @@ -272,9 +272,9 @@ } # Names of the new settings -_rc_names = {*_rcParams.keys()} -_rc_names_global = {*_rcGlobals_children.keys()} -_rc_names_custom = { +RC_NAMES = {*_rcParams.keys()} +RC_NAMES_GLOBAL = {*RCGLOBALS_CHILDREN.keys()} +RC_NAMES_CUSTOM = { 'axes.formatter.zerotrim', 'axes.formatter.timerotation', 'axes.gridminor', 'axes.geogrid', 'axes.alpha', 'image.levels', 'image.edgefix', @@ -300,28 +300,28 @@ } # Used by Axes.format, allows user to pass rc settings as keyword args, # way less verbose. For example, landcolor='b' vs. rc_kw={'land.color':'b'}. -_rc_names_nodots = { # useful for passing these as kwargs +RC_NAMES_NODOTS = { # useful for passing these as kwargs name.replace('.', ''):name for names in - (_rc_names_custom, _rc_names, _rc_names_global) + (RC_NAMES_CUSTOM, RC_NAMES, RC_NAMES_GLOBAL) for name in names } # Categories for returning dict of subcategory properties -_rc_categories = { - *(re.sub('\.[^.]*$', '', name) for names in (_rc_names_custom, _rc_names) for name in names), - *(re.sub('\..*$', '', name) for names in (_rc_names_custom, _rc_names) for name in names) +RC_CATEGORIES = { + *(re.sub('\.[^.]*$', '', name) for names in (RC_NAMES_CUSTOM, RC_NAMES) for name in names), + *(re.sub('\..*$', '', name) for names in (RC_NAMES_CUSTOM, RC_NAMES) for name in names) } # Unit conversion # See: https://matplotlib.org/users/customizing.html, all props matching # the below strings use the units 'points', and my special categories are inches! -_regex = re.compile('^.*(width|space|size|pad|len|small|large)$') # len is for ticklen, space is for subplots props +UNITS_REGEX = re.compile('^.*(width|space|size|pad|len|small|large)$') # len is for ticklen, space is for subplots props def _convert_units(key, value): """Converts certain keys to the units "points". If "key" is passed, tests that key against possible keys that accept physical units.""" # WARNING: Must keep colorbar and subplots units alive, so when user # requests em units, values change with respect to font size. The points # thing is a conveniene feature so not as important for them. - if isinstance(value,str) and _regex.match(key) \ + if isinstance(value,str) and UNITS_REGEX.match(key) \ and key.split('.')[0] not in ('colorbar','subplots'): value = utils.units(value, 'pt') return value @@ -390,7 +390,7 @@ def _get_globals(key=None, value=None): kw_custom['gridminor.linewidth'] = gridwidth*ratio # Now update linked settings if key not in ('gridratio','tickratio','ticklenratio'): - for name in _rcGlobals_children[key]: + for name in RCGLOBALS_CHILDREN[key]: val = _convert_units(key, value) if name in _rcExtraParams: kw_custom[name] = val @@ -424,7 +424,7 @@ def __init__(self): plt.style.use('default') # Load the defaults from file - for i,file in enumerate((_default_rc, _user_rc)): + for i,file in enumerate((DEFAULT_RC, USER_RC)): # Load if not os.path.exists(file): continue @@ -441,31 +441,31 @@ def __init__(self): # Add keys to dictionaries gkeys, ckeys = {*()}, {*()} for key,value in data.items(): - if key in _rc_names_global: + if key in RC_NAMES_GLOBAL: _rcGlobals[key] = value if i == 0: gkeys.add(key) - elif key in _rc_names_custom: + elif key in RC_NAMES_CUSTOM: value = _convert_units(key, value) _rcExtraParams[key] = value if i == 0: ckeys.add(key) - elif key in _rc_names: + elif key in RC_NAMES: value = _convert_units(key, value) _rcParams[key] = value else: raise RuntimeError(('Default', 'User')[i] + f' .proplotrc file has invalid key {key!r}.') # Make sure we did not miss anything if i == 0: - if gkeys != _rc_names_global: - raise RuntimeError(f'Default .proplotrc file has incomplete or invalid global keys {_rc_names_global - gkeys}.') - if ckeys != _rc_names_custom: - raise RuntimeError(f'Default .proplotrc file has incomplete or invalid custom keys {_rc_names_custom - ckeys}.') + if gkeys != RC_NAMES_GLOBAL: + raise RuntimeError(f'Default .proplotrc file has incomplete or invalid global keys {RC_NAMES_GLOBAL - gkeys}.') + if ckeys != RC_NAMES_CUSTOM: + raise RuntimeError(f'Default .proplotrc file has incomplete or invalid custom keys {RC_NAMES_CUSTOM - ckeys}.') # Set default fontname and cycler _set_cycler(_rcGlobals['cycle']) if _rcGlobals.get('fontname', None) is None: - _rcGlobals['fontname'] = _default_font + _rcGlobals['fontname'] = DEFAULT_FONT # Apply *global settings* to children settings rc, rc_new = _get_globals() @@ -495,7 +495,7 @@ def __getitem__(self, key): # Standardize # NOTE: If key is invalid, raise error down the line. if '.' not in key and key not in _rcGlobals: - key = _rc_names_nodots.get(key, key) + key = RC_NAMES_NODOTS.get(key, key) # Allow for special time-saving modes where we *ignore _rcParams* # or even *ignore _rcExtraParams*. @@ -535,7 +535,7 @@ def __setitem__(self, key, value): # Standardize # NOTE: If key is invalid, raise error down the line. if '.' not in key and key not in _rcGlobals: - key = _rc_names_nodots.get(key, key) + key = RC_NAMES_NODOTS.get(key, key) # Special keys if key == 'title.pad': @@ -611,13 +611,13 @@ def __setitem__(self, key, value): _rcParams.update(rc) _rcExtraParams.update(rc_new) # Update normal settings - elif key in _rc_names_custom: + elif key in RC_NAMES_CUSTOM: value = _convert_units(key, value) cache[key] = value if context: restore[key] = _rcExtraParams[key] _rcExtraParams[key] = value - elif key in _rc_names: + elif key in RC_NAMES: value = _convert_units(key, value) cache[key] = value if context: @@ -793,8 +793,8 @@ def category(self, cat, cache=True): set to ``0`` (see `~rc_configurator.context`). """ # Check - if cat not in _rc_categories: - raise ValueError(f'RC category {cat} does not exist. Valid categories are {", ".join(_rc_categories)}.') + if cat not in RC_CATEGORIES: + raise ValueError(f'RC category {cat} does not exist. Valid categories are {", ".join(RC_CATEGORIES)}.') if not cache: mode = 0 else: diff --git a/proplot/styletools.py b/proplot/styletools.py index a990e98ae..56339d668 100644 --- a/proplot/styletools.py +++ b/proplot/styletools.py @@ -43,26 +43,25 @@ ] # Data diretories -_delim = re.compile('[,\s]+') -_data_user = os.path.join(os.path.expanduser('~'), '.proplot') -_data_user_cmaps = os.path.join(_data_user, 'cmaps') -_data_user_cycles = os.path.join(_data_user, 'cycles') -_data_user_fonts = os.path.join(_data_user, 'fonts') # user fonts -_data_cmaps = os.path.join(os.path.dirname(__file__), 'cmaps') # or parent, but that makes pip install distribution hard -_data_cycles = os.path.join(os.path.dirname(__file__), 'cycles') # or parent, but that makes pip install distribution hard -_data_colors = os.path.join(os.path.dirname(__file__), 'colors') # or parent, but that makes pip install distribution hard -_data_fonts = os.path.join(os.path.dirname(__file__), 'fonts') # proplot fonts -if not os.path.isdir(_data_user): - os.mkdir(_data_user) -if not os.path.isdir(_data_user_cmaps): - os.mkdir(_data_user_cmaps) -if not os.path.isdir(_data_user_cycles): - os.mkdir(_data_user_cycles) -if not os.path.isdir(_data_user_fonts): - os.mkdir(_data_user_fonts) +DATA_USER = os.path.join(os.path.expanduser('~'), '.proplot') +DATA_USER_CMAPS = os.path.join(DATA_USER, 'cmaps') +DATA_USER_CYCLES = os.path.join(DATA_USER, 'cycles') +DATA_USER_FONTS = os.path.join(DATA_USER, 'fonts') # user fonts +DATA_CMAPS = os.path.join(os.path.dirname(__file__), 'cmaps') # or parent, but that makes pip install distribution hard +DATA_CYCLES = os.path.join(os.path.dirname(__file__), 'cycles') # or parent, but that makes pip install distribution hard +DATA_COLORS = os.path.join(os.path.dirname(__file__), 'colors') # or parent, but that makes pip install distribution hard +DATA_FONTS = os.path.join(os.path.dirname(__file__), 'fonts') # proplot fonts +if not os.path.isdir(DATA_USER): + os.mkdir(DATA_USER) +if not os.path.isdir(DATA_USER_CMAPS): + os.mkdir(DATA_USER_CMAPS) +if not os.path.isdir(DATA_USER_CYCLES): + os.mkdir(DATA_USER_CYCLES) +if not os.path.isdir(DATA_USER_FONTS): + os.mkdir(DATA_USER_FONTS) # Colormap stuff -_cmaps_categories = { +CMAPS_CATEGORIES = { # User cmaps, placed here so it always appears on top 'User': (), # Assorted origin, but these belong together @@ -149,7 +148,7 @@ 'seismic', 'terrain', 'nipy_spectral', # origin ambiguous ), } -_cmaps_delete = ( +CMAPS_DELETE = ( 'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink', 'spring', 'summer', 'autumn', 'winter', 'cool', 'wistia', 'afmhot', 'gist_heat', 'copper', @@ -158,7 +157,7 @@ 'gnuplot', 'gnuplot2', 'cmrmap', 'hsv', 'hot', 'rainbow', 'gist_rainbow', 'jet', 'nipy_spectral', 'gist_ncar', 'cubehelix', ) -_cmaps_div_slices = { +CMAPS_DIV_SLICES = { 'piyg': (None, 2, None), 'prgn': (None, 1, 2, None), # purple red green 'brbg': (None, 2, 3, None), # brown blue green @@ -172,13 +171,13 @@ 'negpos': (None, 3, None), 'drywet': (None, 3, None), } # slice args used to split up segments of names -_cmaps_div_pairs = [ +CMAPS_DIV_PAIRS = [ (name, ''.join(reversed([name[slice(*idxs[i:i+2])] for i in range(len(idxs)-1)])),) - for name,idxs in _cmaps_div_slices.items() + for name,idxs in CMAPS_DIV_SLICES.items() ] # tuple pairs of mirror image cmap names # Color cycle stuff -_cycles_preset = { +CYCLES_PRESET = { # Default matplotlib v2 'default': ['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'], # From stylesheets @@ -196,35 +195,18 @@ 'Contrast': ["#2B4162", "#FA9F42", "#E0E0E2", "#A21817", "#0B6E4F"], 'Floral': ["#23395B", "#D81E5B", "#FFFD98", "#B9E3C6", "#59C9A5"], } -_cycles_delete = ( +CYCLES_DELETE = ( 'tab10', 'tab20', 'tab20b', 'tab20c', 'paired', 'pastel1', 'pastel2', 'dark2', ) # unappealing cycles, and cycles that are just merged monochrome colormaps -_cycles_rename = ( +CYCLES_RENAME = ( ('Accent','Set1'), ) # rename existing cycles -# Named color stuff -_color_names_filter_space = 'hcl' # dist 'distinct-ness' of colors using this colorspace -_color_names_filter_thresh = 0.10 # bigger number equals fewer colors -_color_names_opencolors = ( - 'red', 'pink', 'grape', 'violet', - 'indigo', 'blue', 'cyan', 'teal', - 'green', 'lime', 'yellow', 'orange', 'gray' - ) -_color_names_shorthands = { - 'b': 'blue', 'g': 'green', 'r': 'red', 'c': 'cyan', - 'm': 'magenta', 'y': 'yellow', 'k': 'black', 'w': 'white' - } -_color_names_bad = re.compile('(' + '|'.join(( - 'shit', 'poop', 'poo', 'pee', 'piss', 'puke', 'vomit', 'snot', 'booger', 'bile', 'diarrhea', - )) + ')') # filter these out, let's try to be professional here... -_color_names_add = ( - 'charcoal', 'sky blue', 'eggshell', 'sea blue', 'coral', 'aqua', 'tomato red', 'brick red', 'crimson', - 'red orange', 'yellow orange', 'yellow green', 'blue green', - 'blue violet', 'red violet', - ) # common names that should always be included -_color_names_translate = tuple((re.compile(regex), sub) for regex,sub in ( +# Named color filter props +FILTER_SPACE = 'hcl' # dist 'distinct-ness' of colors using this colorspace +FILTER_THRESH = 0.10 # bigger number equals fewer colors +FILTER_TRANSLATIONS = tuple((re.compile(regex), sub) for regex,sub in ( ('/', ' '), ("'s", ''), ('grey', 'gray'), ('pinky', 'pink'), @@ -243,9 +225,34 @@ ('grayblue', 'gray blue'), ('lightblue', 'light blue') )) # prevent registering similar-sounding names +FILTER_ADD = ( + 'charcoal', 'sky blue', 'eggshell', 'sea blue', 'coral', 'aqua', 'tomato red', 'brick red', 'crimson', + 'red orange', 'yellow orange', 'yellow green', 'blue green', + 'blue violet', 'red violet', + ) # common names that should always be included +FILTER_BAD = re.compile('(' + '|'.join(( + 'shit', 'poop', 'poo', 'pee', 'piss', 'puke', 'vomit', 'snot', 'booger', 'bile', 'diarrhea', + )) + ')') # filter these out, let's try to be professional here... + +# Named color stuff +OPEN_COLORS = ( + 'red', 'pink', 'grape', 'violet', + 'indigo', 'blue', 'cyan', 'teal', + 'green', 'lime', 'yellow', 'orange', 'gray' + ) +BASE_COLORS_FULL = { + 'blue': (0, 0, 1), + 'green': (0, 0.5, 0), + 'red': (1, 0, 0), + 'cyan': (0, 0.75, 0.75), + 'magenta': (0.75, 0, 0.75), + 'yellow': (0.75, 0.75, 0), + 'black': (0, 0, 0), + 'white': (1, 1, 1), + } # Color math and color spaces -_color_space_aliases = { +CSPACE_ALIASES = { 'rgb': 'rgb', 'hsv': 'hsv', 'hpl': 'hpl', @@ -254,32 +261,26 @@ 'hsluv': 'hsl', 'hcl': 'hcl', } -_color_space_channel_idxs = { +CSPACE_IDXS = { 'hue': 0, 'chroma': 1, 'saturation': 1, 'luminance': 2, 'alpha': 3, } -_color_space_channel_scales = { - 'rgb': (1,1,1), - 'hcl': (360,100,100), - 'hsl': (360,100,100), - 'hpl': (360,100,100) - } # Check data -_data_user_paths = {*()} -_data_allowed_paths = {'cmaps', 'cycles', 'fonts'} +DATA_USER_PATHS = {*()} +DATA_ALLOWED_PATHS = {'cmaps', 'cycles', 'fonts'} def _check_data(): """Checks the data folder and issues helpful warning message for new users. This is called inside every register function.""" - global _data_user_paths + global DATA_USER_PATHS data_user = os.path.join(os.path.expanduser('~'), '.proplot') data_user_paths = {os.path.basename(path) for path in glob.glob(os.path.join(data_user, '*'))} - if data_user_paths != _data_user_paths and data_user_paths > _data_allowed_paths: - _data_user_paths = data_user_paths - warnings.warn(f'Found extra files {", ".join(data_user_paths - _data_allowed_paths)} in the ~/.proplot folder. Files must be placed in the .proplot/cmaps, .proplot/cycles, or .proplot/fonts subfolders.') + if data_user_paths != DATA_USER_PATHS and data_user_paths > DATA_ALLOWED_PATHS: + DATA_USER_PATHS = data_user_paths + warnings.warn(f'Found extra files {", ".join(data_user_paths - DATA_ALLOWED_PATHS)} in the ~/.proplot folder. Files must be placed in the .proplot/cmaps, .proplot/cycles, or .proplot/fonts subfolders.') #-----------------------------------------------------------------------------# # Classes @@ -423,7 +424,7 @@ def _sanitize_key(self, key, mirror=True): reverse = True if mirror and not super().__contains__(key): # search for mirrored key key_mirror = key - for mirror in _cmaps_div_pairs: + for mirror in CMAPS_DIV_PAIRS: try: idx = mirror.index(key) key_mirror = mirror[1 - idx] @@ -464,7 +465,7 @@ def update(self, *args, **kwargs): #-----------------------------------------------------------------------------# def _get_space(space): """Verify requested colorspace is valid.""" - space = _color_space_aliases.get(space.lower(), None) + space = CSPACE_ALIASES.get(space.lower(), None) if space is None: raise ValueError(f'Unknown colorspace "{space}".') return space @@ -477,7 +478,7 @@ def _get_channel(color, channel, space='hsl'): # Interpret channel if callable(color) or isinstance(color, Number): return color - channel = _color_space_channel_idxs.get(channel, None) + channel = CSPACE_IDXS.get(channel, None) if channel is None: raise ValueError(f'Unknown channel {channel}.') if channel not in (0,1,2): @@ -1180,13 +1181,13 @@ def Colormap(*args, name=None, cyclic=None, listmode='perceptual', # Save listed colormap i.e. color cycle if isinstance(cmap, mcolors.ListedColormap): basename = f'{name}.hex' - filename = os.path.join(_data_user_cycles, basename) + filename = os.path.join(DATA_USER_CYCLES, basename) with open(filename, 'w') as f: f.write(','.join(mcolors.to_hex(color) for color in cmap.colors)) # Save segment data directly else: basename = f'{name}.json' - filename = os.path.join(_data_user_cmaps, basename) + filename = os.path.join(DATA_USER_CMAPS, basename) data = {} for key,value in cmap._segmentdata.items(): data[key] = np.array(value).astype(float).tolist() # from np.float to builtin float, and to list of lists @@ -1331,7 +1332,7 @@ def Cycle(*args, samples=None, name=None, save=False, # Save the cycle if save: basename = f'{name}.hex' - filename = os.path.join(_data_user_cycles, basename) + filename = os.path.join(DATA_USER_CYCLES, basename) with open(filename, 'w') as f: f.write(','.join(mcolors.to_hex(color) for color in cmap.colors)) print(f'Saved color cycle to "{basename}".') @@ -1975,7 +1976,8 @@ def _read_cmap_cycle_data(filename): # Load # NOTE: This appears to be biggest import time bottleneck! Increases # time from 0.05s to 0.2s, with numpy loadtxt or with this regex thing. - data = [_delim.split(line.strip()) for line in open(filename).readlines()] + delim = re.compile('[,\s]+') + data = [delim.split(line.strip()) for line in open(filename).readlines()] try: data = [[float(num) for num in line] for line in data] except ValueError: @@ -2067,7 +2069,7 @@ def register_cmaps(): # Turn original matplotlib maps from ListedColormaps to LinearSegmentedColormaps # It makes zero sense to me that they are stored as ListedColormaps _check_data() - for name in _cmaps_categories['Matplotlib Originals']: # initialize as empty lists + for name in CMAPS_CATEGORIES['Matplotlib Originals']: # initialize as empty lists cmap = mcm.cmap_d._getitem(name, None) if cmap and isinstance(cmap, mcolors.ListedColormap): mcm.cmap_d[name] = mcolors.LinearSegmentedColormap.from_list(name, cmap.colors) @@ -2080,7 +2082,7 @@ def register_cmaps(): mcm.cmap_d[name] = mcm.cmap_d[name].reversed(name=name) # make spectral go from 'cold' to 'hot' # Remove gross cmaps (strong-arm user into using the better ones) - for name in _cmaps_delete: + for name in CMAPS_DELETE: mcm.cmap_d.pop(name, None) # Fill initial user-accessible cmap list with the colormaps we will keep @@ -2089,8 +2091,8 @@ def register_cmaps(): # Add colormaps from ProPlot and user directories N = rcParams['image.lut'] # query this when register function is called - for filename in sorted(glob.glob(os.path.join(_data_cmaps, '*'))) + \ - sorted(glob.glob(os.path.join(_data_user_cmaps, '*'))): + for filename in sorted(glob.glob(os.path.join(DATA_CMAPS, '*'))) + \ + sorted(glob.glob(os.path.join(DATA_USER_CMAPS, '*'))): name, x, data = _read_cmap_cycle_data(filename) if name is None: continue @@ -2124,9 +2126,9 @@ def register_cycles(): cycles.clear() # Remove gross cycles, change the names of some others - for name in _cycles_delete: + for name in CYCLES_DELETE: mcm.cmap_d.pop(name, None) - for (name1,name2) in _cycles_rename: + for (name1,name2) in CYCLES_RENAME: cycle = mcm.cmap_d.pop(name1, None) if cycle: mcm.cmap_d[name2] = cycle @@ -2134,8 +2136,8 @@ def register_cycles(): # Read cycles from directories icycles = {} - for filename in sorted(glob.glob(os.path.join(_data_cycles, '*'))) + \ - sorted(glob.glob(os.path.join(_data_user_cycles, '*'))): + for filename in sorted(glob.glob(os.path.join(DATA_CYCLES, '*'))) + \ + sorted(glob.glob(os.path.join(DATA_USER_CYCLES, '*'))): name, _, data = _read_cmap_cycle_data(filename) if name is None: continue @@ -2145,7 +2147,7 @@ def register_cycles(): icycles[name] = data # Register cycles as ListedColormaps - for name,colors in {**_cycles_preset, **icycles}.items(): + for name,colors in {**CYCLES_PRESET, **icycles}.items(): cmap = mcolors.ListedColormap(colors, name=name) cmap.colors = [to_rgb(color) for color in cmap.colors] # sanitize mcm.cmap_d[name] = cmap @@ -2165,10 +2167,11 @@ def register_colors(nmax=np.inf): # Reset native colors dictionary and add some default groups # Add in CSS4 so no surprises for user, but we will not encourage this # usage and will omit CSS4 colors from the demo table. - colordict.clear() scale = (360, 100, 100) - base = {**mcolors.BASE_COLORS} # make copy - base.update({_color_names_shorthands[key]:value for key,value in base.items()}) # full names + base = {} + colordict.clear() + base.update(mcolors.BASE_COLORS) + base.update(BASE_COLORS_FULL) mcolors.colorConverter.colors.clear() # clean out! mcolors.colorConverter.cache.clear() # clean out! for name,dict_ in (('base',base), ('css',mcolors.CSS4_COLORS)): @@ -2176,7 +2179,7 @@ def register_colors(nmax=np.inf): # Load colors from file and get their HCL values names = ('opencolors', 'xkcd', 'crayola') # order is preference for identical color names from different groups - files = [os.path.join(_data_colors, f'{name}.txt') for name in names] + files = [os.path.join(DATA_COLORS, f'{name}.txt') for name in names] pairs = [] seen = {*base} # never overwrite base names, e.g. 'blue' and 'b'! hcls = np.empty((0,3)) @@ -2196,13 +2199,13 @@ def register_colors(nmax=np.inf): for name,color in data: # is list of name, color tuples if i >= nmax: # e.g. for xkcd colors break - for regex,sub in _color_names_translate: + for regex,sub in FILTER_TRANSLATIONS: name = regex.sub(sub, name) - if name in seen or _color_names_bad.search(name): + if name in seen or FILTER_BAD.search(name): continue seen.add(name) pairs.append((category, name)) # save the category name pair - ihcls.append(to_xyz(color, space=_color_names_filter_space)) + ihcls.append(to_xyz(color, space=FILTER_SPACE)) dict_[name] = color # save the color i += 1 _colordict_unfiltered[category] = dict_ @@ -2212,10 +2215,10 @@ def register_colors(nmax=np.inf): # WARNING: Unique axis argument requires numpy version >=1.13 deleted = 0 hcls = hcls/np.array(scale) - hcls = np.round(hcls/_color_names_filter_thresh).astype(np.int64) + hcls = np.round(hcls/FILTER_THRESH).astype(np.int64) _, idxs, _ = np.unique(hcls, return_index=True, return_counts=True, axis=0) # get unique rows for idx,(category,name) in enumerate(pairs): - if name not in _color_names_add and idx not in idxs: + if name not in FILTER_ADD and idx not in idxs: deleted += 1 else: colordict[category][name] = _colordict_unfiltered[category][name] @@ -2265,7 +2268,7 @@ def register_fonts(): # NOTE: Delay font_manager import, because want to avoid rebuilding font # cache, which means import must come after TTFPATH added to environ! _check_data() - paths = _data_fonts + ':' + _data_user_fonts + paths = DATA_FONTS + ':' + DATA_USER_FONTS if 'TTFPATH' not in os.environ: os.environ['TTFPATH'] = paths elif paths not in os.environ['TTFPATH']: @@ -2280,8 +2283,8 @@ def register_fonts(): mfonts._rebuild() # Populate font lists - fonts_system[:] = sorted({font.name for font in mfonts.fontManager.ttflist if not (_data_user_fonts in font.fname or _data_fonts in font.fname)}) - fonts_proplot[:] = sorted({font.name for font in mfonts.fontManager.ttflist if (_data_user_fonts in font.fname or _data_fonts in font.fname)}) + fonts_system[:] = sorted({font.name for font in mfonts.fontManager.ttflist if not (DATA_USER_FONTS in font.fname or DATA_FONTS in font.fname)}) + fonts_proplot[:] = sorted({font.name for font in mfonts.fontManager.ttflist if (DATA_USER_FONTS in font.fname or DATA_FONTS in font.fname)}) fonts[:] = sorted((*fonts_system, *fonts_proplot)) #-----------------------------------------------------------------------------# @@ -2547,8 +2550,8 @@ def show_colors(nbreak=17, minsat=0.2): if opencolors: wscale = 0.5 swatch = 1.5 - nrows, ncols = 10, len(_color_names_opencolors) # rows and columns - plot_names = [[name + str(i) for i in range(nrows)] for name in _color_names_opencolors] + nrows, ncols = 10, len(OPEN_COLORS) # rows and columns + plot_names = [[name + str(i) for i in range(nrows)] for name in OPEN_COLORS] nrows = nrows*2 ncols = (ncols+1)//2 plot_names = np.array(plot_names, order='C') @@ -2561,7 +2564,7 @@ def show_colors(nbreak=17, minsat=0.2): wscale = 1 swatch = 1 colors_hcl = { - key: [c/s for c,s in zip(to_xyz(value, _color_names_filter_space), scale)] + key: [c/s for c,s in zip(to_xyz(value, FILTER_SPACE), scale)] for key,value in icolors.items() } # Separate into columns and roughly sort by brightness in these columns @@ -2653,7 +2656,7 @@ def show_cmaps(*args, N=256, length=4.0, width=0.2): # Get dictionary of registered colormaps and their categories imaps = [name.lower() for name in imaps] - cats = {cat:names for cat,names in _cmaps_categories.items()} + cats = {cat:names for cat,names in CMAPS_CATEGORIES.items()} cats_plot = {cat:[name for name in names if name.lower() in imaps] for cat,names in cats.items()} # Distinguish known from unknown (i.e. user) maps, add as a new category imaps_known = [name.lower() for cat,names in cats.items() for name in names if name.lower() in imaps] diff --git a/proplot/subplots.py b/proplot/subplots.py index 2c38a97f5..9a81021ff 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -54,7 +54,7 @@ ] # Translation -_side_translate = { +SIDE_TRANSLATE = { 'l':'left', 'r':'right', 'b':'bottom', @@ -437,7 +437,7 @@ def get_wspace(self): return self.get_width_ratios()[1::2] def get_active_height_ratios(self): - """Returns height ratios exlucding slots allocated for spaces.""" + """Returns height ratios excluding slots allocated for spaces.""" return self.get_height_ratios()[::2] def get_active_width_ratios(self): @@ -769,7 +769,7 @@ def _add_axes_panel(self, ax, side, filled=False, **kwargs): if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') ax = ax._panel_parent or ax # redirect to main axes - side = _side_translate[s] + side = SIDE_TRANSLATE[s] share, width, space, space_orig = _panels_kwargs(s, filled=filled, figure=False, **kwargs) @@ -824,7 +824,7 @@ def _add_figure_panel(self, side, s = side[0] if s not in 'lrbt': raise ValueError(f'Invalid side {side!r}.') - side = _side_translate[s] + side = SIDE_TRANSLATE[s] _, width, space, space_orig = _panels_kwargs(s, filled=True, figure=True, **kwargs) if s in 'lr': @@ -1199,9 +1199,9 @@ def _insert_row_column(self, side, idx, idx_space = idx - 1*bool(s in 'br') idx_offset = 1*bool(s in 'tl') if s in 'lr': - x, w, ncols = 'x', 'w', 'ncols' + w, ncols = 'w', 'ncols' else: - x, w, ncols = 'y', 'h', 'nrows' + w, ncols = 'h', 'nrows' # Load arrays and test if we need to insert subplots_kw = self._subplots_kw diff --git a/proplot/utils.py b/proplot/utils.py index 6038ec5f2..7e9271e92 100644 --- a/proplot/utils.py +++ b/proplot/utils.py @@ -14,7 +14,7 @@ from icecream import ic except ImportError: # graceful fallback if IceCream isn't installed ic = lambda *a: None if not a else (a[0] if len(a) == 1 else a) # noqa -__all__ = ['arange', 'edges', 'units', '_debug'] +__all__ = ['arange', 'edges', 'units', 'DEBUG'] # Important private helper func def _notNone(*args, names=None): @@ -44,14 +44,14 @@ def _notNone(*args, names=None): return first # Debug decorators -_debug = False # debug mode, used for profiling and activating timer decorators +DEBUG = False # debug mode, used for profiling and activating timer decorators def _logger(func): """A decorator that logs the activity of the script (it actually just prints it, but it could be logging!). See: https://stackoverflow.com/a/1594484/4970632""" @functools.wraps(func) def decorator(*args, **kwargs): res = func(*args, **kwargs) - if _debug: + if DEBUG: print(f'{func.__name__} called with: {args} {kwargs}') return res return decorator @@ -61,10 +61,10 @@ def _timer(func): See: https://stackoverflow.com/a/1594484/4970632""" @functools.wraps(func) def decorator(*args, **kwargs): - if _debug: + if DEBUG: t = time.clock() res = func(*args, **kwargs) - if _debug: + if DEBUG: print(f'{func.__name__}() time: {time.clock()-t}s') return res return decorator @@ -74,10 +74,10 @@ def _counter(func): has benn running. See: https://stackoverflow.com/a/1594484/4970632""" @functools.wraps(func) def decorator(*args, **kwargs): - if _debug: + if DEBUG: t = time.clock() res = func(*args, **kwargs) - if _debug: + if DEBUG: decorator.time += (time.clock() - t) decorator.count += 1 print(f'{func.__name__}() cumulative time: {decorator.time}s ({decorator.count} calls)') diff --git a/proplot/wrappers.py b/proplot/wrappers.py index b6b11fd09..e0dca987b 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -49,37 +49,37 @@ def _load_objects(): # Methods for wrapping # TODO: 'quiver', 'streamplot' for cmap? # TODO: 'hlines', 'vlines', 'axhline', 'axvline', 'axhspan', 'axvspan', -_errorbar_methods = ('plot', 'scatter', 'bar', 'violinplot' +ERRORBAR_METHODS = ('plot', 'scatter', 'bar', 'violinplot' ) -_centers_methods = ('contour', 'contourf', 'quiver', 'streamplot', 'barbs' +CENTERS_METHODS = ('contour', 'contourf', 'quiver', 'streamplot', 'barbs' ) -_edges_methods = ('pcolor', 'pcolormesh' +EDGES_METHODS = ('pcolor', 'pcolormesh' ) -_1d_methods = ('plot', 'scatter', 'bar', 'hist', 'boxplot', 'violinplot', +D1_METHODS = ('plot', 'scatter', 'bar', 'hist', 'boxplot', 'violinplot', 'pie', 'fill_between', 'fill_betweenx', 'step', 'stem', 'hexbin', ) -_2d_methods = (*_centers_methods, *_edges_methods +D2_METHODS = (*CENTERS_METHODS, *EDGES_METHODS ) -_cycle_methods = ('plot', 'scatter', 'bar', 'hist', 'boxplot', 'violinplot', +CYCLE_METHODS = ('plot', 'scatter', 'bar', 'hist', 'boxplot', 'violinplot', 'pie', 'fill_between', 'fill_betweenx', 'step', 'stem', ) -_cmap_methods = ('contour', 'contourf', 'pcolor', 'pcolormesh', +CMAP_METHODS = ('contour', 'contourf', 'pcolor', 'pcolormesh', 'tripcolor', 'tricontour', 'tricontourf', 'cmapline', 'hexbin', 'matshow', 'imshow', 'spy', 'hist2d' ) -_crs_methods = ('get_extent', 'set_extent', 'set_xticks', 'set_yticks' +CRS_METHODS = ('get_extent', 'set_extent', 'set_xticks', 'set_yticks' ) -_latlon_methods = ('plot', 'scatter', *_edges_methods, *_centers_methods +LATLON_METHODS = ('plot', 'scatter', *EDGES_METHODS, *CENTERS_METHODS ) -_transform_methods = ('plot', 'scatter', 'tripcolor', - 'tricontour', 'tricontourf', *_edges_methods, *_centers_methods +TRANSFORM_METHODS = ('plot', 'scatter', 'tripcolor', + 'tricontour', 'tricontourf', *EDGES_METHODS, *CENTERS_METHODS ) # Disabled methods; keys are error messages # TODO: rigorous support for violin plots, bar, barh, streamline and quiver # TODO: 'table', 'eventplot', 'pie', 'xcorr', 'acorr', 'psd', 'csd', # 'magnitude_spectrum', 'angle_spectrum', 'phase_spectrum', 'cohere', 'specgram' -_disabled_methods = { +DISABLED_METHODS = { "Redundant function {} has been disabled. Control axis scale with format(xscale='scale', yscale='scale').": ('semilogx', 'semilogy', 'loglog'), "Redundant function {} has been disabled. Date formatters will be used automatically when x/y coordinates are python datetime or numpy datetime64.": @@ -87,7 +87,7 @@ def _load_objects(): "Redundant function {} has been disabled. Use proj='polar' in subplots() call, then use the angle as your *x* coordinate and radius as your *y* coordinate.": ('polar',) } -_map_disabled_methods = ( +MAP_DISABLED_METHODS = ( # These are obvious # TODO: Error bars? Will they work? Also bar and barh can be used w/ polar 'twinx', 'twiny', @@ -100,7 +100,7 @@ def _load_objects(): ) # Keywords for styling cmap overridden plots -_cmap_style_kwargs = { +STYLE_ARGS_TRANSLATE = { 'contour': {'colors':'colors', 'linewidths':'linewidths', 'linestyles':'linestyles'}, 'hexbin': {'colors':'edgecolors', 'linewidths':'linewidths'}, 'tricontour': {'colors':'colors', 'linewidths':'linewidths', 'linestyles':'linestyles'}, @@ -126,19 +126,19 @@ def _expand_methods_list(func): names, this is much cleaner.""" doc = func.__doc__ for name,methods in ( - ('_1d_methods', _1d_methods), - ('_2d_methods', _2d_methods), - ('_errorbar_methods', _errorbar_methods), - ('_centers_methods', _centers_methods), - ('_edges_methods', _edges_methods), - ('_centers_edges_methods', (*_centers_methods, *_edges_methods)), - ('_latlon_methods', _latlon_methods), - ('_crs_methods', _crs_methods), - ('_transform_methods', _transform_methods), - ('_cycle_methods', _cycle_methods), - ('_cmap_methods', _cmap_methods), - ('_disabled_methods', (*(method for methods in _disabled_methods.values() for method in methods),)), - ('_map_disabled_methods', _map_disabled_methods), + ('D1_METHODS', D1_METHODS), + ('D2_METHODS', D2_METHODS), + ('ERRORBAR_METHODS', ERRORBAR_METHODS), + ('CENTERS_METHODS', CENTERS_METHODS), + ('EDGES_METHODS', EDGES_METHODS), + ('CENTERS_EDGES_METHODS', (*CENTERS_METHODS, *EDGES_METHODS)), + ('LATLON_METHODS', LATLON_METHODS), + ('CRS_METHODS', CRS_METHODS), + ('TRANSFORM_METHODS', TRANSFORM_METHODS), + ('CYCLE_METHODS', CYCLE_METHODS), + ('CMAP_METHODS', CMAP_METHODS), + ('DISABLED_METHODS', (*(method for methods in DISABLED_METHODS.values() for method in methods),)), + ('MAP_DISABLED_METHODS', MAP_DISABLED_METHODS), ): if f'`{name}`' not in doc: continue @@ -204,7 +204,7 @@ def _auto_label(data, axis=None, units=True): @_expand_methods_list def autoformat_1d(self, func, *args, **kwargs): - """Wraps `_1d_methods`, standardized acceptable input and optionally + """Wraps `D1_METHODS`, standardized acceptable input and optionally modifies the x axis label, y axis label, title, and axis ticks if the input is a `~xarray.DataArray`, `~pandas.DataFrame`, or `~pandas.Series`. Permits 2D array input for all of these commands, in @@ -291,7 +291,7 @@ def autoformat_1d(self, func, *args, **kwargs): @_expand_methods_list def autoformat_2d(self, func, *args, order='C', **kwargs): - """Wraps `_2d_methods`, optionally modifies the x axis label, y axis + """Wraps `D2_METHODS`, optionally modifies the x axis label, y axis label, title, and axis ticks if the input is a `~xarray.DataArray`, `~pandas.DataFrame`, or `~pandas.Series`. Infers dependent variable coordinates from the input array if none were provided.""" @@ -384,7 +384,7 @@ def autoformat_2d(self, func, *args, order='C', **kwargs): #------------------------------------------------------------------------------ @_expand_methods_list def enforce_centers(self, func, *args, order='C', **kwargs): - """Wraps 2D plotting functions that take coordinate *centers* (`_centers_methods`), + """Wraps 2D plotting functions that take coordinate *centers* (`CENTERS_METHODS`), calculates centers if graticule *edges* were provided.""" # Checks whether sizes match up, checks whether graticule was input x, y, *Zs = args @@ -412,7 +412,7 @@ def enforce_centers(self, func, *args, order='C', **kwargs): @_expand_methods_list def enforce_edges(self, func, *args, order='C', **kwargs): - """Wraps 2D plotting functions that take graticule *edges* (`_edges_methods`), + """Wraps 2D plotting functions that take graticule *edges* (`EDGES_METHODS`), calculates edges if coordinate *centers* were provided.""" # Checks that sizes match up, checks whether graticule was input x, y, *Zs = args @@ -470,7 +470,7 @@ def add_errorbars(self, func, *args, boxzorder=3, barzorder=3, **kwargs): """ - Wraps `_errorbar_methods`, adds support for drawing error bars. Includes + Wraps `ERRORBAR_METHODS`, adds support for drawing error bars. Includes options for interpreting columns of data as ranges, representing the mean or median of each column with lines, points, or bars, and drawing error bars representing percentile ranges or standard deviation multiples for @@ -670,6 +670,7 @@ def scatter_wrapper(self, func, *args, nargs = len(args) if len(args) > 4: raise ValueError(f'Expected 1-4 positional args, got {nargs}.') + args = list(args) if len(args) == 4: c = args.pop(1) if len(args) == 3: @@ -1120,7 +1121,7 @@ def wrapper(*args, **kwargs): @_expand_methods_list def cartopy_transform(self, func, *args, transform=None, **kwargs): """ - Wraps `_transform_methods` for `~proplot.axes.ProjectionAxesCartopy` axes. + Wraps `TRANSFORM_METHODS` for `~proplot.axes.ProjectionAxesCartopy` axes. With the default `~cartopy.mpl.geoaxes.GeoAxes` API, you need to pass ``transform=cartopy.crs.PlateCarree()`` if your data coordinates are @@ -1140,7 +1141,7 @@ def cartopy_transform(self, func, *args, transform=None, **kwargs): @_expand_methods_list def cartopy_crs(self, func, *args, crs=None, **kwargs): """ - Wraps `_crs_methods` for `~proplot.axes.ProjectionAxesCartopy` axes. + Wraps `CRS_METHODS` for `~proplot.axes.ProjectionAxesCartopy` axes. As with `cartopy_transform`, but passes ``crs=cartopy.crs.PlateCarree()`` as the default. Also fixes bug associated with tight bounding boxes and `~cartopy.mpl.geoaxes.GeoAxes.set_extent`. @@ -1167,7 +1168,7 @@ def cartopy_crs(self, func, *args, crs=None, **kwargs): @_expand_methods_list def basemap_latlon(self, func, *args, latlon=True, **kwargs): """ - Wraps `_latlon_methods` for `~proplot.axes.BasemapProjectionAxes` axes. + Wraps `LATLON_METHODS` for `~proplot.axes.BasemapProjectionAxes` axes. With the default `~mpl_toolkits.basemap` API, you need to pass ``latlon=True`` if your data coordinates are longitude and latitude @@ -1215,7 +1216,7 @@ def _gridfix_coordinates(lon, lat): @_expand_methods_list def cartopy_gridfix(self, func, lon, lat, *Zs, globe=False, **kwargs): """ - Wraps `_centers_edges_methods` for `~proplot.axes.ProjectionAxesCartopy` axes. + Wraps `CENTERS_EDGES_METHODS` for `~proplot.axes.ProjectionAxesCartopy` axes. Makes 1D longitude vectors monotonic and adds the `globe` keyword arg to optionally make data coverage *global*. Passing ``globe=True`` does the @@ -1255,7 +1256,7 @@ def cartopy_gridfix(self, func, lon, lat, *Zs, globe=False, **kwargs): @_expand_methods_list def basemap_gridfix(self, func, lon, lat, *Zs, globe=False, **kwargs): """ - Wraps `_centers_edges_methods` for `~proplot.axes.BasemapProjectionAxes` axes. + Wraps `CENTERS_EDGES_METHODS` for `~proplot.axes.BasemapProjectionAxes` axes. Makes 1D longitude vectors monotonic and cycles them to fit within the map edges (i.e. if the projection central longitude is 90 degrees, will permute @@ -1367,7 +1368,7 @@ def cycle_wrapper(self, func, *args, panel_kw=None, **kwargs): """ - Wraps methods that use the property cycler (`_cycle_methods`), + Wraps methods that use the property cycler (`CYCLE_METHODS`), adds features for controlling colors in the property cycler and drawing legends or colorbars in one go. Critically, this wrapper also **standardizes acceptable input** -- these methods now all accept 2D arrays holding columns @@ -1638,7 +1639,7 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, color=None, colors=None, edgecolor=None, edgecolors=None, **kwargs): """ - Wraps methods that take a ``cmap`` argument (`_cmap_methods`), + Wraps methods that take a ``cmap`` argument (`CMAP_METHODS`), adds several new keyword args and features. Uses the `~proplot.styletools.BinNorm` normalizer to bin data into discrete color levels (see notes). @@ -1784,7 +1785,7 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, colors = _notNone(color, colors, edgecolor, edgecolors, None, names=('color', 'colors', 'edgecolor', 'edgecolors')) linewidths = _notNone(lw, linewidth, linewidths, None, names=('lw', 'linewidth', 'linewidths')) linestyles = _notNone(ls, linestyle, linestyles, None, names=('ls', 'linestyle', 'linestyles')) - style_kw = _cmap_style_kwargs.get(name, {}) + style_kw = STYLE_ARGS_TRANSLATE.get(name, {}) edgefix = _notNone(edgefix, rc['image.edgefix']) for key,value in (('colors',colors), ('linewidths',linewidths), ('linestyles',linestyles)): if value is None: From f9c6eda855e82f2349fb53385570ff02e41931d9 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 19:06:15 -0600 Subject: [PATCH 21/28] Name change fix --- proplot/axes.py | 70 ++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/proplot/axes.py b/proplot/axes.py index 28e3f04d4..7bcac53e1 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -196,7 +196,7 @@ def __getattribute__(self, attr, *args): error messages, and applies the `~proplot.wrappers.text_wrapper` wrapper.""" obj = object.__getattribute__(self, attr, *args) - for message,attrs in wrappers._disabled_methods.items(): + for message,attrs in wrappers.DISABLED_METHODS.items(): if attr in attrs: raise AttributeError(message.format(attr)) if attr == 'text': @@ -1455,21 +1455,21 @@ def __getattribute__(self, attr, *args): obj = super().__getattribute__(attr, *args) if callable(obj): # Step 3) Color usage wrappers - if attr in wrappers._cmap_methods: # must come first! + if attr in wrappers.CMAP_METHODS: # must come first! obj = wrappers._cmap_wrapper(self, obj) - elif attr in wrappers._cycle_methods: + elif attr in wrappers.CYCLE_METHODS: obj = wrappers._cycle_wrapper(self, obj) # Step 2) Utilities - if attr in wrappers._centers_methods: + if attr in wrappers.CENTERS_METHODS: obj = wrappers._enforce_centers(self, obj) - elif attr in wrappers._edges_methods: + elif attr in wrappers.EDGES_METHODS: obj = wrappers._enforce_edges(self, obj) - elif attr in wrappers._errorbar_methods: + elif attr in wrappers.ERRORBAR_METHODS: obj = wrappers._add_errorbars(self, obj) # Step 1) Parse input - if attr in wrappers._2d_methods: + if attr in wrappers.D2_METHODS: obj = wrappers._autoformat_2d(self, obj) - elif attr in wrappers._1d_methods: + elif attr in wrappers.D1_METHODS: obj = wrappers._autoformat_1d(self, obj) # Step 0) Special wrappers if attr == 'plot': @@ -2281,7 +2281,7 @@ def __init__(self, *args, **kwargs): # just to disable docstring inheritence def __getattribute__(self, attr, *args): """Disables the methods `MAP_DISABLED_METHODS`, which are inappropriate for map projections.""" - if attr in wrappers._map_disabled_methods: + if attr in wrappers.MAP_DISABLED_METHODS: raise AttributeError(f'Invalid plotting function {attr!r} for map projection axes.') return super().__getattribute__(attr, *args) @@ -2404,22 +2404,22 @@ def __getattribute__(self, attr, *args): obj = super().__getattribute__(attr, *args) if callable(obj): # Step 4) Color usage wrappers - if attr in wrappers._cmap_methods: + if attr in wrappers.CMAP_METHODS: obj = wrappers._cmap_wrapper(self, obj) - elif attr in wrappers._cycle_methods: + elif attr in wrappers.CYCLE_METHODS: obj = wrappers._cycle_wrapper(self, obj) # Step 3) Fix coordinate grid - if attr in wrappers._edges_methods or attr in wrappers._centers_methods: + if attr in wrappers.EDGES_METHODS or attr in wrappers.CENTERS_METHODS: obj = wrappers._cartopy_gridfix(self, obj) # Step 2) Utilities - if attr in wrappers._edges_methods: + if attr in wrappers.EDGES_METHODS: obj = wrappers._enforce_edges(self, obj) - elif attr in wrappers._centers_methods: + elif attr in wrappers.CENTERS_METHODS: obj = wrappers._enforce_centers(self, obj) # Step 1) Parse args input - if attr in wrappers._2d_methods: + if attr in wrappers.D2_METHODS: obj = wrappers._autoformat_2d(self, obj) - elif attr in wrappers._1d_methods: + elif attr in wrappers.D1_METHODS: obj = wrappers._autoformat_1d(self, obj) # Step 0) Special wrappers if attr == 'plot': @@ -2673,27 +2673,27 @@ def __getattribute__(self, attr, *args): obj = super().__getattribute__(attr, *args) if callable(obj): # Step 5) Color usage wrappers - if attr in wrappers._cmap_methods: + if attr in wrappers.CMAP_METHODS: obj = wrappers._cmap_wrapper(self, obj) - elif attr in wrappers._cycle_methods: + elif attr in wrappers.CYCLE_METHODS: obj = wrappers._cycle_wrapper(self, obj) # Step 4) Fix coordinate grid - if attr in wrappers._edges_methods or attr in wrappers._centers_methods: + if attr in wrappers.EDGES_METHODS or attr in wrappers.CENTERS_METHODS: obj = wrappers._cartopy_gridfix(self, obj) # Step 3) Utilities - if attr in wrappers._edges_methods: + if attr in wrappers.EDGES_METHODS: obj = wrappers._enforce_edges(self, obj) - elif attr in wrappers._centers_methods: + elif attr in wrappers.CENTERS_METHODS: obj = wrappers._enforce_centers(self, obj) # Step 2) Better default keywords - if attr in wrappers._transform_methods: + if attr in wrappers.TRANSFORM_METHODS: obj = wrappers._cartopy_transform(self, obj) - elif attr in wrappers._crs_methods: + elif attr in wrappers.CRS_METHODS: obj = wrappers._cartopy_crs(self, obj) # Step 1) Parse args input - if attr in wrappers._2d_methods: + if attr in wrappers.D2_METHODS: obj = wrappers._autoformat_2d(self, obj) - elif attr in wrappers._1d_methods: + elif attr in wrappers.D1_METHODS: obj = wrappers._autoformat_1d(self, obj) # Step 0) Special wrappers if attr == 'plot': @@ -2999,30 +2999,30 @@ def __getattribute__(self, attr, *args): # instance accessible from axes instance! Can of worms and had bunch of # weird errors! Just pick the ones you think user will want to use. obj = super().__getattribute__(attr, *args) - if attr in wrappers._latlon_methods or attr in wrappers._edges_methods \ - or attr in wrappers._centers_methods: + if attr in wrappers.LATLON_METHODS or attr in wrappers.EDGES_METHODS \ + or attr in wrappers.CENTERS_METHODS: # Step 6) Call identically named Basemap object method obj = wrappers._basemap_call(self, obj) # Step 5) Color usage wrappers - if attr in wrappers._cmap_methods: + if attr in wrappers.CMAP_METHODS: obj = wrappers._cmap_wrapper(self, obj) - elif attr in wrappers._cycle_methods: + elif attr in wrappers.CYCLE_METHODS: obj = wrappers._cycle_wrapper(self, obj) # Step 4) Fix coordinate grid - if attr in wrappers._edges_methods or attr in wrappers._centers_methods: + if attr in wrappers.EDGES_METHODS or attr in wrappers.CENTERS_METHODS: obj = wrappers._basemap_gridfix(self, obj) # Step 3) Utilities - if attr in wrappers._edges_methods: + if attr in wrappers.EDGES_METHODS: obj = wrappers._enforce_edges(self, obj) - elif attr in wrappers._centers_methods: + elif attr in wrappers.CENTERS_METHODS: obj = wrappers._enforce_centers(self, obj) # Step 2) Better default keywords - if attr in wrappers._latlon_methods: + if attr in wrappers.LATLON_METHODS: obj = wrappers._basemap_latlon(self, obj) # Step 1) Parse args input - if attr in wrappers._2d_methods: + if attr in wrappers.D2_METHODS: obj = wrappers._autoformat_2d(self, obj) - elif attr in wrappers._1d_methods: + elif attr in wrappers.D1_METHODS: obj = wrappers._autoformat_1d(self, obj) # Step 0) Special wrappers if attr == 'plot': From c880ef15ac687d5281c523284d8107e3efea6995 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 22:27:04 -0600 Subject: [PATCH 22/28] Figure documentation --- proplot/subplots.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index 9a81021ff..b8ddcecc5 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -708,11 +708,14 @@ def __init__(self, panels. If float, units are inches. If string, units are interpreted by `~proplot.utils.units`. includepanels : bool, optional - Whether to include panels when centering spanning *x* axis labels, - *y* axis labels, and figure "super titles". Defaults to ``False``. + Whether to include panels when centering *x* axis labels, + *y* axis labels, and figure "super titles" along the edge of the + subplot grid. Defaults to ``False``. autoformat : bool, optional - Whether to automatically format the axes when a `~pandas.Series`, - `~pandas.DataFrame` or `~xarray.DataArray` is passed to a plotting + Whether to automatically configure *x* axis labels, *y* axis + labels, axis formatters, axes titles, colorbar labels, and legend + labels when a `~pandas.Series`, `~pandas.DataFrame` or + `~xarray.DataArray` with relevant metadata is passed to a plotting command. gridspec_kw, subplots_kw, subplots_orig_kw Keywords used for initializing the main gridspec, for initializing From 7a611b507278c2a1588eeccb8a80ae4622c227f7 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 22:45:13 -0600 Subject: [PATCH 23/28] _subplots_geometry cleanup --- proplot/subplots.py | 66 ++++++++++++++++++++++----------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index b8ddcecc5..99a22435e 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -517,8 +517,7 @@ def _subplots_geometry(**kwargs): necessary to reconstruct and modify this configuration. Note that `wspace`, `hspace`, `left`, `right`, `top`, and `bottom` always have fixed physical units, then we scale figure width, figure height, and width - and height ratios to accommodate requested geometry. And panel widths and - heights are also fixed.""" + and height ratios to accommodate spaces.""" # Dimensions and geometry nrows, ncols = kwargs['nrows'], kwargs['ncols'] aspect, xref, yref = kwargs['aspect'], kwargs['xref'], kwargs['yref'] @@ -529,11 +528,12 @@ def _subplots_geometry(**kwargs): wratios, hratios = kwargs['wratios'], kwargs['hratios'] left, bottom = kwargs['left'], kwargs['bottom'] right, top = kwargs['right'], kwargs['top'] - # Panel string toggles + # Panel string toggles, lists containing empty strings '' (indicating a + # main axes), or one of 'l', 'r', 'b', 't' (indicating axes panels) or + # 'f' (indicating figure panels) wpanels, hpanels = kwargs['wpanels'], kwargs['hpanels'] # Checks, important now that we modify gridspec geometry - # TODO: Helper func? Nah, no big deal if len(hratios) != nrows: raise ValueError(f'Expected {nrows} width ratios for {nrows} rows, got {len(hratios)}.') if len(wratios) != ncols: @@ -548,7 +548,6 @@ def _subplots_geometry(**kwargs): raise ValueError(f'Expected {ncols} wpanel toggles for {ncols} columns, got {len(wpanels)}.') # Get indices corresponding to main axes or main axes space slots - # TODO: Shouldn't panel space be included in these calculations? idxs_ratios, idxs_space = [], [] for panels in (hpanels,wpanels): # Ratio indices @@ -564,23 +563,24 @@ def _subplots_geometry(**kwargs): space_idxs.append(idx + offset - 1) idxs_space.append(space_idxs) # Separate the panel and axes ratios - haxes = [hratios[idx] for idx in idxs_ratios[0]] - waxes = [wratios[idx] for idx in idxs_ratios[1]] - hpanels = [ratio for idx,ratio in enumerate(hratios) if idx not in idxs_ratios[0]] - wpanels = [ratio for idx,ratio in enumerate(wratios) if idx not in idxs_ratios[1]] - haxes_space = [hspace[idx] for idx in idxs_space[0]] - waxes_space = [wspace[idx] for idx in idxs_space[1]] + hratios_main = [hratios[idx] for idx in idxs_ratios[0]] + wratios_main = [wratios[idx] for idx in idxs_ratios[1]] + hratios_panels = [ratio for idx,ratio in enumerate(hratios) if idx not in idxs_ratios[0]] + wratios_panels = [ratio for idx,ratio in enumerate(wratios) if idx not in idxs_ratios[1]] + hspace_main = [hspace[idx] for idx in idxs_space[0]] + wspace_main = [wspace[idx] for idx in idxs_space[1]] # Reduced geometry - nrows_ax = len(haxes) - ncols_ax = len(waxes) + nrows_main = len(hratios_main) + ncols_main = len(wratios_main) # Get reference properties, account for panel slots in space and ratios + # TODO: Shouldn't panel space be included in these calculations? (x1, x2), (y1, y2) = xref, yref dx, dy = x2 - x1 + 1, y2 - y1 + 1 - rwspace = sum(waxes_space[x1:x2]) - rhspace = sum(haxes_space[y1:y2]) - rwratio = (ncols_ax*sum(waxes[x1:x2+1]))/(dx*sum(waxes)) - rhratio = (nrows_ax*sum(haxes[y1:y2+1]))/(dy*sum(haxes)) + rwspace = sum(wspace_main[x1:x2]) + rhspace = sum(hspace_main[y1:y2]) + rwratio = (ncols_main*sum(wratios_main[x1:x2+1]))/(dx*sum(wratios_main)) + rhratio = (nrows_main*sum(hratios_main[y1:y2+1]))/(dy*sum(hratios_main)) if rwratio == 0 or rhratio == 0: raise RuntimeError(f'Something went wrong, got wratio={rwratio!r} and hratio={rhratio!r} for reference axes.') if np.iterable(aspect): @@ -596,31 +596,31 @@ def _subplots_geometry(**kwargs): axwidth = units(rc['subplots.axwidth']) if axheight is not None: auto_width = True - axheight_all = (nrows_ax*(axheight - rhspace))/(dy*rhratio) - height = axheight_all + top + bottom + sum(hspace) + sum(hpanels) + axheight_all = (nrows_main*(axheight - rhspace))/(dy*rhratio) + height = axheight_all + top + bottom + sum(hspace) + sum(hratios_panels) if axwidth is not None: auto_height = True - axwidth_all = (ncols_ax*(axwidth - rwspace))/(dx*rwratio) - width = axwidth_all + left + right + sum(wspace) + sum(wpanels) + axwidth_all = (ncols_main*(axwidth - rwspace))/(dx*rwratio) + width = axwidth_all + left + right + sum(wspace) + sum(wratios_panels) if axwidth is not None and axheight is not None: auto_width = auto_height = False else: if height is not None: - axheight_all = height - top - bottom - sum(hspace) - sum(hpanels) - axheight = (axheight_all*dy*rhratio)/nrows_ax + rhspace + axheight_all = height - top - bottom - sum(hspace) - sum(hratios_panels) + axheight = (axheight_all*dy*rhratio)/nrows_main + rhspace if width is not None: - axwidth_all = width - left - right - sum(wspace) - sum(wpanels) - axwidth = (axwidth_all*dx*rwratio)/ncols_ax + rwspace + axwidth_all = width - left - right - sum(wspace) - sum(wratios_panels) + axwidth = (axwidth_all*dx*rwratio)/ncols_main + rwspace # Automatically figure dim that was not specified above if auto_height: axheight = axwidth/aspect - axheight_all = (nrows_ax*(axheight - rhspace))/(dy*rhratio) - height = axheight_all + top + bottom + sum(hspace) + sum(hpanels) + axheight_all = (nrows_main*(axheight - rhspace))/(dy*rhratio) + height = axheight_all + top + bottom + sum(hspace) + sum(hratios_panels) elif auto_width: axwidth = axheight*aspect - axwidth_all = (ncols_ax*(axwidth - rwspace))/(dx*rwratio) - width = axwidth_all + left + right + sum(wspace) + sum(wpanels) + axwidth_all = (ncols_main*(axwidth - rwspace))/(dx*rwratio) + width = axwidth_all + left + right + sum(wspace) + sum(wratios_panels) if axwidth_all < 0: raise ValueError(f"Not enough room for axes (would have width {axwidth_all}). Try using tight=False, increasing figure width, or decreasing 'left', 'right', or 'wspace' spaces.") if axheight_all < 0: @@ -628,11 +628,11 @@ def _subplots_geometry(**kwargs): # Reconstruct the ratios array with physical units for subplot slots # The panel slots are unchanged because panels have fixed widths - waxes = axwidth_all*np.array(waxes)/sum(waxes) - haxes = axheight_all*np.array(haxes)/sum(haxes) - for idx,ratio in zip(idxs_ratios[0],haxes): + wratios_main = axwidth_all*np.array(wratios_main)/sum(wratios_main) + hratios_main = axheight_all*np.array(hratios_main)/sum(hratios_main) + for idx,ratio in zip(idxs_ratios[0],hratios_main): hratios[idx] = ratio - for idx,ratio in zip(idxs_ratios[1],waxes): + for idx,ratio in zip(idxs_ratios[1],wratios_main): wratios[idx] = ratio # Convert margins to figure-relative coordinates From ddcc5fe01dc0a1896cc55434ac35330079791058 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Thu, 5 Sep 2019 22:57:12 -0600 Subject: [PATCH 24/28] Repair dead links in wrappers.py --- proplot/wrappers.py | 39 ++++++++++++--------------------------- 1 file changed, 12 insertions(+), 27 deletions(-) diff --git a/proplot/wrappers.py b/proplot/wrappers.py index e0dca987b..3d9d7c2f4 100644 --- a/proplot/wrappers.py +++ b/proplot/wrappers.py @@ -1121,7 +1121,7 @@ def wrapper(*args, **kwargs): @_expand_methods_list def cartopy_transform(self, func, *args, transform=None, **kwargs): """ - Wraps `TRANSFORM_METHODS` for `~proplot.axes.ProjectionAxesCartopy` axes. + Wraps `TRANSFORM_METHODS` for `~proplot.axes.CartopyAxes` axes. With the default `~cartopy.mpl.geoaxes.GeoAxes` API, you need to pass ``transform=cartopy.crs.PlateCarree()`` if your data coordinates are @@ -1141,7 +1141,7 @@ def cartopy_transform(self, func, *args, transform=None, **kwargs): @_expand_methods_list def cartopy_crs(self, func, *args, crs=None, **kwargs): """ - Wraps `CRS_METHODS` for `~proplot.axes.ProjectionAxesCartopy` axes. + Wraps `CRS_METHODS` for `~proplot.axes.CartopyAxes` axes. As with `cartopy_transform`, but passes ``crs=cartopy.crs.PlateCarree()`` as the default. Also fixes bug associated with tight bounding boxes and `~cartopy.mpl.geoaxes.GeoAxes.set_extent`. @@ -1168,7 +1168,7 @@ def cartopy_crs(self, func, *args, crs=None, **kwargs): @_expand_methods_list def basemap_latlon(self, func, *args, latlon=True, **kwargs): """ - Wraps `LATLON_METHODS` for `~proplot.axes.BasemapProjectionAxes` axes. + Wraps `LATLON_METHODS` for `~proplot.axes.BasemapAxes` axes. With the default `~mpl_toolkits.basemap` API, you need to pass ``latlon=True`` if your data coordinates are longitude and latitude @@ -1216,7 +1216,7 @@ def _gridfix_coordinates(lon, lat): @_expand_methods_list def cartopy_gridfix(self, func, lon, lat, *Zs, globe=False, **kwargs): """ - Wraps `CENTERS_EDGES_METHODS` for `~proplot.axes.ProjectionAxesCartopy` axes. + Wraps `CENTERS_EDGES_METHODS` for `~proplot.axes.CartopyAxes` axes. Makes 1D longitude vectors monotonic and adds the `globe` keyword arg to optionally make data coverage *global*. Passing ``globe=True`` does the @@ -1256,7 +1256,7 @@ def cartopy_gridfix(self, func, lon, lat, *Zs, globe=False, **kwargs): @_expand_methods_list def basemap_gridfix(self, func, lon, lat, *Zs, globe=False, **kwargs): """ - Wraps `CENTERS_EDGES_METHODS` for `~proplot.axes.BasemapProjectionAxes` axes. + Wraps `CENTERS_EDGES_METHODS` for `~proplot.axes.BasemapAxes` axes. Makes 1D longitude vectors monotonic and cycles them to fit within the map edges (i.e. if the projection central longitude is 90 degrees, will permute @@ -1398,8 +1398,7 @@ def cycle_wrapper(self, func, *args, `~proplot.axes.Axes.legend`. legend_kw : dict-like, optional Ignored if `legend` is ``None``. Extra keyword args for our call - to `~proplot.axes.Axes` `~proplot.axes.Axes.legend` or - `~proplot.axes.PanelAxes` `~proplot.axes.PanelAxes.legend`. + to `~proplot.axes.Axes.legend`. colorbar : bool, int, or str, optional If not ``None``, this is a location specifying where to draw an *inset* or *panel* colorbar from the resulting handle(s). If ``True``, the @@ -1407,8 +1406,7 @@ def cycle_wrapper(self, func, *args, `~proplot.axes.Axes.colorbar`. colorbar_kw : dict-like, optional Ignored if `colorbar` is ``None``. Extra keyword args for our call - to the `~proplot.axes.Axes` `~proplot.axes.Axes.colorbar` or - `~proplot.axes.PanelAxes` `~proplot.axes.PanelAxes.colorbar` methods. + to `~proplot.axes.Axes.colorbar`. panel_kw : dict-like, optional Dictionary of keyword arguments passed to `~proplot.axes.Axes.panel`, if you are generating an @@ -1421,7 +1419,7 @@ def cycle_wrapper(self, func, *args, See also -------- - `~proplot.styletools.Cycle` + `~proplot.styletools.Cycle`, `~proplot.styletools.colors` Note ---- @@ -1724,8 +1722,7 @@ def cmap_wrapper(self, func, *args, cmap=None, cmap_kw=None, `~proplot.axes.Axes.colorbar`. colorbar_kw : dict-like, optional Ignored if `colorbar` is ``None``. Extra keyword args for our call - to `~proplot.axes.Axes` `~proplot.axes.Axes.colorbar` or - `~proplot.axes.PanelAxes` `~proplot.axes.PanelAxes.colorbar`. + to `~proplot.axes.Axes.colorbar`. panel_kw : dict-like, optional Dictionary of keyword arguments passed to `~proplot.axes.Axes.panel`, if you are generating an @@ -2051,7 +2048,7 @@ def legend_wrapper(self, **kwargs): """ Wraps `~matplotlib.axes.Axes` `~matplotlib.axes.Axes.legend` and - `~proplot.axes.PanelAxes` `~proplot.axes.PanelAxes.legend`, adds some + `~proplot.subplots.Figure` `~proplot.subplots.Figure.legend`, adds some handy features. Parameters @@ -2115,10 +2112,6 @@ def legend_wrapper(self, ---------------- **kwargs Passed to `~matplotlib.axes.Axes.legend`. - - See also - -------- - `~proplot.axes.PanelAxes.legend` """ # First get legend settings and interpret kwargs. if order not in ('F','C'): @@ -2212,10 +2205,6 @@ def legend_wrapper(self, pairs = [pairs[i*ncol:(i+1)*ncol] for i in range(len(pairs))] # to list of iterables if list_of_lists: # remove empty lists, pops up in some examples pairs = [ipairs for ipairs in pairs if ipairs] - # Special case of PanelAxes with invisible frame, axes tight bounding - # box will include frame even though it is invisible! - if getattr(self, '_side', None) in ('top','bottom') and not frameon: - kwargs.setdefault('borderpad', 0) # Now draw legend(s) legs = [] @@ -2384,8 +2373,8 @@ def colorbar_wrapper(self, fixticks=False, **kwargs): """ - Wraps `~proplot.axes.Axes` `~proplot.axes.Axes.colorbar` and - `~proplot.axes.PanelAxes` `~proplot.axes.PanelAxes.colorbar`, adds some + Wraps `~matplotlib.axes.Axes` `~matplotlib.axes.Axes.colorbar` and + `~proplot.subplots.Figure` `~proplot.subplots.Figure.colorbar`, adds some handy features. Parameters @@ -2493,10 +2482,6 @@ def colorbar_wrapper(self, ---------------- **kwargs Passed to `~matplotlib.figure.Figure.colorbar`. - - See also - -------- - `~proplot.axes.Axes.colorbar`, `~proplot.axes.PanelAxes.colorbar` """ # Developer notes # * Colorbar axes must be of type `matplotlib.axes.Axes`, From 039aea3100f9f72b7152c0054efc408e81eca6ab Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Fri, 6 Sep 2019 11:58:55 -0600 Subject: [PATCH 25/28] Demo stacked figure panels --- docs/tutorial/tutorial_17_1.svg | 46718 +++++++++++++++--------------- docs/tutorial/tutorial_18_0.svg | 18576 ++++++------ docs/tutorial1.rst | 20 +- proplot/subplots.py | 2 +- 4 files changed, 34278 insertions(+), 31038 deletions(-) diff --git a/docs/tutorial/tutorial_17_1.svg b/docs/tutorial/tutorial_17_1.svg index 31455f0b7..7ff60b7c1 100644 --- a/docs/tutorial/tutorial_17_1.svg +++ b/docs/tutorial/tutorial_17_1.svg @@ -2,7 +2,7 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2434,17 +2434,17 @@ L 111.34375 28.011875 +" id="m20783d3e4c" style="stroke:#000000;stroke-width:0.6;"/> - + - + @@ -2453,59 +2453,59 @@ L 0 4 +" id="mad6423b812" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - + - + @@ -2516,10 +2516,10 @@ L 0 2 +" id="m9584ccdb5f" style="stroke:#000000;stroke-width:0.6;"/> - + @@ -2575,7 +2575,7 @@ Q 4.203125 38.703125 4.203125 34.796875 z " id="HelveticaNeue-48"/> - + @@ -2583,7 +2583,7 @@ z - + @@ -2628,7 +2628,7 @@ L 18.40625 62.203125 z " id="HelveticaNeue-53"/> - + @@ -2636,7 +2636,7 @@ z - + @@ -2655,7 +2655,7 @@ L 27.09375 0 z " id="HelveticaNeue-49"/> - + @@ -2664,12 +2664,12 @@ z - + - + @@ -2680,137 +2680,137 @@ z +" id="m676c46c23a" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -2878,7 +2878,7 @@ L 21.703125 15.40625 z " id="HelveticaNeue-Bold-46"/> - + @@ -2886,2483 +2886,2483 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + @@ -5371,162 +5371,162 @@ L 209.74375 28.011875 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -5572,7 +5572,7 @@ L 19.59375 71.40625 z " id="HelveticaNeue-Bold-98"/> - + @@ -5580,2483 +5580,2483 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + @@ -8065,162 +8065,162 @@ L 308.14375 28.011875 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -8257,7 +8257,7 @@ Q 39.203125 42.40625 40.59375 33.5 z " id="HelveticaNeue-Bold-99"/> - + @@ -8265,2483 +8265,2483 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + @@ -10750,12 +10750,12 @@ L 111.34375 135.838437 - + - + @@ -10763,12 +10763,12 @@ L 111.34375 135.838437 - + - + @@ -10776,12 +10776,12 @@ L 111.34375 135.838437 - + - + @@ -10790,12 +10790,12 @@ L 111.34375 135.838437 - + - + @@ -10804,112 +10804,112 @@ L 111.34375 135.838437 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + @@ -11076,7 +11076,7 @@ Q 48.796875 7.703125 50.5 16.40625 z " id="HelveticaNeue-101"/> - + @@ -11087,23 +11087,23 @@ z - - - - @@ -11149,7 +11149,7 @@ Q 39.59375 2.40625 42.09375 6.59375 z " id="HelveticaNeue-Bold-100"/> - + @@ -11157,2483 +11157,2483 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + @@ -13642,162 +13642,162 @@ L 209.74375 135.838437 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -13836,7 +13836,7 @@ Q 17.40625 15.5 17.09375 22.40625 z " id="HelveticaNeue-Bold-101"/> - + @@ -13844,2483 +13844,2483 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - + - + - + - + - + - + - + @@ -16329,162 +16329,162 @@ L 308.14375 135.838437 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -16512,7 +16512,7 @@ L 0 42.203125 z " id="HelveticaNeue-Bold-102"/> - + @@ -16520,2425 +16520,2425 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -18946,12 +18946,12 @@ L 111.34375 243.665 - + - + @@ -18960,56 +18960,56 @@ L 111.34375 243.665 - + - + - + - + - + - + - + - + @@ -19018,12 +19018,12 @@ L 111.34375 243.665 - + - + @@ -19031,12 +19031,12 @@ L 111.34375 243.665 - + - + @@ -19044,12 +19044,12 @@ L 111.34375 243.665 - + - + @@ -19058,12 +19058,12 @@ L 111.34375 243.665 - + - + @@ -19072,134 +19072,134 @@ L 111.34375 243.665 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -19258,7 +19258,7 @@ Q 55.09375 0.203125 55.09375 3.296875 z " id="HelveticaNeue-Bold-103"/> - + @@ -19266,2425 +19266,2425 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + @@ -21692,12 +21692,12 @@ L 209.74375 243.665 - + - + @@ -21706,56 +21706,56 @@ L 209.74375 243.665 - + - + - + - + - + - + - + - + @@ -21777,7 +21777,7 @@ L 2.296875 51.703125 z " id="HelveticaNeue-120"/> - + @@ -21791,162 +21791,162 @@ z - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -21974,7 +21974,7 @@ L 19.59375 71.40625 z " id="HelveticaNeue-Bold-104"/> - + @@ -21982,2425 +21982,2425 @@ z - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + @@ -24408,12 +24408,12 @@ L 308.14375 243.665 - + - + @@ -24422,56 +24422,56 @@ L 308.14375 243.665 - + - + - + - + - + - + - + - + @@ -24480,162 +24480,162 @@ L 308.14375 243.665 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -24653,7 +24653,7 @@ L 20 51.703125 z " id="HelveticaNeue-Bold-105"/> - + @@ -24661,110 +24661,110 @@ z - - - - - - - - - - - - - - - + - + @@ -24772,7 +24772,7 @@ L 105.26375 369.3225 - + @@ -24785,7 +24785,7 @@ L 19.40625 11.09375 z " id="HelveticaNeue-46"/> - + @@ -24795,37 +24795,193 @@ z - + - + - - - - - - - + + + + + + + + + + + + + + + + + + - @@ -24833,101 +24989,101 @@ z - - - - - - - - - - - - - - + - + @@ -24935,12 +25091,12 @@ L 105.26375 369.3225 - + - + @@ -24950,147 +25106,150 @@ L 105.26375 369.3225 - + - + - - - - - - - + + + + + + + + + + - - - - - - - - - - - - - - - - + - + @@ -25098,7 +25257,7 @@ L 302.06375 369.3225 - + @@ -25144,7 +25303,7 @@ Q 4.09375 51.203125 4.40625 45.796875 z " id="HelveticaNeue-50"/> - + @@ -25154,7 +25313,7 @@ z - + @@ -25179,7 +25338,7 @@ L 51.5 24.09375 z " id="HelveticaNeue-52"/> - + @@ -25189,7 +25348,7 @@ z - + @@ -25245,7 +25404,7 @@ Q 25 38.09375 28.59375 38.09375 z " id="HelveticaNeue-54"/> - + @@ -25255,7 +25414,7 @@ z - + @@ -25319,7 +25478,7 @@ Q 13 13.59375 13 20 z " id="HelveticaNeue-56"/> - + @@ -25327,26 +25486,142 @@ z - - - - - - - + + + + + + + + + + + + + + + + + + - @@ -25354,101 +25629,101 @@ z - - - - - - - - - - - - - - + - + @@ -25456,12 +25731,12 @@ L 302.06375 369.3225 - + - + @@ -25471,12 +25746,12 @@ L 302.06375 369.3225 - + - + @@ -25486,12 +25761,12 @@ L 302.06375 369.3225 - + - + @@ -25501,12 +25776,12 @@ L 302.06375 369.3225 - + - + @@ -25514,293 +25789,240 @@ L 302.06375 369.3225 - - - - - - - + + + + + + + + + + + + + - - - - - - - - - - - - - - - + + + + + + + + + + + + - - - + + - - - - + - + - + - + - + - + - + - + - + - + - - - - + - + - + - + - + - + - + - + - + - + - + - + @@ -25823,32 +26045,32 @@ Q 45.5 57.09375 50.90625 62.40625 z " id="HelveticaNeue-55"/> - + - + - + - + - + - + @@ -25900,46 +26122,224 @@ Q 40.90625 50.5 40.90625 47.203125 z " id="HelveticaNeue-57"/> - + - + - + - + - - - - - - - - + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -25947,279 +26347,1078 @@ z - - - - - - - - - - - - - + + + + + + + + + + + + - - - - + + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + - - + + - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + + + + + + + + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -26468,41 +27667,44 @@ z - - + + + + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + - - + + diff --git a/docs/tutorial/tutorial_18_0.svg b/docs/tutorial/tutorial_18_0.svg index f77679bf6..a617c338d 100644 --- a/docs/tutorial/tutorial_18_0.svg +++ b/docs/tutorial/tutorial_18_0.svg @@ -2,7 +2,7 @@ - + - - - - - - - - - - - + + + + - + - - + + - - - - - - - + + + + + + - - + + + + + + - - - - + + + + + + - + - - - + + - - - - - - - - - - - - - - - - + - - + + - +" id="m0c6a95c215" style="stroke:#000000;stroke-width:0.6;"/> - + @@ -3876,20 +4496,20 @@ Q 4.203125 38.703125 4.203125 34.796875 z " id="HelveticaNeue-48"/> - + - - + @@ -3935,7 +4555,7 @@ Q 4.09375 51.203125 4.40625 45.796875 z " id="HelveticaNeue-50"/> - + @@ -3943,13 +4563,13 @@ z - - + @@ -3974,7 +4594,7 @@ L 51.5 24.09375 z " id="HelveticaNeue-52"/> - + @@ -3985,52 +4605,52 @@ z +" id="md93494f3a2" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - + @@ -4190,7 +4810,7 @@ Q 48.796875 7.703125 50.5 16.40625 z " id="HelveticaNeue-101"/> - + @@ -4203,36 +4823,36 @@ z - +" id="m8480a65782" style="stroke:#000000;stroke-width:0.6;"/> - + - + - - + @@ -4251,7 +4871,7 @@ L 27.09375 0 z " id="HelveticaNeue-49"/> - + @@ -4259,18 +4879,18 @@ z - - + - + @@ -4278,13 +4898,13 @@ L 112.495 79.140918 - - + @@ -4342,7 +4962,7 @@ Q 22.296875 40.40625 21.796875 40.5 z " id="HelveticaNeue-51"/> - + @@ -4350,18 +4970,18 @@ z - - + - + @@ -4372,165 +4992,165 @@ L 112.495 40.936837 +" id="m279a7d1b4e" style="stroke:#000000;stroke-width:0.48;"/> - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - @@ -4714,7 +5334,7 @@ L 3.40625 20.59375 z " id="HelveticaNeue-35"/> - + @@ -4731,3860 +5351,4480 @@ z - - - - - - - - - - - - + + + + - + - - + + - - - - - - - + + + + + + - - + + + + + + - - - - + + + + + + - + + - - - + - - - - - - - - - - - - - - - - + - - + + - - + - + - - + - + @@ -8592,18 +9832,18 @@ L 172.299082 23.745 - - + - + @@ -8612,55 +9852,55 @@ L 210.503163 23.745 - + - + - + - + - + - + - + - + @@ -8673,36 +9913,36 @@ L 210.503163 23.745 - - + - + - - + - + @@ -8710,18 +9950,18 @@ L 227.695 98.242959 - - + - + @@ -8729,18 +9969,18 @@ L 227.695 79.140918 - - + - + @@ -8748,18 +9988,18 @@ L 227.695 60.038878 - - + - + @@ -8768,167 +10008,167 @@ L 227.695 40.936837 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - + @@ -8945,119 +10185,119 @@ L 227.695 23.745 - - - - - + - + - - + @@ -9102,7 +10342,7 @@ L 18.40625 62.203125 z " id="HelveticaNeue-53"/> - + @@ -9110,62 +10350,62 @@ z - + - + - + - + - + - + - + - + - + @@ -9178,13 +10418,13 @@ z - - + @@ -9197,7 +10437,7 @@ L 19.40625 11.09375 z " id="HelveticaNeue-46"/> - + @@ -9206,18 +10446,18 @@ z - - + - + @@ -9226,13 +10466,13 @@ L 342.895 80.816159 - - + @@ -9288,7 +10528,7 @@ Q 25 38.09375 28.59375 38.09375 z " id="HelveticaNeue-54"/> - + @@ -9297,13 +10537,13 @@ z - - + @@ -9367,7 +10607,7 @@ Q 13 13.59375 13 20 z " id="HelveticaNeue-56"/> - + @@ -9377,192 +10617,192 @@ z - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - @@ -9610,7 +10850,7 @@ L 14.40625 51.703125 z " id="HelveticaNeue-110"/> - + @@ -9625,120 +10865,120 @@ z - - - - - + - + - - + - + @@ -9746,62 +10986,62 @@ L 416.495 23.745 - + - + - + - + - + - + - + - + - + @@ -9814,18 +11054,18 @@ L 416.495 23.745 - - + - + @@ -9834,18 +11074,18 @@ L 458.095 99.96851 - - + - + @@ -9854,18 +11094,18 @@ L 458.095 80.816159 - - + - + @@ -9874,18 +11114,18 @@ L 458.095 61.663807 - - + - + @@ -9895,197 +11135,197 @@ L 458.095 42.511455 - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - - - - - - - - - + @@ -10100,453 +11340,1070 @@ L 458.095 23.745 - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + - + - + - + - - + + - + - + + + + + + + + + + + + + + + + - + - - + + - + - + + + + + + + + + + + + + + + + - + - - + + - + - + + + + + + + + + + + + + + + + + - + - - + + - + - + + + + + + + + + + + + + + + + + - + - - - - - - - - + + + + + + + + + + + + + + - - - - + + + + + + + + + + + + + + + + + + + + + - - - + + - - + - - - - - - - - - - - - - + + + + - + - + - + - - + + - + - + + + + + + + + + + + + + + + + - + - - + + - + - + + + + + + + + + + + + + + + + - + - - + + + + + + + + + + + + + + + + + + - + - + - + - - + + - + - + + + + + + + + + + + + + + + + + - + - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + - - - + + - - - - - - - - - - - - - - - + - - + + - + @@ -10574,13 +12431,13 @@ z - - + - - + + - + @@ -10633,13 +12490,15 @@ z - - + + - - + + - + @@ -10685,15 +12544,15 @@ z - - + - - + + - + @@ -10702,13 +12561,15 @@ L 391.915 167.12375 - - + + - - + + - + @@ -10737,7 +12598,177 @@ z - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -11244,20 +13275,23 @@ z - - + + + + + - - + + - - + + - - + + - - + + diff --git a/docs/tutorial1.rst b/docs/tutorial1.rst index a0024bd20..5c71e554f 100644 --- a/docs/tutorial1.rst +++ b/docs/tutorial1.rst @@ -287,8 +287,9 @@ Figure colorbars and legends To draw a colorbar or legend along the edge of a figure, use the `~proplot.subplots.Figure.colorbar` or `~proplot.subplots.Figure.legend` ``Figure`` methods. The colorbar or -legend will be aligned between edges of the subplot grid, instead of the -figure bounds. +legend will be aligned between edges of the subplot grid. As with axes +panels, drawing successive colorbars or legends along the same side will +“stack” them. To draw a colorbar or legend beneath particular row(s) and column(s) of the subplot grid, use the ``row``, ``rows``, ``col``, or ``cols`` @@ -303,9 +304,10 @@ rows or columns. f, axs = plot.subplots(ncols=3, nrows=3, axwidth=1.2) m = axs.pcolormesh(np.random.rand(20,20), cmap='grays', levels=np.linspace(0,1,11), extend='both')[0] axs.format(suptitle='Figure colorbars and legends demo', abc=True, abcloc='l', abcformat='a.', xlabel='xlabel', ylabel='ylabel') - f.colorbar(m, label='label', ticks=0.5, loc='b', col=1) - f.colorbar(m, label='label', ticks=0.2, loc='b', cols=(2,3)) - f.colorbar(m, label='label', ticks=0.1, loc='r', length=0.7) + f.colorbar(m, label='column 1', ticks=0.5, loc='b', col=1) + f.colorbar(m, label='columns 2-3', ticks=0.2, loc='b', cols=(2,3)) + f.colorbar(m, label='stacked colorbar', ticks=0.1, loc='b', minorticks=0.05) # this one is stacked + f.colorbar(m, label='colorbar with length <1', ticks=0.1, loc='r', length=0.7) @@ -320,7 +322,7 @@ rows or columns. import proplot as plot import numpy as np - f, axs = plot.subplots(ncols=4, axwidth=1.3, share=0, wspace=0.3) + f, axs = plot.subplots(ncols=2, nrows=2, axwidth=1.3, share=0, wspace=0.3, order='F') data = (np.random.rand(50,50)-0.1).cumsum(axis=0) m = axs[:2].contourf(data, cmap='grays', extend='both') cycle = plot.colors('grays', 5) @@ -328,8 +330,10 @@ rows or columns. for abc,color in zip('ABCDEF',cycle): h = axs[2:].plot(np.random.rand(10), lw=3, color=color, label=f'line {abc}') hs.extend(h[0]) - f.colorbar(m[0], length=0.8, label='label', loc='b', cols=(1,2)) - f.legend(hs, ncols=5, label='label', frame=True, loc='b', cols=(3,4)) + f.colorbar(m[0], length=0.8, label='colorbar label', loc='b', col=1) + f.colorbar(m[0], label='colorbar label', loc='l') + f.legend(hs, ncols=2, center=True, frame=False, loc='b', col=2) + f.legend(hs, ncols=1, label='legend label', frame=False, loc='r') axs.format(suptitle='Figure colorbars and legends demo', abc=True, abcloc='ul', abcformat='A') for ax,title in zip(axs, ['2D dataset #1', '2D dataset #2', 'Line set #1', 'Line set #2']): ax.format(xlabel='xlabel', title=title) diff --git a/proplot/subplots.py b/proplot/subplots.py index 3cad7f4f3..d04d890cf 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -63,7 +63,7 @@ # Dimensions of figures for common journals JOURNAL_SPECS = { - 'pnas1': '8.7cm', # if 1 number specified, this is a tuple + 'pnas1': '8.7cm', 'pnas2': '11.4cm', 'pnas3': '17.8cm', 'ams1': 3.2, # spec is in inches From 8804efc87405b9bac52e8490968dfae091dd48e0 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Mon, 9 Sep 2019 15:24:36 -0600 Subject: [PATCH 26/28] _reassign_title bugfix, minor docs changes --- proplot/axes.py | 62 +++++++++++++++++++++++----------------------- proplot/rctools.py | 4 +-- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/proplot/axes.py b/proplot/axes.py index 7bcac53e1..591f1b4fd 100644 --- a/proplot/axes.py +++ b/proplot/axes.py @@ -64,38 +64,38 @@ # Translator for inset colorbars and legends SIDE_TRANSLATE = { - 'l':'left', - 'r':'right', - 'b':'bottom', - 't':'top', + 'l': 'left', + 'r': 'right', + 'b': 'bottom', + 't': 'top', } LOC_TRANSLATE = { - None:None, - 'l':'left', - 'r':'right', - 'b':'bottom', - 't':'top', - 'c':'center', - 'i':'best', - 'inset':'best', - 0:'best', - 1:'upper right', - 2:'upper left', - 3:'lower left', - 4:'lower right', - 5:'center left', - 6:'center right', - 7:'lower center', - 8:'upper center', - 9:'center', - 'ur':'upper right', - 'ul':'upper left', - 'll':'lower left', - 'lr':'lower right', - 'cr':'center right', - 'cl':'center left', - 'uc':'upper center', - 'lc':'lower center', + None: None, + 'inset': 'best', + 'i': 'best', + 0: 'best', + 1: 'upper right', + 2: 'upper left', + 3: 'lower left', + 4: 'lower right', + 5: 'center left', + 6: 'center right', + 7: 'lower center', + 8: 'upper center', + 9: 'center', + 'l': 'left', + 'r': 'right', + 'b': 'bottom', + 't': 'top', + 'c': 'center', + 'ur': 'upper right', + 'ul': 'upper left', + 'll': 'lower left', + 'lr': 'lower right', + 'cr': 'center right', + 'cl': 'center left', + 'uc': 'upper center', + 'lc': 'lower center', } # Helper function @@ -371,7 +371,7 @@ def _reassign_title(self): # called on the main axes *or* on the top panel itself. This is # critical for bounding box calcs; not always clear whether draw() and # get_tightbbox() are called on the main axes or panel first - if self._panel_side == 'top': + if self._panel_side == 'top' and self._panel_parent: ax, taxs = self._panel_parent, [self] else: ax, taxs = self, self._tpanels diff --git a/proplot/rctools.py b/proplot/rctools.py index 9d2c275b3..f6fd92e07 100644 --- a/proplot/rctools.py +++ b/proplot/rctools.py @@ -40,8 +40,8 @@ ================ ==================================================================================================================================================================================================================== ``nbsetup`` Whether to run `setup` on import. Can only be changed from the ``~/.proplotrc`` file. ``format`` The inline backend figure format, one of ``retina``, ``png``, ``jpeg``, ``pdf``, or ``svg``. Can only be changed from the ``~/.proplotrc`` file. -``autosave`` If non-empty and ``nbsetup`` is ``True``, passed to `%autosave `__. Can only be changed from the ``~/.proplotrc`` file. -``autoreload`` If non-empty and ``nbsetup`` is ``True``, passed to `%autoreload `__. Can only be changed from the ``~/.proplotrc`` file. +``autosave`` If not empty or ``0`` and ``nbsetup`` is ``True``, passed to `%autosave `__. Can only be changed from the ``~/.proplotrc`` file. +``autoreload`` If not empty or ``0`` and ``nbsetup`` is ``True``, passed to `%autoreload `__. Can only be changed from the ``~/.proplotrc`` file. ``abc`` Boolean, indicates whether to draw a-b-c labels by default. ``tight`` Boolean, indicates whether to auto-adjust figure bounds and subplot spacings. ``share`` The axis sharing level, one of ``0``, ``1``, ``2``, or ``3``. From 2b78889ae25050bb23a35517499574fdc79c1d48 Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Mon, 9 Sep 2019 15:42:26 -0600 Subject: [PATCH 27/28] Preliminary add_subplot changes --- proplot/subplots.py | 101 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 84 insertions(+), 17 deletions(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index d04d890cf..5001c0ca2 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -1,10 +1,9 @@ #!/usr/bin/env python3 """ -The starting point for creating custom ProPlot figures and axes. -The `subplots` function is all you'll need to directly use here. -It returns a `Figure` instance and an `axes_grid` container of -`~proplot.axes.Axes` axes, whose positions are controlled by the -`FlexibleGridSpec` class. +The `subplots` function is your starting point for creating custom +ProPlot figures and axes. It returns a `Figure` instance and an +`axes_grid` container of `~proplot.axes.Axes` axes, whose positions are +controlled by the `FlexibleGridSpec` class. .. raw:: html @@ -42,6 +41,7 @@ import matplotlib.figure as mfigure import matplotlib.transforms as mtransforms import matplotlib.gridspec as mgridspec +from types import Integral try: import matplotlib.backends.backend_macosx as mbackend except ImportError: @@ -55,10 +55,10 @@ # Translation SIDE_TRANSLATE = { - 'l':'left', - 'r':'right', - 'b':'bottom', - 't':'top', + 'l': 'left', + 'r': 'right', + 'b': 'bottom', + 't': 'top', } # Dimensions of figures for common journals @@ -78,7 +78,6 @@ 'aaas2': '12cm', # AAAS 2 column } - #-----------------------------------------------------------------------------# # Miscellaneous stuff #-----------------------------------------------------------------------------# @@ -1434,12 +1433,78 @@ def _share_axes_setup(self, ref=None): for child in iaxs: child._sharey_setup(parent, parent._sharey_level) - def add_subplot(self, *args, **kwargs): - """Issues warning for new users that try to call - `~matplotlib.figure.Figure.add_subplot` manually.""" - if self._locked: - warnings.warn('Using "fig.add_subplot()" with ProPlot figures may result in unexpected behavior. Please use "proplot.subplots()" instead.') - ax = super().add_subplot(*args, **kwargs) + def add_subplot(self, *args, + proj=None, projection=None, basemap=False, + **kwargs): + """ + Adds subplot using the existing figure gridspec. + + Parameters + ---------- + *args + If `~matplotlib.gridspec.SubplotSpec` instance, must be a child + of the main subplot gridspec! + + If a 3-digit integer or a tuple indicating (nrows, ncols, index), + the geometry must match the geometry of the input gridspec! + proj, projection : str, optional + The registered matplotlib projection name, or a basemap or cartopy + map projection name. For valid map projection names, see the + :ref:`Table of projections`. + """ + # TODO: Consider permitting add_subplot? + # Copied from matplotlib add_subplot + if not len(args): + args = (1, 1, 1) + if len(args) == 1 and isinstance(args[0], Integral): + if not 100 <= args[0] <= 999: + raise ValueError(f'Integer subplot specification must be a three-digit number, not {args[0]!r}.') + args = tuple(map(int, str(args[0]))) + # Copied from SubplotBase __init__ and modified to enforce restrictions + gridspec = self._gridspec_main + subplotspec = None + if len(args) == 1: + if isinstance(args[0], SubplotSpec): + subplotspec = args[0] + else: + try: + s = str(int(args[0])) + rows, cols, num = map(int, s) + except ValueError: + raise ValueError(f'Single argument to subplot must be a 3-digit integer, not {args[0]!r}.') + elif len(args) == 3: + rows, cols, num = args + else: + raise ValueError(f'Illegal argument(s) to add_subplot: {args}') + if subplotspec is None: + rows = int(rows) + cols = int(cols) + if isinstance(num, tuple) and len(num) == 2: + num = [int(n) for n in num] + else: + if num < 1 or num > rows*cols: + raise ValueError(f'num must be 1 <= num <= {rows*cols}, not {num}') + if (rows, cols) != gridspec.get_active_geometry(): + raise ValueError(f'Input arguments {args!r} conflict with existing gridspec geometry of {rows} rows, {cols} columns.') + if not isinstance(num, tuple): + num = (num, num) + subplotspec = gridspec[(num[0] - 1):num[1]] + + # The default is CartesianAxes + proj = _notNone(proj, projection, 'cartesian', names=('proj','projection')) + # Builtin matplotlib polar axes, just use my overridden version + if name == 'polar': + proj = 'polar2' + # Custom Basemap and Cartopy axes + # TODO: Have Proj return all unused keyword args, with a + # map_projection = obj entry, and maybe hide the Proj constructor as + # an argument processing utility? + elif proj != 'cartesian': + kwargs = projs.Proj(name, basemap=basemap, **kwargs) + proj = 'basemap' if basemap else 'cartopy' + + # Initialize + ax = super().add_subplot(subplotspec, projection=proj, **kwargs) return ax def colorbar(self, *args, @@ -1821,7 +1886,9 @@ def subplots(array=None, ncols=1, nrows=1, for the *x* axis, *y* axis, or both axes. Only has an effect when `spanx`, `spany`, or `span` are ``False``. proj, projection : str or dict-like, optional - The map projection name. The argument is interpreted as follows. + The registered matplotlib projection name, or a basemap or cartopy + map projection name. For valid map projection names, see the + :ref:`Table of projections`. Argument is interpreted as follows. * If string, this projection is used for all subplots. For valid names, see the :ref:`Table of projections`. From 513d3e0e07db8af9550c040d62fb63a9f002e32f Mon Sep 17 00:00:00 2001 From: Luke Davis Date: Sat, 14 Sep 2019 12:45:12 -0600 Subject: [PATCH 28/28] Fix import error --- proplot/subplots.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proplot/subplots.py b/proplot/subplots.py index cf81ace01..16f9e3b28 100644 --- a/proplot/subplots.py +++ b/proplot/subplots.py @@ -73,7 +73,7 @@ import matplotlib.figure as mfigure import matplotlib.transforms as mtransforms import matplotlib.gridspec as mgridspec -from types import Integral +from numbers import Integral try: import matplotlib.backends.backend_macosx as mbackend except ImportError: