From c276f1ed527e9a3bda651240f0e9ad1ac4b0ebb2 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 12 Aug 2026 01:36:31 +0200 Subject: [PATCH 1/8] feat(show): crop kwarg for on-the-fly bounding-box rendering Add show(crop=(xmin, xmax, ymin, ymax)) to restrict a plot to a bounding box in the rendered coordinate system, addressing #764. - points/shapes: cheap per-element predicate subset before drawing (radius-aware for circles); auto-scaled color domain taken from the full element so colors match the uncropped plot. - images: rasterize only the crop window via rasterize()'s target bbox, so the full image is never materialized (fast at Visium HD scale) and the zoom keeps full figure resolution. Placement is correct without a transform rewrite. Contrast auto-scales over the window unless vmin/vmax or a norm is given. - labels: drawn in full and clipped to the box (windowed label rendering needs full-element palette handling; deferred). - exact axis limits (bypass extent-union merge, honor inverted y-axis, ignore pad_extent); validated single-coordinate-system. Unit tests cover the bbox helpers, points/shapes subset, full-element color domain, image window-rasterization, and validation errors. --- src/spatialdata_plot/pl/_validate.py | 11 ++++ src/spatialdata_plot/pl/basic.py | 80 ++++++++++++++++------- src/spatialdata_plot/pl/render.py | 53 +++++++++++++++ src/spatialdata_plot/pl/utils.py | 82 +++++++++++++++++++++--- tests/pl/test_show.py | 96 ++++++++++++++++++++++++++++ tests/pl/test_utils.py | 72 ++++++++++++++++++++- 6 files changed, 362 insertions(+), 32 deletions(-) diff --git a/src/spatialdata_plot/pl/_validate.py b/src/spatialdata_plot/pl/_validate.py index 61e8f639..5e944d9b 100644 --- a/src/spatialdata_plot/pl/_validate.py +++ b/src/spatialdata_plot/pl/_validate.py @@ -97,6 +97,7 @@ def _validate_show_parameters( fig: Figure | None, title: list[str] | str | None, pad_extent: int | float, + crop: tuple[float, float, float, float] | None, ax: list[Axes] | Axes | None, return_ax: bool, save: str | Path | None, @@ -186,6 +187,16 @@ def _validate_show_parameters( if not isinstance(pad_extent, int | float): raise TypeError("Parameter 'pad_extent' must be numeric.") + if crop is not None: + if not isinstance(crop, tuple) or len(crop) != 4 or not all(isinstance(v, int | float) for v in crop): + raise TypeError("Parameter 'crop' must be a tuple of four numbers (xmin, xmax, ymin, ymax).") + xmin, xmax, ymin, ymax = crop + if not (xmin < xmax and ymin < ymax): + raise ValueError( + f"Parameter 'crop' must satisfy xmin < xmax and ymin < ymax, got (xmin={xmin}, xmax={xmax}, " + f"ymin={ymin}, ymax={ymax})." + ) + if ax is not None and not isinstance(ax, Axes | list): raise TypeError("Parameter 'ax' must be a matplotlib.axes.Axes or a list of Axes.") diff --git a/src/spatialdata_plot/pl/basic.py b/src/spatialdata_plot/pl/basic.py index a755ccfc..82b9478b 100644 --- a/src/spatialdata_plot/pl/basic.py +++ b/src/spatialdata_plot/pl/basic.py @@ -1316,6 +1316,7 @@ def show( fig: Figure | None = None, title: list[str] | str | None = None, pad_extent: int | float = 0, + crop: tuple[float, float, float, float] | None = None, ax: list[Axes] | Axes | None = None, return_ax: bool = False, save: str | Path | None = None, @@ -1379,7 +1380,17 @@ def show( of panels. If ``None``, each panel is titled with its coordinate system name, or, in multi-panel color mode, with its color key. pad_extent : int | float, default 0 - Padding added around the computed spatial extent on all sides. + Padding added around the computed spatial extent on all sides. Ignored when ``crop`` is set. + crop : tuple[float, float, float, float] | None, default None + Restrict the plot to a bounding box ``(xmin, xmax, ymin, ymax)`` in the rendered coordinate + system's units (same order as :meth:`matplotlib.axes.Axes.axis`). Points and shapes are + subsetted before drawing for speed; large images are rasterized to the window only, so the + full image is never materialized (fast at Visium HD scale) and the zoom keeps full figure + resolution; labels are drawn in full and clipped to the box. For points and shapes, + auto-scaled color ranges are computed from the full element so colors match the uncropped + plot; a cropped image's contrast auto-scales over the window (pass explicit ``vmin``/``vmax`` + or a ``norm`` to fix it). Requires a single coordinate system (pass ``coordinate_systems`` + with one entry if several would otherwise be rendered). ax : list[Axes] | Axes | None Pre-existing matplotlib axes to plot on. Can be a single :class:`~matplotlib.axes.Axes` or a list matching the number of coordinate systems. If ``None``, a new figure and axes are created. @@ -1441,6 +1452,7 @@ def show( fig=fig, title=title, pad_extent=pad_extent, + crop=crop, ax=ax, return_ax=return_ax, save=save, @@ -1494,6 +1506,19 @@ def show( ax=ax, ) + # `crop` is one box in one coordinate system's units; applying the same numbers across + # coordinate systems with different scales/units would be incoherent. + crop_box: tuple[float, float, float, float] | None = None + if crop is not None: + if len(coordinate_systems) > 1: + raise ValueError( + f"`crop` requires a single coordinate system, but {len(coordinate_systems)} would be " + f"rendered ({coordinate_systems}). Pass `coordinate_systems=` with exactly one entry." + ) + # show()'s `crop` is (xmin, xmax, ymin, ymax); the subset helpers expect (x0, y0, x1, y1). + xmin, xmax, ymin, ymax = crop + crop_box = (xmin, ymin, xmax, ymax) + panels = _plan_panels( coordinate_systems=coordinate_systems, render_cmds=render_cmds, @@ -1567,6 +1592,7 @@ def show( title=title, dpi=dpi, figsize=figsize, + crop=crop_box, ) if has_shapes and wants["shapes"]: @@ -1581,27 +1607,34 @@ def show( "all geometries are empty. Drop the element or restore at least one non-empty geometry." ) - # fast path for axis-aligned transforms; identical result, falls back to get_extent otherwise - extent = _get_extent_fast( - sdata, - coordinate_system=cs, - has_images=has_images and wants["images"], - has_labels=has_labels and wants["labels"], - has_points=has_points and wants["points"], - has_shapes=has_shapes and wants["shapes"], - elements=wanted_elements, - ) - cs_x_min, cs_x_max = extent["x"] - cs_y_min, cs_y_max = extent["y"] - - if any([has_images, has_labels, has_points, has_shapes]): - # If the axis already has limits, only expand them but not overwrite - x_min = min(ax_x_min, cs_x_min) - pad_extent - x_max = max(ax_x_max, cs_x_max) + pad_extent - y_min = min(ax_y_min, cs_y_min) - pad_extent - y_max = max(ax_y_max, cs_y_max) + pad_extent - ax.set_xlim(x_min, x_max) - ax.set_ylim(y_max, y_min) # (0, 0) is top-left + if crop_box is not None: + # `crop` pins the view to the exact box: set limits directly (bypassing the + # expand-don't-overwrite merge, which would expand back out to any pre-existing + # axes limits) and ignore `pad_extent`. crop_box is (x0, y0, x1, y1). + ax.set_xlim(crop_box[0], crop_box[2]) + ax.set_ylim(crop_box[3], crop_box[1]) # (0, 0) is top-left + else: + # fast path for axis-aligned transforms; identical result, falls back to get_extent otherwise + extent = _get_extent_fast( + sdata, + coordinate_system=cs, + has_images=has_images and wants["images"], + has_labels=has_labels and wants["labels"], + has_points=has_points and wants["points"], + has_shapes=has_shapes and wants["shapes"], + elements=wanted_elements, + ) + cs_x_min, cs_x_max = extent["x"] + cs_y_min, cs_y_max = extent["y"] + + if any([has_images, has_labels, has_points, has_shapes]): + # If the axis already has limits, only expand them but not overwrite + x_min = min(ax_x_min, cs_x_min) - pad_extent + x_max = max(ax_x_max, cs_x_max) + pad_extent + y_min = min(ax_y_min, cs_y_min) - pad_extent + y_max = max(ax_y_max, cs_y_max) + pad_extent + ax.set_xlim(x_min, x_max) + ax.set_ylim(y_max, y_min) # (0, 0) is top-left if legend_params_obj.colorbar and axis_colorbar_requests: pending_colorbars.append((ax, axis_colorbar_requests)) @@ -2058,6 +2091,7 @@ def _render_panel( title: list[str] | None, dpi: int | None, figsize: tuple[float, float] | None, + crop: tuple[float, float, float, float] | None = None, ) -> tuple[list[str], dict[str, bool]]: """Render every applicable render command into a single panel's axes. @@ -2115,6 +2149,8 @@ def _render_panel( } if cmd == "render_images": kwargs["channel_legend_entries"] = axis_channel_legend_entries + if cmd in {"render_points", "render_shapes", "render_images"}: + kwargs["crop"] = crop if cmd in {"render_images", "render_labels"}: kwargs["rasterize"] = _should_rasterize( cast("ImageRenderParams | LabelsRenderParams", element_params), dpi, figsize diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index d1242559..f7493057 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -78,6 +78,9 @@ colormap_with_alpha, ) from spatialdata_plot.pl.utils import ( + _bbox_mask_points, + _bbox_mask_shapes, + _bbox_to_element_space, _categorical_legend_handles, _decorate_axs, _fast_extent, @@ -105,6 +108,23 @@ ) +def _pin_norm_to_full_data(color_spec: ColorSpec, cmap_params: CmapParams) -> None: + """Pin ``cmap_params.norm`` vmin/vmax from the full (pre-crop) continuous color vector. + + Cropping happens after color resolution but the norm autoscales later at draw time from the + (cropped) color vector, which would recolor the visible data and shift the colorbar. Pinning the + range here keeps the matplotlib per-element coloring identical to the uncropped plot. No-op for + categorical color or when the user already supplied explicit vmin/vmax. Datashader colors the + per-pixel aggregate, not this vector, so its range still reflects the visible region. + """ + if not color_spec.is_continuous: + return + if cmap_params.norm.vmin is not None and cmap_params.norm.vmax is not None: + return + resolved = _resolve_continuous_norm(color_spec.color_vector, cmap_params) + cmap_params.norm.vmin, cmap_params.norm.vmax = resolved.vmin, resolved.vmax + + def _get_top_data_array(element: xr.DataArray | DataTree) -> xr.DataArray: if isinstance(element, DataTree): return next(iter(next(iter(element.values())).data_vars.values())) @@ -601,6 +621,7 @@ def _render_shapes( fig_params: FigParams, legend_params: LegendParams, colorbar_requests: list[ColorbarSpec] | None = None, + crop: tuple[float, float, float, float] | None = None, ) -> None: _log_context.set("render_shapes") element = render_params.element @@ -700,6 +721,21 @@ def _render_shapes( if outline_color_spec is not None: outline_color_spec = outline_color_spec.filter(keep) + # On-the-fly crop: drop shapes outside the box *after* color resolution, so the (continuous) norm + # and categorical palette stay derived from the full element and colors match the uncropped plot. + if crop is not None: + elem_bbox = _bbox_to_element_space(sdata_filt.shapes[element], coordinate_system, crop) + if elem_bbox is not None: # None = rotation/shear; render full and let axis limits clip + _pin_norm_to_full_data(color_spec, render_params.cmap_params) + keep_crop = _bbox_mask_shapes(shapes, elem_bbox) + color_spec = color_spec.filter(keep_crop) + shapes = shapes[keep_crop].reset_index(drop=True) + if len(shapes) == 0: + return + sdata_filt[element] = shapes + if outline_color_spec is not None: + outline_color_spec = outline_color_spec.filter(keep_crop) + color_spec = color_spec.apply_transfunc(render_params.transfunc) norm = render_params.cmap_params.fresh_norm() @@ -1313,6 +1349,7 @@ def _render_points( fig_params: FigParams, legend_params: LegendParams, colorbar_requests: list[ColorbarSpec] | None = None, + crop: tuple[float, float, float, float] | None = None, ) -> None: _log_context.set("render_points") element = render_params.element @@ -1451,6 +1488,20 @@ def _render_points( points = points[keep].reset_index(drop=True) _reparse_points(sdata_filt, element, points, transformation_in_cs, coordinate_system, col_for_color) + # On-the-fly crop: drop points outside the box *after* color resolution so the (continuous) norm + # and categorical palette stay derived from the full element and colors match the uncropped plot. + if crop is not None: + elem_bbox = _bbox_to_element_space(sdata.points[element], coordinate_system, crop) + if elem_bbox is not None: # None = rotation/shear; render full and let axis limits clip + _pin_norm_to_full_data(color_spec, render_params.cmap_params) + keep_crop = _bbox_mask_points(points["x"].to_numpy(), points["y"].to_numpy(), elem_bbox) + if not keep_crop.any(): + return + color_spec = color_spec.filter(keep_crop) + points = points[keep_crop].reset_index(drop=True) + n_points = len(points) # method auto-threshold below should see the drawn count + _reparse_points(sdata_filt, element, points, transformation_in_cs, coordinate_system, col_for_color) + color_spec = color_spec.apply_transfunc(render_params.transfunc) trans, trans_data = _prepare_transformation(sdata.points[element], coordinate_system, ax) @@ -1735,6 +1786,7 @@ def _render_images( rasterize: bool, colorbar_requests: list[ColorbarSpec] | None = None, channel_legend_entries: list[ChannelLegendEntry] | None = None, + crop: tuple[float, float, float, float] | None = None, ) -> None: _log_context.set("render_images") sdata_filt = sdata.filter_by_coordinate_system( @@ -1783,6 +1835,7 @@ def _render_images( height=fig_params.fig.get_size_inches()[1], coordinate_system=coordinate_system, extent=extent, + crop=crop, ) channels = img.coords["c"].values.tolist() if render_params.channel is None else render_params.channel diff --git a/src/spatialdata_plot/pl/utils.py b/src/spatialdata_plot/pl/utils.py index 3afff5f4..441cdb47 100644 --- a/src/spatialdata_plot/pl/utils.py +++ b/src/spatialdata_plot/pl/utils.py @@ -812,6 +812,7 @@ def _rasterize_if_necessary( height: float, coordinate_system: str, extent: dict[str, tuple[float, float]], + crop: tuple[float, float, float, float] | None = None, ) -> DataArray: """Ensure fast rendering by adapting the resolution if necessary. @@ -849,24 +850,34 @@ def _rasterize_if_necessary( target_y_dims = dpi * height target_x_dims = dpi * width - # Rasterize when the source image is substantially larger than what the - # current figure DPI × size requires. The +100 margin avoids rasterizing - # when the image is only slightly larger than the target. - do_rasterization = y_dims > target_y_dims + 100 or x_dims > target_x_dims + 100 + if crop is not None: + # Restrict rasterization to the crop window. ``rasterize`` maps the target bbox + # through the element transform internally, so the window is placed correctly + # without a transform rewrite, only its source pixels are read (cost bounded by + # the window, not the full image), and the zoom keeps full figure resolution. + # ``crop`` is (x0, y0, x1, y1) in coordinate-system units. + raster_extent = {"x": (crop[0], crop[2]), "y": (crop[1], crop[3])} + do_rasterization = True + else: + raster_extent = extent + # Rasterize when the source image is substantially larger than what the + # current figure DPI × size requires. The +100 margin avoids rasterizing + # when the image is only slightly larger than the target. + do_rasterization = y_dims > target_y_dims + 100 or x_dims > target_x_dims + 100 if do_rasterization: logger.info("Rasterizing image for faster rendering.") # ``rasterize`` interprets ``target_unit_to_pixels`` in world units, not # intrinsic pixels. Dividing by world extent keeps the result correct # for any transformation (translation, scale, etc.). - world_x = float(extent["x"][1]) - float(extent["x"][0]) - world_y = float(extent["y"][1]) - float(extent["y"][0]) + world_x = float(raster_extent["x"][1]) - float(raster_extent["x"][0]) + world_y = float(raster_extent["y"][1]) - float(raster_extent["y"][0]) target_unit_to_pixels = min(target_y_dims / world_y, target_x_dims / world_x) image = rasterize( image, ("y", "x"), - [extent["y"][0], extent["x"][0]], - [extent["y"][1], extent["x"][1]], + [raster_extent["y"][0], raster_extent["x"][0]], + [raster_extent["y"][1], raster_extent["x"][1]], coordinate_system, target_unit_to_pixels=target_unit_to_pixels, ) @@ -1459,6 +1470,61 @@ def _element_extent_fast( return {"x": (float(tc[:, 0].min()), float(tc[:, 0].max())), "y": (float(tc[:, 1].min()), float(tc[:, 1].max()))} +# --- Fast bbox subset for on-the-fly cropping (points/shapes only) --------------------------------- +# Drop rows/geometries outside a coordinate-system bbox before the expensive draw, without rebuilding +# a SpatialData object or re-joining tables (which is what makes spatialdata.bounding_box_query slow). +# Images/labels are not subset here: slicing a DataArray does not update what get_extent/imshow read, +# so a sliced image is drawn in the wrong place; they rely on axis-limit clipping instead. + + +def _bbox_to_element_space( + element: Any, coordinate_system: str, bbox: tuple[float, float, float, float] +) -> tuple[float, float, float, float] | None: + """Map a coordinate-system bbox ``(x0, y0, x1, y1)`` to element-native coords. + + Inverts the axis-aligned affine on the box corners and re-sorts so the result has ``x0 <= x1`` and + ``y0 <= y1`` even when the transform flips an axis (a negative scale would otherwise yield a + reversed box that silently empties ``.cx``/``.sel``). Returns ``None`` for rotation/shear, where a + box does not map to a box; the caller then skips the fast subset. + """ + matrix = get_transformation(element, get_all=True)[coordinate_system].to_affine_matrix(("x", "y"), ("x", "y")) + affine = matrix[:2, :2] + if not _is_axis_aligned(affine): + return None + x0, y0, x1, y1 = bbox + corners = np.array([[x0, y0], [x1, y0], [x0, y1], [x1, y1]], dtype=float) + elem = (corners - matrix[:2, 2]) @ np.linalg.inv(affine).T + return (float(elem[:, 0].min()), float(elem[:, 1].min()), float(elem[:, 0].max()), float(elem[:, 1].max())) + + +def _bbox_mask_points(x: ArrayLike, y: ArrayLike, elem_bbox: tuple[float, float, float, float]) -> ArrayLike: + """Boolean keep-mask for points whose element-native ``(x, y)`` fall inside ``elem_bbox``.""" + x0, y0, x1, y1 = elem_bbox + x, y = np.asarray(x), np.asarray(y) + return (x >= x0) & (x <= x1) & (y >= y0) & (y <= y1) + + +def _bbox_mask_shapes(shapes: GeoDataFrame, elem_bbox: tuple[float, float, float, float]) -> ArrayLike: + """Boolean keep-mask for shapes whose bounds intersect ``elem_bbox`` (element-native coords). + + Bbox-intersect, not clip: a boundary-crossing shape is kept whole (axis-limit clipping trims it + visually). Circles are stored as ``Point`` + ``radius``, so their bounds are the centre expanded by + the radius; a centroid-only test would drop circles whose body overlaps the box. Polygons use the + geometry's own bounds. This is the masking form of geopandas ``.cx`` (which returns a frame, not a + mask we can align to ``color_spec``). + """ + x0, y0, x1, y1 = elem_bbox + geom = shapes.geometry + if (geom.geom_type == "Point").all(): # circles: Point + radius column + cx, cy = geom.x.to_numpy(), geom.y.to_numpy() + r = np.asarray(shapes[ShapesModel.RADIUS_KEY], dtype=float) + minx, miny, maxx, maxy = cx - r, cy - r, cx + r, cy + r + else: # polygons / multipolygons (also valid for plain points: degenerate bounds) + b = geom.bounds # C-level; columns minx, miny, maxx, maxy + minx, miny, maxx, maxy = (b[c].to_numpy() for c in ("minx", "miny", "maxx", "maxy")) + return (maxx >= x0) & (minx <= x1) & (maxy >= y0) & (miny <= y1) + + def _fast_extent(element: Any, coordinate_system: str) -> dict[str, tuple[float, float]]: """Element extent via the fast corner-transform. diff --git a/tests/pl/test_show.py b/tests/pl/test_show.py index 455c8661..76176b2f 100644 --- a/tests/pl/test_show.py +++ b/tests/pl/test_show.py @@ -3,10 +3,13 @@ import matplotlib import matplotlib.pyplot as plt +import numpy as np +import pandas as pd import pytest import scanpy as sc from matplotlib.figure import Figure from spatialdata import SpatialData +from spatialdata.models import PointsModel from spatialdata.transformations import Identity, set_transformation import spatialdata_plot # noqa: F401 @@ -138,6 +141,99 @@ def test_title_empty_string_suppresses_title(self, sdata_blobs: SpatialData): plt.close("all") +def test_crop_sets_exact_axis_limits(sdata_blobs: SpatialData): + """crop=(xmin, xmax, ymin, ymax) pins the view to the box; y is inverted (top-left origin).""" + ax = sdata_blobs.pl.render_points().pl.show(crop=(100, 300, 120, 260), return_ax=True, show=False) + assert ax.get_xlim() == pytest.approx((100, 300)) + assert ax.get_ylim() == pytest.approx((260, 120)) # set_ylim(ymax, ymin) + plt.close("all") + + +def test_crop_ignores_pad_extent(sdata_blobs: SpatialData): + """pad_extent must not widen a crop box (the view is exactly the box).""" + ax = sdata_blobs.pl.render_points().pl.show(crop=(100, 300, 120, 260), pad_extent=50, return_ax=True, show=False) + assert ax.get_xlim() == pytest.approx((100, 300)) + assert ax.get_ylim() == pytest.approx((260, 120)) + plt.close("all") + + +def test_crop_reduces_points_drawn(sdata_blobs: SpatialData): + """The fast subset draws fewer points than the full render.""" + + def n_offsets(ax): + return sum(len(c.get_offsets()) for c in ax.collections if hasattr(c, "get_offsets")) + + full = sdata_blobs.pl.render_points().pl.show(return_ax=True, show=False) + cropped = sdata_blobs.pl.render_points().pl.show(crop=(100, 300, 120, 260), return_ax=True, show=False) + assert 0 < n_offsets(cropped) < n_offsets(full) + plt.close("all") + + +def test_crop_continuous_color_domain_from_full_element(): + """Auto-scaled color range must come from the full element, so cropped colors match uncropped.""" + rng = np.random.default_rng(0) + df = pd.DataFrame({"x": rng.uniform(0, 100, 2000), "y": rng.uniform(0, 100, 2000), "val": rng.uniform(0, 1, 2000)}) + df.loc[0, ["x", "y", "val"]] = [90, 90, 10.0] # an extreme value far outside the crop box + sdata = SpatialData(points={"p": PointsModel.parse(df, transformations={"global": Identity()})}) + + def vrange(ax): + for c in ax.collections: + if getattr(c, "norm", None) is not None and c.norm.vmax is not None: + return (c.norm.vmin, c.norm.vmax) + return None + + full = sdata.pl.render_points("p", color="val").pl.show(return_ax=True, show=False) + cropped = sdata.pl.render_points("p", color="val").pl.show(crop=(20, 50, 30, 60), return_ax=True, show=False) + assert vrange(cropped) == pytest.approx(vrange(full)) + plt.close("all") + + +def test_crop_image_rasterizes_only_window(): + """A cropped large image is rasterized to the window at figure resolution, not the full image then clipped. + + Regression for #764: rasterize() maps the crop bbox through the element transform, so placement is + correct even under a Scale+Translation (which a naive .sel would mis-place) and only the window is read. + """ + from spatialdata.models import Image2DModel + from spatialdata.transformations import Scale, Sequence, Translation + + n = 3000 + rng = np.random.default_rng(0) + transform = Sequence([Scale([2.0, 2.0], axes=("x", "y")), Translation([1000.0, 500.0], axes=("x", "y"))]) + img = Image2DModel.parse( + rng.random((1, n, n), dtype=np.float32), dims=("c", "y", "x"), transformations={"global": transform} + ) + sdata = SpatialData(images={"img": img}) + # full world extent x=(1000, 7000), y=(500, 6500); crop a small central window + ax = sdata.pl.render_images("img").pl.show(crop=(3500, 3900, 3500, 3900), return_ax=True, show=False) + + assert ax.get_xlim() == pytest.approx((3500, 3900)) + assert ax.get_ylim() == pytest.approx((3900, 3500)) # inverted y + # the rendered raster covers the window at ~figure resolution, not the 3000-px source + (im,) = ax.get_images() + assert max(im.get_array().shape[:2]) < n // 2 + plt.close("all") + + +def test_crop_invalid_order_raises(sdata_blobs: SpatialData): + with pytest.raises(ValueError, match="xmin < xmax and ymin < ymax"): + sdata_blobs.pl.render_points().pl.show(crop=(300, 100, 120, 260), show=False) + + +def test_crop_wrong_length_raises(sdata_blobs: SpatialData): + with pytest.raises(TypeError, match="tuple of four numbers"): + sdata_blobs.pl.render_points().pl.show(crop=(100, 300, 120), show=False) + + +def test_crop_multiple_coordinate_systems_raises(sdata_blobs: SpatialData): + """crop is one box in one CS's units; rendering several CS at once is rejected.""" + set_transformation(sdata_blobs["blobs_points"], Identity(), to_coordinate_system="other") + with pytest.raises(ValueError, match="single coordinate system"): + sdata_blobs.pl.render_points().pl.show( + coordinate_systems=["global", "other"], crop=(100, 300, 120, 260), show=False + ) + + def test_fig_parameter_emits_deprecation_warning(sdata_blobs: SpatialData): """Passing fig= should emit a DeprecationWarning (regression for #204).""" fig = Figure() diff --git a/tests/pl/test_utils.py b/tests/pl/test_utils.py index fac573a5..e732ada7 100644 --- a/tests/pl/test_utils.py +++ b/tests/pl/test_utils.py @@ -7,9 +7,10 @@ import scanpy as sc import xarray as xr from anndata import AnnData -from shapely.geometry import Point +from shapely.geometry import Point, Polygon from spatialdata import SpatialData, get_centroids from spatialdata.models import Labels2DModel, PointsModel, ShapesModel, TableModel +from spatialdata.transformations import Affine, Identity, Scale, Sequence, Translation import spatialdata_plot from spatialdata_plot.pl import measure_obs @@ -19,7 +20,12 @@ _datashader_map_aggregate_to_color, ) from spatialdata_plot.pl.render_params import CmapParams, Color, ColorLike, colormap_with_alpha -from spatialdata_plot.pl.utils import set_zero_in_cmap_to_transparent +from spatialdata_plot.pl.utils import ( + _bbox_mask_points, + _bbox_mask_shapes, + _bbox_to_element_space, + set_zero_in_cmap_to_transparent, +) from tests.conftest import DPI, PlotTester, PlotTesterMeta sc.pl.set_rcParams_defaults() @@ -1355,3 +1361,65 @@ def test_datashader_points_image_aligns_with_points_extent(): assert (min(x0, x1), max(x0, x1)) == pytest.approx((0.1, 0.9)) assert (min(y0, y1), max(y0, y1)) == pytest.approx((0.1, 0.9)) plt.close("all") + + +# --- bbox-subset helpers (on-the-fly crop) -------------------------------------------------------- + + +def _points(x, y): + return PointsModel.parse(pd.DataFrame({"x": x, "y": y}), transformations={"g": Identity()}) + + +def test_bbox_to_element_space_identity_round_trips(): + pts = _points([0.0, 1.0], [0.0, 1.0]) + assert _bbox_to_element_space(pts, "g", (2.0, 3.0, 8.0, 9.0)) == pytest.approx((2.0, 3.0, 8.0, 9.0)) + + +def test_bbox_to_element_space_inverts_scale_and_translation(): + t = Sequence([Scale([2, 2], axes=("x", "y")), Translation([100, 50], axes=("x", "y"))]) + pts = PointsModel.parse(pd.DataFrame({"x": [0.0], "y": [0.0]}), transformations={"g": t}) + # cs box x[110,126] y[110,116] -> element x[5,13] y[30,33] + assert _bbox_to_element_space(pts, "g", (110.0, 110.0, 126.0, 116.0)) == pytest.approx((5.0, 30.0, 13.0, 33.0)) + + +def test_bbox_to_element_space_resorts_under_axis_flip(): + # a negative x-scale flips the axis; the element box must keep x0 < x1 so .sel/mask don't empty + flip = Scale([-1, 1], axes=("x", "y")) + pts = PointsModel.parse(pd.DataFrame({"x": [0.0], "y": [0.0]}), transformations={"g": flip}) + x0, y0, x1, y1 = _bbox_to_element_space(pts, "g", (2.0, 1.0, 6.0, 3.0)) + assert x0 < x1 and y0 < y1 + + +def test_bbox_to_element_space_none_for_rotation(): + theta = 0.3 + rot = Affine( + [[np.cos(theta), -np.sin(theta), 0], [np.sin(theta), np.cos(theta), 0], [0, 0, 1]], + input_axes=("x", "y"), + output_axes=("x", "y"), + ) + pts = PointsModel.parse(pd.DataFrame({"x": [0.0], "y": [0.0]}), transformations={"g": rot}) + assert _bbox_to_element_space(pts, "g", (0.0, 0.0, 1.0, 1.0)) is None + + +def test_bbox_mask_points_matches_numpy_predicate(): + x = np.array([1.0, 5.0, 9.0, 15.0]) + y = np.array([1.0, 5.0, 9.0, 15.0]) + mask = _bbox_mask_points(x, y, (2.0, 2.0, 8.0, 8.0)) + np.testing.assert_array_equal(mask, [False, True, False, False]) + + +def test_bbox_mask_shapes_keeps_circle_near_edge(): + # circle centred at (0,0) r=3: centroid outside box (1..2) but body overlaps -> must be kept + circ = ShapesModel.parse( + gpd.GeoDataFrame({"geometry": [Point(0, 0)], "radius": [3.0]}), transformations={"g": Identity()} + ) + assert _bbox_mask_shapes(circ, (1.0, 1.0, 2.0, 2.0)).tolist() == [True] + # a centroid-only test (geopandas .cx) would have dropped it + assert len(circ.cx[1:2, 1:2]) == 0 + + +def test_bbox_mask_shapes_polygon_intersect_and_empty(): + polys = [Polygon([(0, 0), (10, 0), (10, 10), (0, 10)]), Polygon([(100, 100), (110, 100), (110, 110), (100, 110)])] + gdf = ShapesModel.parse(gpd.GeoDataFrame({"geometry": polys}), transformations={"g": Identity()}) + np.testing.assert_array_equal(_bbox_mask_shapes(gdf, (1.0, 1.0, 5.0, 5.0)), [True, False]) + np.testing.assert_array_equal(_bbox_mask_shapes(gdf, (200.0, 200.0, 210.0, 210.0)), [False, False]) From 5b66f8db286a1a8822eb4ea1a4628be153d22df9 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 12 Aug 2026 15:22:09 +0200 Subject: [PATCH 2/8] =?UTF-8?q?fix(show):=20address=20crop=20review=20?= =?UTF-8?q?=E2=80=94=20rename=20to=20crop=5Fcoord,=20correctness=20fixes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Follow-up to the max code review of the crop feature. - Rename public kwarg crop -> crop_coord to match scanpy sc.pl.spatial / squidpy sq.pl.spatial_scatter (interop > novelty); 4-tuple unchanged. - Norm handling is now non-mutating: capture the full-element range and apply it only on the matplotlib backend. Fixes the datashader leak (it now autoscales over the window, correct for sum/count) and the pre-transfunc pin (range is taken over the transfunc'd full vector). - _bbox_mask_shapes is radius-aware per row, so a frame mixing circles and polygons no longer drops edge circles. - Multiscale images pick the pyramid level for the crop WINDOW's required resolution, not the full image, so a Visium-HD crop no longer upsamples a coarse level. - Document that labels and method='datashader' images are clip-only under crop (windowed labels need full-element palette handling; deferred). - Simplify the crop axis-limit block to read crop_coord directly. Tests: transfunc-matches-uncropped, datashader-autoscales-over-window, multiscale-selects-finer-level, mixed circle+polygon mask. --- src/spatialdata_plot/pl/_validate.py | 16 +++--- src/spatialdata_plot/pl/basic.py | 46 ++++++++-------- src/spatialdata_plot/pl/render.py | 59 ++++++++++++-------- src/spatialdata_plot/pl/utils.py | 38 +++++++++---- tests/pl/test_show.py | 81 ++++++++++++++++++++++++---- tests/pl/test_utils.py | 10 ++++ 6 files changed, 180 insertions(+), 70 deletions(-) diff --git a/src/spatialdata_plot/pl/_validate.py b/src/spatialdata_plot/pl/_validate.py index 5e944d9b..b8c16d00 100644 --- a/src/spatialdata_plot/pl/_validate.py +++ b/src/spatialdata_plot/pl/_validate.py @@ -97,7 +97,7 @@ def _validate_show_parameters( fig: Figure | None, title: list[str] | str | None, pad_extent: int | float, - crop: tuple[float, float, float, float] | None, + crop_coord: tuple[float, float, float, float] | None, ax: list[Axes] | Axes | None, return_ax: bool, save: str | Path | None, @@ -187,13 +187,17 @@ def _validate_show_parameters( if not isinstance(pad_extent, int | float): raise TypeError("Parameter 'pad_extent' must be numeric.") - if crop is not None: - if not isinstance(crop, tuple) or len(crop) != 4 or not all(isinstance(v, int | float) for v in crop): - raise TypeError("Parameter 'crop' must be a tuple of four numbers (xmin, xmax, ymin, ymax).") - xmin, xmax, ymin, ymax = crop + if crop_coord is not None: + if ( + not isinstance(crop_coord, tuple) + or len(crop_coord) != 4 + or not all(isinstance(v, int | float) for v in crop_coord) + ): + raise TypeError("Parameter 'crop_coord' must be a tuple of four numbers (xmin, xmax, ymin, ymax).") + xmin, xmax, ymin, ymax = crop_coord if not (xmin < xmax and ymin < ymax): raise ValueError( - f"Parameter 'crop' must satisfy xmin < xmax and ymin < ymax, got (xmin={xmin}, xmax={xmax}, " + f"Parameter 'crop_coord' must satisfy xmin < xmax and ymin < ymax, got (xmin={xmin}, xmax={xmax}, " f"ymin={ymin}, ymax={ymax})." ) diff --git a/src/spatialdata_plot/pl/basic.py b/src/spatialdata_plot/pl/basic.py index 82b9478b..8b04e985 100644 --- a/src/spatialdata_plot/pl/basic.py +++ b/src/spatialdata_plot/pl/basic.py @@ -1316,7 +1316,7 @@ def show( fig: Figure | None = None, title: list[str] | str | None = None, pad_extent: int | float = 0, - crop: tuple[float, float, float, float] | None = None, + crop_coord: tuple[float, float, float, float] | None = None, ax: list[Axes] | Axes | None = None, return_ax: bool = False, save: str | Path | None = None, @@ -1380,17 +1380,19 @@ def show( of panels. If ``None``, each panel is titled with its coordinate system name, or, in multi-panel color mode, with its color key. pad_extent : int | float, default 0 - Padding added around the computed spatial extent on all sides. Ignored when ``crop`` is set. - crop : tuple[float, float, float, float] | None, default None + Padding added around the computed spatial extent on all sides. Ignored when ``crop_coord`` is set. + crop_coord : tuple[float, float, float, float] | None, default None Restrict the plot to a bounding box ``(xmin, xmax, ymin, ymax)`` in the rendered coordinate - system's units (same order as :meth:`matplotlib.axes.Axes.axis`). Points and shapes are - subsetted before drawing for speed; large images are rasterized to the window only, so the - full image is never materialized (fast at Visium HD scale) and the zoom keeps full figure - resolution; labels are drawn in full and clipped to the box. For points and shapes, - auto-scaled color ranges are computed from the full element so colors match the uncropped - plot; a cropped image's contrast auto-scales over the window (pass explicit ``vmin``/``vmax`` - or a ``norm`` to fix it). Requires a single coordinate system (pass ``coordinate_systems`` - with one entry if several would otherwise be rendered). + system's units (same order as :meth:`matplotlib.axes.Axes.axis` and as ``crop_coord`` in + :func:`scanpy.pl.spatial` / :func:`squidpy.pl.spatial_scatter`). Points and shapes are + subsetted before drawing for speed; large images on the default matplotlib backend are + rasterized to the window only, so the full image is never materialized (fast at Visium HD + scale) and the zoom keeps full figure resolution; labels, and ``method='datashader'`` images, + are drawn in full and clipped to the box. For points and shapes, auto-scaled color ranges are + computed from the full element so colors match the uncropped plot; a cropped image's contrast + auto-scales over the window (pass explicit ``vmin``/``vmax`` or a ``norm`` to fix it). + Requires a single coordinate system (pass ``coordinate_systems`` with one entry if several + would otherwise be rendered). ax : list[Axes] | Axes | None Pre-existing matplotlib axes to plot on. Can be a single :class:`~matplotlib.axes.Axes` or a list matching the number of coordinate systems. If ``None``, a new figure and axes are created. @@ -1452,7 +1454,7 @@ def show( fig=fig, title=title, pad_extent=pad_extent, - crop=crop, + crop_coord=crop_coord, ax=ax, return_ax=return_ax, save=save, @@ -1506,17 +1508,17 @@ def show( ax=ax, ) - # `crop` is one box in one coordinate system's units; applying the same numbers across + # `crop_coord` is one box in one coordinate system's units; applying the same numbers across # coordinate systems with different scales/units would be incoherent. crop_box: tuple[float, float, float, float] | None = None - if crop is not None: + if crop_coord is not None: if len(coordinate_systems) > 1: raise ValueError( - f"`crop` requires a single coordinate system, but {len(coordinate_systems)} would be " + f"`crop_coord` requires a single coordinate system, but {len(coordinate_systems)} would be " f"rendered ({coordinate_systems}). Pass `coordinate_systems=` with exactly one entry." ) - # show()'s `crop` is (xmin, xmax, ymin, ymax); the subset helpers expect (x0, y0, x1, y1). - xmin, xmax, ymin, ymax = crop + # show()'s `crop_coord` is (xmin, xmax, ymin, ymax); the subset helpers expect (x0, y0, x1, y1). + xmin, xmax, ymin, ymax = crop_coord crop_box = (xmin, ymin, xmax, ymax) panels = _plan_panels( @@ -1607,12 +1609,12 @@ def show( "all geometries are empty. Drop the element or restore at least one non-empty geometry." ) - if crop_box is not None: - # `crop` pins the view to the exact box: set limits directly (bypassing the + if crop_coord is not None: + # `crop_coord` pins the view to the exact box: set limits directly (bypassing the # expand-don't-overwrite merge, which would expand back out to any pre-existing - # axes limits) and ignore `pad_extent`. crop_box is (x0, y0, x1, y1). - ax.set_xlim(crop_box[0], crop_box[2]) - ax.set_ylim(crop_box[3], crop_box[1]) # (0, 0) is top-left + # axes limits) and ignore `pad_extent`. crop_coord is (xmin, xmax, ymin, ymax). + ax.set_xlim(crop_coord[0], crop_coord[1]) + ax.set_ylim(crop_coord[3], crop_coord[2]) # (0, 0) is top-left else: # fast path for axis-aligned transforms; identical result, falls back to get_extent otherwise extent = _get_extent_fast( diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index f7493057..eed3ff7e 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -2,7 +2,7 @@ import dataclasses from collections import abc -from collections.abc import Sequence +from collections.abc import Callable, Sequence from copy import copy from typing import Any, Literal, cast @@ -108,21 +108,24 @@ ) -def _pin_norm_to_full_data(color_spec: ColorSpec, cmap_params: CmapParams) -> None: - """Pin ``cmap_params.norm`` vmin/vmax from the full (pre-crop) continuous color vector. +def _full_element_norm_range( + color_spec: ColorSpec, cmap_params: CmapParams, transfunc: Callable[..., Any] | None +) -> tuple[float, float] | None: + """``(vmin, vmax)`` over the full (pre-crop) continuous color vector, after ``transfunc``. - Cropping happens after color resolution but the norm autoscales later at draw time from the - (cropped) color vector, which would recolor the visible data and shift the colorbar. Pinning the - range here keeps the matplotlib per-element coloring identical to the uncropped plot. No-op for - categorical color or when the user already supplied explicit vmin/vmax. Datashader colors the - per-pixel aggregate, not this vector, so its range still reflects the visible region. + A crop drops rows before drawing, but the matplotlib backend must keep the uncropped colour range + so the zoom matches the full plot. Returns the range resolved over the full element's transfunc'd + values (what the uncropped plot autoscales to), or ``None`` for categorical color or when the user + already fixed vmin/vmax. Non-mutating and applied only on the matplotlib path: the datashader and + image backends never receive it and autoscale over the visible window instead. """ if not color_spec.is_continuous: - return + return None if cmap_params.norm.vmin is not None and cmap_params.norm.vmax is not None: - return - resolved = _resolve_continuous_norm(color_spec.color_vector, cmap_params) - cmap_params.norm.vmin, cmap_params.norm.vmax = resolved.vmin, resolved.vmax + return (cmap_params.norm.vmin, cmap_params.norm.vmax) + vec = color_spec.apply_transfunc(transfunc).color_vector if transfunc is not None else color_spec.color_vector + resolved = _resolve_continuous_norm(vec, cmap_params) + return (float(resolved.vmin), float(resolved.vmax)) def _get_top_data_array(element: xr.DataArray | DataTree) -> xr.DataArray: @@ -721,12 +724,13 @@ def _render_shapes( if outline_color_spec is not None: outline_color_spec = outline_color_spec.filter(keep) - # On-the-fly crop: drop shapes outside the box *after* color resolution, so the (continuous) norm - # and categorical palette stay derived from the full element and colors match the uncropped plot. + # On-the-fly crop: drop shapes outside the box. Capture the full-element colour range first so the + # matplotlib backend keeps the uncropped norm (datashader autoscales over the window instead). + crop_norm_range: tuple[float, float] | None = None if crop is not None: elem_bbox = _bbox_to_element_space(sdata_filt.shapes[element], coordinate_system, crop) if elem_bbox is not None: # None = rotation/shear; render full and let axis limits clip - _pin_norm_to_full_data(color_spec, render_params.cmap_params) + crop_norm_range = _full_element_norm_range(color_spec, render_params.cmap_params, render_params.transfunc) keep_crop = _bbox_mask_shapes(shapes, elem_bbox) color_spec = color_spec.filter(keep_crop) shapes = shapes[keep_crop].reset_index(drop=True) @@ -953,6 +957,10 @@ def _draw_centroids(xy: np.ndarray, radius: float | None = None) -> None: cax = _build_ds_colorbar(reduction_bounds, norm, render_params.cmap_params.cmap) elif method == "matplotlib": + # Under crop, pin the norm to the full-element range so the zoom matches the uncropped plot + # (datashader, handled above, autoscales over the window instead). + if crop_norm_range is not None: + norm.vmin, norm.vmax = crop_norm_range # Build the paths once and share them across the fill and outline collections (geometry is # identical; only colours/alpha/linewidth differ), then apply the coordinate-system affine # once to the shared Path objects rather than once per collection. @@ -1488,12 +1496,13 @@ def _render_points( points = points[keep].reset_index(drop=True) _reparse_points(sdata_filt, element, points, transformation_in_cs, coordinate_system, col_for_color) - # On-the-fly crop: drop points outside the box *after* color resolution so the (continuous) norm - # and categorical palette stay derived from the full element and colors match the uncropped plot. + # On-the-fly crop: drop points outside the box. Capture the full-element colour range first so the + # matplotlib backend keeps the uncropped norm (datashader autoscales over the window instead). + crop_norm_range: tuple[float, float] | None = None if crop is not None: elem_bbox = _bbox_to_element_space(sdata.points[element], coordinate_system, crop) if elem_bbox is not None: # None = rotation/shear; render full and let axis limits clip - _pin_norm_to_full_data(color_spec, render_params.cmap_params) + crop_norm_range = _full_element_norm_range(color_spec, render_params.cmap_params, render_params.transfunc) keep_crop = _bbox_mask_points(points["x"].to_numpy(), points["y"].to_numpy(), elem_bbox) if not keep_crop.any(): return @@ -1560,11 +1569,13 @@ def _render_points( elif method == "matplotlib": # matplotlib colors each point by its own value, so resolve the norm to match shapes/labels # instead of letting ax.scatter autoscale a fresh one. Non-continuous keeps the fresh norm. - norm = ( - _resolve_continuous_norm(color_spec.color_vector, render_params.cmap_params) - if color_spec.is_continuous - else render_params.cmap_params.fresh_norm() - ) + # Under crop, pin to the full-element range so the zoom matches the uncropped plot. + if color_spec.is_continuous: + norm = _resolve_continuous_norm(color_spec.color_vector, render_params.cmap_params) + if crop_norm_range is not None: + norm.vmin, norm.vmax = crop_norm_range + else: + norm = render_params.cmap_params.fresh_norm() # update axis limits if plot was empty before (necessary if datashader comes after) update_parameters = not _mpl_ax_contains_elements(ax) cax = _scatter_points( @@ -1808,6 +1819,8 @@ def _render_images( width=fig_params.fig.get_size_inches()[0], height=fig_params.fig.get_size_inches()[1], scale=scale, + crop=crop, + extent=extent, ) # rasterize spatial image if necessary to speed up performance use_datashader = render_params.method == "datashader" diff --git a/src/spatialdata_plot/pl/utils.py b/src/spatialdata_plot/pl/utils.py index 441cdb47..1298c4c4 100644 --- a/src/spatialdata_plot/pl/utils.py +++ b/src/spatialdata_plot/pl/utils.py @@ -951,11 +951,16 @@ def _multiscale_to_spatial_image( height: float, scale: str | None = None, is_label: bool = False, + crop: tuple[float, float, float, float] | None = None, + extent: dict[str, tuple[float, float]] | None = None, ) -> DataArray: """Extract the DataArray to be rendered from a multiscale image. From the `DataTree`, the scale that fits the given image size and dpi most is selected and returned. In case the lowest resolution is still too high, a rasterization step is added. + When ``crop`` (a cs-space ``(x0, y0, x1, y1)`` box) and the full ``extent`` are given, only the + crop window is shown, so the level is chosen so the *window* reaches the target resolution rather + than the full image — otherwise a Visium-HD crop would upsample a coarse pyramid level. Parameters ---------- @@ -998,6 +1003,16 @@ def _multiscale_to_spatial_image( optimal_x = width * dpi optimal_y = height * dpi + if crop is not None and extent is not None: + # Only the crop window is drawn, so the full image needs enough pixels that the window + # portion reaches the target — scale the target up by full/window per axis. + full_x = float(extent["x"][1]) - float(extent["x"][0]) + full_y = float(extent["y"][1]) - float(extent["y"][0]) + win_x, win_y = crop[2] - crop[0], crop[3] - crop[1] + if win_x > 0 and win_y > 0: + optimal_x *= full_x / win_x + optimal_y *= full_y / win_y + # Pick the lowest-resolution scale where both x and y are >= the # target pixel count. Falls back to highest available resolution. optimal_scale = scales[-1] @@ -1508,20 +1523,23 @@ def _bbox_mask_shapes(shapes: GeoDataFrame, elem_bbox: tuple[float, float, float """Boolean keep-mask for shapes whose bounds intersect ``elem_bbox`` (element-native coords). Bbox-intersect, not clip: a boundary-crossing shape is kept whole (axis-limit clipping trims it - visually). Circles are stored as ``Point`` + ``radius``, so their bounds are the centre expanded by - the radius; a centroid-only test would drop circles whose body overlaps the box. Polygons use the - geometry's own bounds. This is the masking form of geopandas ``.cx`` (which returns a frame, not a - mask we can align to ``color_spec``). + visually). Circles are stored as ``Point`` + ``radius``, so a centroid-only test would drop circles + whose body overlaps the box. Rows are handled per-geometry (a frame may mix circles and polygons): + polygons use the geometry's own bounds; circle rows expand their degenerate ``Point`` bounds by the + radius. This is the masking form of geopandas ``.cx`` (which returns a frame, not a mask we can align + to ``color_spec``). """ x0, y0, x1, y1 = elem_bbox geom = shapes.geometry - if (geom.geom_type == "Point").all(): # circles: Point + radius column - cx, cy = geom.x.to_numpy(), geom.y.to_numpy() + b = geom.bounds # C-level; columns minx, miny, maxx, maxy (degenerate minx==maxx==cx for Points) + minx, miny, maxx, maxy = (b[c].to_numpy() for c in ("minx", "miny", "maxx", "maxy")) + is_point = (geom.geom_type == "Point").to_numpy() + if is_point.any() and ShapesModel.RADIUS_KEY in shapes: # expand circle rows by their radius r = np.asarray(shapes[ShapesModel.RADIUS_KEY], dtype=float) - minx, miny, maxx, maxy = cx - r, cy - r, cx + r, cy + r - else: # polygons / multipolygons (also valid for plain points: degenerate bounds) - b = geom.bounds # C-level; columns minx, miny, maxx, maxy - minx, miny, maxx, maxy = (b[c].to_numpy() for c in ("minx", "miny", "maxx", "maxy")) + minx = np.where(is_point, minx - r, minx) + miny = np.where(is_point, miny - r, miny) + maxx = np.where(is_point, maxx + r, maxx) + maxy = np.where(is_point, maxy + r, maxy) return (maxx >= x0) & (minx <= x1) & (maxy >= y0) & (miny <= y1) diff --git a/tests/pl/test_show.py b/tests/pl/test_show.py index 76176b2f..e62c4d54 100644 --- a/tests/pl/test_show.py +++ b/tests/pl/test_show.py @@ -142,8 +142,8 @@ def test_title_empty_string_suppresses_title(self, sdata_blobs: SpatialData): def test_crop_sets_exact_axis_limits(sdata_blobs: SpatialData): - """crop=(xmin, xmax, ymin, ymax) pins the view to the box; y is inverted (top-left origin).""" - ax = sdata_blobs.pl.render_points().pl.show(crop=(100, 300, 120, 260), return_ax=True, show=False) + """crop_coord=(xmin, xmax, ymin, ymax) pins the view to the box; y is inverted (top-left origin).""" + ax = sdata_blobs.pl.render_points().pl.show(crop_coord=(100, 300, 120, 260), return_ax=True, show=False) assert ax.get_xlim() == pytest.approx((100, 300)) assert ax.get_ylim() == pytest.approx((260, 120)) # set_ylim(ymax, ymin) plt.close("all") @@ -151,7 +151,7 @@ def test_crop_sets_exact_axis_limits(sdata_blobs: SpatialData): def test_crop_ignores_pad_extent(sdata_blobs: SpatialData): """pad_extent must not widen a crop box (the view is exactly the box).""" - ax = sdata_blobs.pl.render_points().pl.show(crop=(100, 300, 120, 260), pad_extent=50, return_ax=True, show=False) + ax = sdata_blobs.pl.render_points().pl.show(crop_coord=(100, 300, 120, 260), pad_extent=50, return_ax=True, show=False) assert ax.get_xlim() == pytest.approx((100, 300)) assert ax.get_ylim() == pytest.approx((260, 120)) plt.close("all") @@ -164,7 +164,7 @@ def n_offsets(ax): return sum(len(c.get_offsets()) for c in ax.collections if hasattr(c, "get_offsets")) full = sdata_blobs.pl.render_points().pl.show(return_ax=True, show=False) - cropped = sdata_blobs.pl.render_points().pl.show(crop=(100, 300, 120, 260), return_ax=True, show=False) + cropped = sdata_blobs.pl.render_points().pl.show(crop_coord=(100, 300, 120, 260), return_ax=True, show=False) assert 0 < n_offsets(cropped) < n_offsets(full) plt.close("all") @@ -183,11 +183,74 @@ def vrange(ax): return None full = sdata.pl.render_points("p", color="val").pl.show(return_ax=True, show=False) - cropped = sdata.pl.render_points("p", color="val").pl.show(crop=(20, 50, 30, 60), return_ax=True, show=False) + cropped = sdata.pl.render_points("p", color="val").pl.show(crop_coord=(20, 50, 30, 60), return_ax=True, show=False) assert vrange(cropped) == pytest.approx(vrange(full)) plt.close("all") +def test_crop_transfunc_norm_matches_uncropped(): + """The pinned norm must use the transfunc'd full-element range, so crop+transfunc matches uncropped.""" + rng = np.random.default_rng(0) + df = pd.DataFrame({"x": rng.uniform(0, 100, 3000), "y": rng.uniform(0, 100, 3000), "val": rng.uniform(0, 1, 3000)}) + df.loc[0, ["x", "y", "val"]] = [90, 90, 10.0] # extreme value outside the crop box + sdata = SpatialData(points={"p": PointsModel.parse(df, transformations={"global": Identity()})}) + + def vrange(ax): + for c in ax.collections: + if getattr(c, "norm", None) is not None and c.norm.vmax is not None: + return (c.norm.vmin, c.norm.vmax) + return None + + full = sdata.pl.render_points("p", color="val", transfunc=np.log1p, method="matplotlib").pl.show( + return_ax=True, show=False + ) + cropped = sdata.pl.render_points("p", color="val", transfunc=np.log1p, method="matplotlib").pl.show( + crop_coord=(20, 50, 30, 60), return_ax=True, show=False + ) + assert vrange(cropped) == pytest.approx(vrange(full)) # log1p range, not the raw range + plt.close("all") + + +def test_crop_datashader_autoscales_over_window(): + """Datashader crop autoscales over the visible window: a value far outside the box can't recolor it.""" + rng = np.random.default_rng(0) + base = pd.DataFrame({"x": rng.uniform(20, 50, 12000), "y": rng.uniform(30, 60, 12000), "val": rng.uniform(0, 1, 12000)}) + outside = pd.DataFrame({"x": [200.0], "y": [200.0], "val": [1000.0]}) # far outside the crop window + s_a = SpatialData(points={"p": PointsModel.parse(base, transformations={"global": Identity()})}) + s_b = SpatialData( + points={"p": PointsModel.parse(pd.concat([base, outside], ignore_index=True), transformations={"global": Identity()})} + ) + + def raster(s): + ax = s.pl.render_points("p", color="val", method="datashader").pl.show( + crop_coord=(20, 50, 30, 60), return_ax=True, show=False + ) + (im,) = ax.get_images() + arr = np.asarray(im.get_array()).copy() + plt.close("all") + return arr + + # If the norm leaked the full-data range (old bug), the extreme value would squish the window's colors. + np.testing.assert_array_equal(raster(s_a), raster(s_b)) + + +def test_crop_multiscale_selects_finer_level(): + """A crop must pick a pyramid level fine enough for the WINDOW, not the whole image (Visium HD).""" + from spatialdata.models import Image2DModel + + from spatialdata_plot.pl.utils import _multiscale_to_spatial_image + + n = 800 + rng = np.random.default_rng(0) + tree = Image2DModel.parse(rng.random((1, n, n), dtype=np.float32), dims=("c", "y", "x"), scale_factors=[2, 2]) + extent = {"x": (0.0, float(n)), "y": (0.0, float(n))} + coarse = _multiscale_to_spatial_image(tree, dpi=10, width=5, height=5) # target ~50px over the full image + fine = _multiscale_to_spatial_image( + tree, dpi=10, width=5, height=5, crop=(0.0, 0.0, 80.0, 80.0), extent=extent # 10% window -> 10x boost + ) + assert fine.shape[-1] > coarse.shape[-1] + + def test_crop_image_rasterizes_only_window(): """A cropped large image is rasterized to the window at figure resolution, not the full image then clipped. @@ -205,7 +268,7 @@ def test_crop_image_rasterizes_only_window(): ) sdata = SpatialData(images={"img": img}) # full world extent x=(1000, 7000), y=(500, 6500); crop a small central window - ax = sdata.pl.render_images("img").pl.show(crop=(3500, 3900, 3500, 3900), return_ax=True, show=False) + ax = sdata.pl.render_images("img").pl.show(crop_coord=(3500, 3900, 3500, 3900), return_ax=True, show=False) assert ax.get_xlim() == pytest.approx((3500, 3900)) assert ax.get_ylim() == pytest.approx((3900, 3500)) # inverted y @@ -217,12 +280,12 @@ def test_crop_image_rasterizes_only_window(): def test_crop_invalid_order_raises(sdata_blobs: SpatialData): with pytest.raises(ValueError, match="xmin < xmax and ymin < ymax"): - sdata_blobs.pl.render_points().pl.show(crop=(300, 100, 120, 260), show=False) + sdata_blobs.pl.render_points().pl.show(crop_coord=(300, 100, 120, 260), show=False) def test_crop_wrong_length_raises(sdata_blobs: SpatialData): with pytest.raises(TypeError, match="tuple of four numbers"): - sdata_blobs.pl.render_points().pl.show(crop=(100, 300, 120), show=False) + sdata_blobs.pl.render_points().pl.show(crop_coord=(100, 300, 120), show=False) def test_crop_multiple_coordinate_systems_raises(sdata_blobs: SpatialData): @@ -230,7 +293,7 @@ def test_crop_multiple_coordinate_systems_raises(sdata_blobs: SpatialData): set_transformation(sdata_blobs["blobs_points"], Identity(), to_coordinate_system="other") with pytest.raises(ValueError, match="single coordinate system"): sdata_blobs.pl.render_points().pl.show( - coordinate_systems=["global", "other"], crop=(100, 300, 120, 260), show=False + coordinate_systems=["global", "other"], crop_coord=(100, 300, 120, 260), show=False ) diff --git a/tests/pl/test_utils.py b/tests/pl/test_utils.py index e732ada7..7b877672 100644 --- a/tests/pl/test_utils.py +++ b/tests/pl/test_utils.py @@ -1418,6 +1418,16 @@ def test_bbox_mask_shapes_keeps_circle_near_edge(): assert len(circ.cx[1:2, 1:2]) == 0 +def test_bbox_mask_shapes_mixed_circle_and_polygon(): + # a frame mixing a circle (Point+radius) and a polygon must stay radius-aware per row: + # the r=3 circle body reaches the box; the distant polygon does not. + gdf = gpd.GeoDataFrame( + {"geometry": [Point(0, 0), Polygon([(100, 100), (101, 100), (101, 101)])], "radius": [3.0, np.nan]} + ) + shapes = ShapesModel.parse(gdf, transformations={"g": Identity()}) + np.testing.assert_array_equal(_bbox_mask_shapes(shapes, (1.0, 1.0, 2.0, 2.0)), [True, False]) + + def test_bbox_mask_shapes_polygon_intersect_and_empty(): polys = [Polygon([(0, 0), (10, 0), (10, 10), (0, 10)]), Polygon([(100, 100), (110, 100), (110, 110), (100, 110)])] gdf = ShapesModel.parse(gpd.GeoDataFrame({"geometry": polys}), transformations={"g": Identity()}) From 906b8119d92a05ae56e935c4395aa5052c9b3896 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 12 Aug 2026 15:37:32 +0200 Subject: [PATCH 3/8] feat(show): window the datashader-image crop path too MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously method='datashader' images ignored crop_coord (full render + axis-clip). Now the datashader aggregation is restricted to the window: rasterize() supplies the correct window coords/transform and only the sliced source is materialized, so the full image is never read — this scales to Visium HD (prototype: peak memory 258 -> 19 MB on 8k^2, and O(window) instead of O(image)). The datashader reduction (max/sum/...) is preserved by aggregating the sliced source in pixel space and index- assigning onto the rasterized grid. Falls back to full render for rotation/shear or an empty window. New _datashader_window_image helper in utils.py; regression test asserts the window is rasterized at figure resolution, not the full source. --- src/spatialdata_plot/pl/basic.py | 16 ++++---- src/spatialdata_plot/pl/render.py | 1 + src/spatialdata_plot/pl/utils.py | 63 +++++++++++++++++++++++++++++++ tests/pl/test_show.py | 22 +++++++++++ 4 files changed, 94 insertions(+), 8 deletions(-) diff --git a/src/spatialdata_plot/pl/basic.py b/src/spatialdata_plot/pl/basic.py index 8b04e985..68b85b2f 100644 --- a/src/spatialdata_plot/pl/basic.py +++ b/src/spatialdata_plot/pl/basic.py @@ -1385,14 +1385,14 @@ def show( Restrict the plot to a bounding box ``(xmin, xmax, ymin, ymax)`` in the rendered coordinate system's units (same order as :meth:`matplotlib.axes.Axes.axis` and as ``crop_coord`` in :func:`scanpy.pl.spatial` / :func:`squidpy.pl.spatial_scatter`). Points and shapes are - subsetted before drawing for speed; large images on the default matplotlib backend are - rasterized to the window only, so the full image is never materialized (fast at Visium HD - scale) and the zoom keeps full figure resolution; labels, and ``method='datashader'`` images, - are drawn in full and clipped to the box. For points and shapes, auto-scaled color ranges are - computed from the full element so colors match the uncropped plot; a cropped image's contrast - auto-scales over the window (pass explicit ``vmin``/``vmax`` or a ``norm`` to fix it). - Requires a single coordinate system (pass ``coordinate_systems`` with one entry if several - would otherwise be rendered). + subsetted before drawing for speed; large images (both the matplotlib and ``datashader`` + backends) are rasterized to the window only, so the full image is never materialized (fast + at Visium HD scale) and the zoom keeps full figure resolution; labels are drawn in full and + clipped to the box. For points and shapes, auto-scaled color ranges are computed from the + full element so colors match the uncropped plot; a cropped image's contrast auto-scales over + the window (pass explicit ``vmin``/``vmax`` or a ``norm`` to fix it). Requires a single + coordinate system (pass ``coordinate_systems`` with one entry if several would otherwise be + rendered). ax : list[Axes] | Axes | None Pre-existing matplotlib axes to plot on. Can be a single :class:`~matplotlib.axes.Axes` or a list matching the number of coordinate systems. If ``None``, a new figure and axes are created. diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index eed3ff7e..bf514001 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -1839,6 +1839,7 @@ def _render_images( coordinate_system=coordinate_system, extent=extent, downsample_method=downsample_method, + crop=crop, ) elif rasterize: img = _rasterize_if_necessary( diff --git a/src/spatialdata_plot/pl/utils.py b/src/spatialdata_plot/pl/utils.py index 1298c4c4..4b02aaac 100644 --- a/src/spatialdata_plot/pl/utils.py +++ b/src/spatialdata_plot/pl/utils.py @@ -889,6 +889,55 @@ def _rasterize_if_necessary( return image +def _datashader_window_image( + image: DataArray, + crop: tuple[float, float, float, float], + coordinate_system: str, + target_x_dims: int, + target_y_dims: int, + downsample_method: str, + has_c_dim: bool, + x_dims: int, + y_dims: int, +) -> DataArray | None: + """Datashader-aggregate only the crop window of an image; ``None`` to fall back to the full path. + + ``rasterize`` produces the target grid with correct world coords/transform for the ``crop`` box; + the source is sliced to the window in element-pixel space and aggregated with the datashader + reduction in that pixel space, then index-assigned onto the grid. The full image is never read. + Returns ``None`` for rotation/shear (box does not map to a box) or an empty window. + """ + elem_bbox = _bbox_to_element_space(image, coordinate_system, crop) + if elem_bbox is None: + return None + px0, py0, px1, py1 = (int(round(v)) for v in elem_bbox) + px0, py0 = max(px0, 0), max(py0, 0) + px1, py1 = min(px1, x_dims), min(py1, y_dims) + if px1 <= px0 or py1 <= py0: + return None + + cx0, cy0, cx1, cy1 = crop + target_unit_to_pixels = min(target_y_dims / (cy1 - cy0), target_x_dims / (cx1 - cx0)) + base = rasterize( + image, ("y", "x"), [cy0, cx0], [cy1, cx1], coordinate_system, target_unit_to_pixels=target_unit_to_pixels + ) + out_y, out_x = (base.shape[1], base.shape[2]) if has_c_dim else base.shape + src = image.isel(x=slice(px0, px1), y=slice(py0, py1)) + src = src.compute() if hasattr(src.data, "compute") else src + # Canvas is in the sliced source's own (pixel) coordinate space; the aggregated grid is + # index-assigned onto base, which already carries the correct world coords/transform. + cvs = ds.Canvas(plot_width=out_x, plot_height=out_y, x_range=(px0, px1), y_range=(py0, py1)) + if has_c_dim: + agg = np.stack( + [np.asarray(cvs.raster(src.isel(c=i), downsample_method=downsample_method).values) for i in range(src.sizes["c"])], + axis=0, + ) + else: + agg = np.asarray(cvs.raster(src, downsample_method=downsample_method).values) + base.values = agg.astype(base.dtype, copy=False) + return base + + def _rasterize_if_necessary_datashader( image: DataArray, dpi: float, @@ -897,12 +946,18 @@ def _rasterize_if_necessary_datashader( coordinate_system: str, extent: dict[str, tuple[float, float]], downsample_method: str, + crop: tuple[float, float, float, float] | None = None, ) -> DataArray: """Downsample to canvas resolution with a configurable datashader reduction. Used by ``render_images(method='datashader')`` so sparse images (mostly zeros, rare non-zero pixels) survive the downsample step instead of being averaged away by the default mean aggregation. + + When ``crop`` (a cs-space ``(x0, y0, x1, y1)`` box) is given, the aggregation is restricted to the + window: ``rasterize`` supplies the correct window coords/transform and only the sliced source is + materialized (so the full image is never read — this scales to Visium HD). Falls back to the full + path for rotation/shear or an empty window. """ has_c_dim = len(image.shape) == 3 y_dims, x_dims = (image.shape[1], image.shape[2]) if has_c_dim else image.shape @@ -910,6 +965,14 @@ def _rasterize_if_necessary_datashader( target_y_dims = int(dpi * height) target_x_dims = int(dpi * width) + if crop is not None: + windowed = _datashader_window_image( + image, crop, coordinate_system, target_x_dims, target_y_dims, downsample_method, has_c_dim, x_dims, y_dims + ) + if windowed is not None: + return windowed + # rotation/shear or empty window: fall through to the full render (axis limits clip) + if y_dims <= target_y_dims and x_dims <= target_x_dims: return image diff --git a/tests/pl/test_show.py b/tests/pl/test_show.py index e62c4d54..dfd63bef 100644 --- a/tests/pl/test_show.py +++ b/tests/pl/test_show.py @@ -278,6 +278,28 @@ def test_crop_image_rasterizes_only_window(): plt.close("all") +def test_crop_datashader_image_rasterizes_only_window(): + """method='datashader' images are windowed under crop too, not full-rendered then clipped (#764 F4).""" + from spatialdata.models import Image2DModel + from spatialdata.transformations import Scale, Sequence, Translation + + n = 3000 + rng = np.random.default_rng(0) + transform = Sequence([Scale([2.0, 2.0], axes=("x", "y")), Translation([1000.0, 500.0], axes=("x", "y"))]) + img = Image2DModel.parse( + rng.random((1, n, n), dtype=np.float32), dims=("c", "y", "x"), transformations={"global": transform} + ) + sdata = SpatialData(images={"img": img}) + ax = sdata.pl.render_images("img", method="datashader").pl.show( + crop_coord=(3500, 3900, 3500, 3900), return_ax=True, show=False + ) + assert ax.get_xlim() == pytest.approx((3500, 3900)) + assert ax.get_ylim() == pytest.approx((3900, 3500)) # inverted y + (im,) = ax.get_images() + assert max(im.get_array().shape[:2]) < n // 2 # window at figure resolution, not the full source + plt.close("all") + + def test_crop_invalid_order_raises(sdata_blobs: SpatialData): with pytest.raises(ValueError, match="xmin < xmax and ymin < ymax"): sdata_blobs.pl.render_points().pl.show(crop_coord=(300, 100, 120, 260), show=False) From c84f76abb98308b2660b6783a7d6d2d5f0dc8472 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 12 Aug 2026 16:13:12 +0200 Subject: [PATCH 4/8] feat(show): window the labels crop path Labels were the last element still full-render + axis-clip under crop_coord. Thread crop into _render_labels so the label raster is windowed via the same crop-aware _rasterize_if_necessary / _multiscale_to_spatial_image paths as images (full array never materialized; multiscale picks the level for the window). Colour stability: windowing drops off-window instances before colours resolve. That is stable for numeric columns, pandas-Categorical columns (fixed levels) and explicit palettes; a plain-string column with the default palette would reshuffle colours as whole categories drop out of the window, so that case falls back to full render + clip. Empty-window guard returns before the instance-overlap/colour machinery when the box covers no labels. Tests: placement + empty window; no-colour-reshuffle for categorical (windowed) and string (fallback). Full non-visual suite: 390 passed. --- src/spatialdata_plot/pl/basic.py | 18 +++---- src/spatialdata_plot/pl/render.py | 24 ++++++++++ tests/pl/test_show.py | 79 +++++++++++++++++++++++++++++++ 3 files changed, 113 insertions(+), 8 deletions(-) diff --git a/src/spatialdata_plot/pl/basic.py b/src/spatialdata_plot/pl/basic.py index 68b85b2f..7977cddf 100644 --- a/src/spatialdata_plot/pl/basic.py +++ b/src/spatialdata_plot/pl/basic.py @@ -1386,13 +1386,15 @@ def show( system's units (same order as :meth:`matplotlib.axes.Axes.axis` and as ``crop_coord`` in :func:`scanpy.pl.spatial` / :func:`squidpy.pl.spatial_scatter`). Points and shapes are subsetted before drawing for speed; large images (both the matplotlib and ``datashader`` - backends) are rasterized to the window only, so the full image is never materialized (fast - at Visium HD scale) and the zoom keeps full figure resolution; labels are drawn in full and - clipped to the box. For points and shapes, auto-scaled color ranges are computed from the - full element so colors match the uncropped plot; a cropped image's contrast auto-scales over - the window (pass explicit ``vmin``/``vmax`` or a ``norm`` to fix it). Requires a single - coordinate system (pass ``coordinate_systems`` with one entry if several would otherwise be - rendered). + backends) and labels are rasterized to the window only, so the full array is never + materialized (fast at Visium HD scale) and the zoom keeps full figure resolution. For points + and shapes, auto-scaled color ranges are computed from the full element so colors match the + uncropped plot; a cropped image's contrast auto-scales over the window (pass explicit + ``vmin``/``vmax`` or a ``norm`` to fix it). Labels coloured by a plain-string column with the + default palette fall back to full render + clip (windowing could otherwise reshuffle + colours); use a categorical dtype or an explicit palette to keep the windowed fast path. + Requires a single coordinate system (pass ``coordinate_systems`` with one entry if several + would otherwise be rendered). ax : list[Axes] | Axes | None Pre-existing matplotlib axes to plot on. Can be a single :class:`~matplotlib.axes.Axes` or a list matching the number of coordinate systems. If ``None``, a new figure and axes are created. @@ -2151,7 +2153,7 @@ def _render_panel( } if cmd == "render_images": kwargs["channel_legend_entries"] = axis_channel_legend_entries - if cmd in {"render_points", "render_shapes", "render_images"}: + if cmd in {"render_points", "render_shapes", "render_images", "render_labels"}: kwargs["crop"] = crop if cmd in {"render_images", "render_labels"}: kwargs["rasterize"] = _should_rasterize( diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index bf514001..32a9756d 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -2219,6 +2219,7 @@ def _render_labels( legend_params: LegendParams, rasterize: bool, colorbar_requests: list[ColorbarSpec] | None = None, + crop: tuple[float, float, float, float] | None = None, ) -> None: _log_context.set("render_labels") element = render_params.element @@ -2249,6 +2250,21 @@ def _render_labels( _guard_2d_only(label, element, "labels") extent = get_extent(label, coordinate_system=coordinate_system) + # Windowing the label raster under `crop` drops off-window instances before colours are resolved. + # That is colour-stable for numeric (continuous) columns, pandas-Categorical columns (fixed levels), + # and when an explicit palette is given; but a plain-string column with the default palette would + # reshuffle colours as whole categories drop out of the window (their sorted positions shift). Fall + # back to full render + axis-clip for that case so cropped colours always match the uncropped plot. + crop_labels = crop + if crop is not None and col_for_color is not None and palette is None and table_name is not None: + _color_col = sdata[table_name].obs.get(col_for_color) + if ( + _color_col is not None + and not pd.api.types.is_numeric_dtype(_color_col) + and not isinstance(_color_col.dtype, pd.CategoricalDtype) + ): + crop_labels = None + # get best scale out of multiscale label if isinstance(label, DataTree): label = _multiscale_to_spatial_image( @@ -2258,6 +2274,8 @@ def _render_labels( height=fig_params.fig.get_size_inches()[1], scale=scale, is_label=True, + crop=crop_labels, + extent=extent, ) # spatialdata >= 0.8 rejects non-integer label rasters at the model boundary, but the library @@ -2279,6 +2297,7 @@ def _render_labels( height=fig_params.fig.get_size_inches()[1], coordinate_system=coordinate_system, extent=extent, + crop=crop_labels, ) # the above adds a useless c dimension of 1 (y, x) -> (1, y, x) @@ -2288,6 +2307,11 @@ def _render_labels( # rasterize mask below; compute them once over the (possibly rasterized) raster. unique_labels = np.unique(label.values) + if crop_labels is not None and not np.any(unique_labels != 0): + # The crop window covers no labels (only background). Nothing to draw; the panel's axis + # limits already clip to the box, so return before the instance-overlap/colour machinery. + return + if table_name is None: instance_id = unique_labels table = None diff --git a/tests/pl/test_show.py b/tests/pl/test_show.py index dfd63bef..cd66edbb 100644 --- a/tests/pl/test_show.py +++ b/tests/pl/test_show.py @@ -300,6 +300,85 @@ def test_crop_datashader_image_rasterizes_only_window(): plt.close("all") +def _grid_labels_sdata(): + """A 2000x2000 label raster of 400 block-instances with a Scale+Translation, plus a table with a + categorical and a plain-string colour column. Large enough that rasterize()/windowing engages.""" + import anndata as ad + from spatialdata.models import Labels2DModel, TableModel + from spatialdata.transformations import Scale, Sequence, Translation + + n = 2000 + rng = np.random.default_rng(1) + lab = np.zeros((n, n), dtype=np.int32) + k = 0 + for i in range(20): + for j in range(20): + k += 1 + lab[i * 100 : (i + 1) * 100, j * 100 : (j + 1) * 100] = k + transform = Sequence([Scale([2.0, 2.0], axes=("x", "y")), Translation([1000.0, 500.0], axes=("x", "y"))]) + labels = Labels2DModel.parse(lab, dims=("y", "x"), transformations={"global": transform}) + obs = pd.DataFrame( + { + "instance_id": np.arange(1, 401), + "region": pd.Categorical(["labels"] * 400), + "ct_cat": pd.Categorical(rng.choice(list("ABCDE"), size=400), categories=list("ABCDE")), + "ct_str": rng.choice(list("ABCDE"), size=400).astype(object), + } + ) + table = TableModel.parse(ad.AnnData(obs=obs), region="labels", region_key="region", instance_key="instance_id") + return SpatialData(labels={"labels": labels}, tables={"table": table}) + + +def _legend_colors(ax): + leg = ax.get_legend() + out = {} + if leg is None: + return out + for text, handle in zip(leg.get_texts(), leg.legend_handles): + for attr in ("get_facecolor", "get_color"): + try: + v = np.ravel(getattr(handle, attr)()) + if v.size >= 3: + out[text.get_text()] = tuple(np.round(v[:3], 3)) + break + except (AttributeError, TypeError): + pass + return out + + +def test_crop_labels_placement_and_empty_window(): + """Labels crop pins the view to the box; a window with no labels renders without crashing.""" + sdata = _grid_labels_sdata() + ax = sdata.pl.render_labels("labels", color="ct_cat").pl.show( + crop_coord=(2600, 3000, 2200, 2600), return_ax=True, show=False + ) + assert ax.get_xlim() == pytest.approx((2600, 3000)) + assert ax.get_ylim() == pytest.approx((2600, 2200)) # inverted y + plt.close("all") + # a box far outside the data must not raise (empty-window guard) + sdata.pl.render_labels("labels", color="ct_cat").pl.show(crop_coord=(99000, 99400, 99000, 99400), show=False) + plt.close("all") + + +@pytest.mark.parametrize("col", ["ct_cat", "ct_str"]) +def test_crop_labels_no_color_reshuffle(col): + """Cropped label colours must match the uncropped plot for shared categories (windowed dtype-Categorical; + plain-string falls back to full render so it stays stable too).""" + sdata = _grid_labels_sdata() + full = sdata.pl.render_labels("labels", color=col).pl.show(return_ax=True, show=False) + full_colors = _legend_colors(full) + plt.close("all") + cropped = sdata.pl.render_labels("labels", color=col).pl.show( + crop_coord=(2600, 3000, 2200, 2600), return_ax=True, show=False + ) + crop_colors = _legend_colors(cropped) + plt.close("all") + shared = [c for c in set(full_colors) & set(crop_colors)] + assert shared # the window keeps several categories + for c in shared: + assert full_colors[c] == pytest.approx(crop_colors[c], abs=0.02) + + def test_crop_invalid_order_raises(sdata_blobs: SpatialData): with pytest.raises(ValueError, match="xmin < xmax and ymin < ymax"): sdata_blobs.pl.render_points().pl.show(crop_coord=(300, 100, 120, 260), show=False) From 52d49f4b5ecca105e240652a5801a865cd26cf64 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 12 Aug 2026 16:38:43 +0200 Subject: [PATCH 5/8] refactor(show): tidy crop internals (no behavior change) Cleanup from a quality review of the crop feature: - Extract _rasterize_to_bbox and use it in both _rasterize_if_necessary (replacing the raster_extent/do_rasterization branching) and _datashader_window_image, so 'rasterize a bbox to figure resolution' lives in one place. - Drop _datashader_window_image's redundant has_c_dim/x_dims/y_dims params (recomputed from image at the top). - Resolve the full-element crop norm range lazily on the matplotlib branch instead of eagerly in the crop block, so the datashader (large-data) path no longer pays a full-element min/max scan it never uses. --- src/spatialdata_plot/pl/render.py | 34 ++++++++----- src/spatialdata_plot/pl/utils.py | 81 ++++++++++++++----------------- 2 files changed, 58 insertions(+), 57 deletions(-) diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index 32a9756d..7aadc406 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -724,13 +724,14 @@ def _render_shapes( if outline_color_spec is not None: outline_color_spec = outline_color_spec.filter(keep) - # On-the-fly crop: drop shapes outside the box. Capture the full-element colour range first so the - # matplotlib backend keeps the uncropped norm (datashader autoscales over the window instead). - crop_norm_range: tuple[float, float] | None = None + # On-the-fly crop: drop shapes outside the box. Keep a reference to the pre-crop colour spec so the + # matplotlib backend can pin the uncropped norm; the range itself is resolved lazily below (only on + # the matplotlib path — datashader autoscales over the window, so it must not pay the full scan). + full_color_spec: ColorSpec | None = None if crop is not None: elem_bbox = _bbox_to_element_space(sdata_filt.shapes[element], coordinate_system, crop) if elem_bbox is not None: # None = rotation/shear; render full and let axis limits clip - crop_norm_range = _full_element_norm_range(color_spec, render_params.cmap_params, render_params.transfunc) + full_color_spec = color_spec # capture before filtering (filter returns a new object) keep_crop = _bbox_mask_shapes(shapes, elem_bbox) color_spec = color_spec.filter(keep_crop) shapes = shapes[keep_crop].reset_index(drop=True) @@ -958,9 +959,12 @@ def _draw_centroids(xy: np.ndarray, radius: float | None = None) -> None: elif method == "matplotlib": # Under crop, pin the norm to the full-element range so the zoom matches the uncropped plot - # (datashader, handled above, autoscales over the window instead). - if crop_norm_range is not None: - norm.vmin, norm.vmax = crop_norm_range + # (datashader, handled above, autoscales over the window instead). Resolved here (not in the crop + # block) so the datashader path never pays the full-element scan. + if full_color_spec is not None: + crop_norm_range = _full_element_norm_range(full_color_spec, render_params.cmap_params, render_params.transfunc) + if crop_norm_range is not None: + norm.vmin, norm.vmax = crop_norm_range # Build the paths once and share them across the fill and outline collections (geometry is # identical; only colours/alpha/linewidth differ), then apply the coordinate-system affine # once to the shared Path objects rather than once per collection. @@ -1496,16 +1500,17 @@ def _render_points( points = points[keep].reset_index(drop=True) _reparse_points(sdata_filt, element, points, transformation_in_cs, coordinate_system, col_for_color) - # On-the-fly crop: drop points outside the box. Capture the full-element colour range first so the - # matplotlib backend keeps the uncropped norm (datashader autoscales over the window instead). - crop_norm_range: tuple[float, float] | None = None + # On-the-fly crop: drop points outside the box. Keep a reference to the pre-crop colour spec so the + # matplotlib backend can pin the uncropped norm; the range itself is resolved lazily below (only on + # the matplotlib path — datashader autoscales over the window, so it must not pay the full scan). + full_color_spec: ColorSpec | None = None if crop is not None: elem_bbox = _bbox_to_element_space(sdata.points[element], coordinate_system, crop) if elem_bbox is not None: # None = rotation/shear; render full and let axis limits clip - crop_norm_range = _full_element_norm_range(color_spec, render_params.cmap_params, render_params.transfunc) keep_crop = _bbox_mask_points(points["x"].to_numpy(), points["y"].to_numpy(), elem_bbox) if not keep_crop.any(): return + full_color_spec = color_spec # capture before filtering (filter returns a new object) color_spec = color_spec.filter(keep_crop) points = points[keep_crop].reset_index(drop=True) n_points = len(points) # method auto-threshold below should see the drawn count @@ -1572,8 +1577,11 @@ def _render_points( # Under crop, pin to the full-element range so the zoom matches the uncropped plot. if color_spec.is_continuous: norm = _resolve_continuous_norm(color_spec.color_vector, render_params.cmap_params) - if crop_norm_range is not None: - norm.vmin, norm.vmax = crop_norm_range + if full_color_spec is not None: + # pin to the full-element range so the cropped zoom matches the uncropped plot + crop_norm_range = _full_element_norm_range(full_color_spec, render_params.cmap_params, render_params.transfunc) + if crop_norm_range is not None: + norm.vmin, norm.vmax = crop_norm_range else: norm = render_params.cmap_params.fresh_norm() # update axis limits if plot was empty before (necessary if datashader comes after) diff --git a/src/spatialdata_plot/pl/utils.py b/src/spatialdata_plot/pl/utils.py index 4b02aaac..62d4d6d2 100644 --- a/src/spatialdata_plot/pl/utils.py +++ b/src/spatialdata_plot/pl/utils.py @@ -805,6 +805,24 @@ def _get_valid_cs( return valid_cs +def _rasterize_to_bbox( + image: DataArray, + bbox: tuple[float, float, float, float], + coordinate_system: str, + target_x_dims: float, + target_y_dims: float, +) -> DataArray: + """Rasterize ``image`` to the world bbox ``(x0, y0, x1, y1)`` at ~``target_*_dims`` figure pixels. + + ``rasterize`` interprets ``target_unit_to_pixels`` in world units (not intrinsic pixels), so + dividing the target pixel count by the world span keeps placement correct for any transformation + (translation, scale, etc.) without a transform rewrite. + """ + x0, y0, x1, y1 = bbox + target_unit_to_pixels = min(target_y_dims / (y1 - y0), target_x_dims / (x1 - x0)) + return rasterize(image, ("y", "x"), [y0, x0], [y1, x1], coordinate_system, target_unit_to_pixels=target_unit_to_pixels) + + def _rasterize_if_necessary( image: DataArray, dpi: float, @@ -851,41 +869,23 @@ def _rasterize_if_necessary( target_x_dims = dpi * width if crop is not None: - # Restrict rasterization to the crop window. ``rasterize`` maps the target bbox - # through the element transform internally, so the window is placed correctly - # without a transform rewrite, only its source pixels are read (cost bounded by - # the window, not the full image), and the zoom keeps full figure resolution. - # ``crop`` is (x0, y0, x1, y1) in coordinate-system units. - raster_extent = {"x": (crop[0], crop[2]), "y": (crop[1], crop[3])} - do_rasterization = True + # Restrict rasterization to the crop window: only its source pixels are read (cost bounded by + # the window, not the full image), and the zoom keeps full figure resolution. ``crop`` is + # (x0, y0, x1, y1) in coordinate-system units. + bbox = crop + elif y_dims > target_y_dims + 100 or x_dims > target_x_dims + 100: + # Rasterize when the source is substantially larger than the figure DPI × size requires; the + # +100 margin avoids rasterizing when the image is only slightly larger than the target. + bbox = (extent["x"][0], extent["y"][0], extent["x"][1], extent["y"][1]) else: - raster_extent = extent - # Rasterize when the source image is substantially larger than what the - # current figure DPI × size requires. The +100 margin avoids rasterizing - # when the image is only slightly larger than the target. - do_rasterization = y_dims > target_y_dims + 100 or x_dims > target_x_dims + 100 - - if do_rasterization: - logger.info("Rasterizing image for faster rendering.") - # ``rasterize`` interprets ``target_unit_to_pixels`` in world units, not - # intrinsic pixels. Dividing by world extent keeps the result correct - # for any transformation (translation, scale, etc.). - world_x = float(raster_extent["x"][1]) - float(raster_extent["x"][0]) - world_y = float(raster_extent["y"][1]) - float(raster_extent["y"][0]) - target_unit_to_pixels = min(target_y_dims / world_y, target_x_dims / world_x) - image = rasterize( - image, - ("y", "x"), - [raster_extent["y"][0], raster_extent["x"][0]], - [raster_extent["y"][1], raster_extent["x"][1]], - coordinate_system, - target_unit_to_pixels=target_unit_to_pixels, - ) - if hasattr(image.data, "compute"): - # rasterize is lazy; downstream reads the result once per channel (NaN check, - # compositing, draw), so materialize once instead of re-running the warp each time. - image = image.copy(data=image.data.compute()) + return image + logger.info("Rasterizing image for faster rendering.") + image = _rasterize_to_bbox(image, bbox, coordinate_system, target_x_dims, target_y_dims) + if hasattr(image.data, "compute"): + # rasterize is lazy; downstream reads the result once per channel (NaN check, compositing, + # draw), so materialize once instead of re-running the warp each time. + image = image.copy(data=image.data.compute()) return image @@ -896,9 +896,6 @@ def _datashader_window_image( target_x_dims: int, target_y_dims: int, downsample_method: str, - has_c_dim: bool, - x_dims: int, - y_dims: int, ) -> DataArray | None: """Datashader-aggregate only the crop window of an image; ``None`` to fall back to the full path. @@ -907,6 +904,8 @@ def _datashader_window_image( reduction in that pixel space, then index-assigned onto the grid. The full image is never read. Returns ``None`` for rotation/shear (box does not map to a box) or an empty window. """ + has_c_dim = len(image.shape) == 3 + y_dims, x_dims = (image.shape[1], image.shape[2]) if has_c_dim else image.shape elem_bbox = _bbox_to_element_space(image, coordinate_system, crop) if elem_bbox is None: return None @@ -916,11 +915,7 @@ def _datashader_window_image( if px1 <= px0 or py1 <= py0: return None - cx0, cy0, cx1, cy1 = crop - target_unit_to_pixels = min(target_y_dims / (cy1 - cy0), target_x_dims / (cx1 - cx0)) - base = rasterize( - image, ("y", "x"), [cy0, cx0], [cy1, cx1], coordinate_system, target_unit_to_pixels=target_unit_to_pixels - ) + base = _rasterize_to_bbox(image, crop, coordinate_system, target_x_dims, target_y_dims) out_y, out_x = (base.shape[1], base.shape[2]) if has_c_dim else base.shape src = image.isel(x=slice(px0, px1), y=slice(py0, py1)) src = src.compute() if hasattr(src.data, "compute") else src @@ -966,9 +961,7 @@ def _rasterize_if_necessary_datashader( target_x_dims = int(dpi * width) if crop is not None: - windowed = _datashader_window_image( - image, crop, coordinate_system, target_x_dims, target_y_dims, downsample_method, has_c_dim, x_dims, y_dims - ) + windowed = _datashader_window_image(image, crop, coordinate_system, target_x_dims, target_y_dims, downsample_method) if windowed is not None: return windowed # rotation/shear or empty window: fall through to the full render (axis limits clip) From aed7791d07430d3c140bb2b74126348748fd9556 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 12 Aug 2026 16:49:27 +0200 Subject: [PATCH 6/8] test(show): add visual tests for crop_coord (#764) Add TestShow.test_plot_crop_{image,points,shapes,circles,labels, layered_elements} exercising crop_coord on the blobs dataset. Reference images are generated on CI and added in a follow-up commit (baselines must match the CI matplotlib, not a local render). --- tests/pl/test_show.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/pl/test_show.py b/tests/pl/test_show.py index cd66edbb..4accd95a 100644 --- a/tests/pl/test_show.py +++ b/tests/pl/test_show.py @@ -32,6 +32,34 @@ class TestShow(PlotTester, metaclass=PlotTesterMeta): def test_plot_pad_extent_adds_padding(self, sdata_blobs: SpatialData): sdata_blobs.pl.render_images(element="blobs_image").pl.show(pad_extent=100) + def test_plot_crop_image(self, sdata_blobs: SpatialData): + """Visual test: crop_coord windows an image to the box (#764).""" + sdata_blobs.pl.render_images("blobs_image").pl.show(crop_coord=(150, 400, 150, 400)) + + def test_plot_crop_points(self, sdata_blobs: SpatialData): + """Visual test: crop_coord subsets points to the box, colours from the full element (#764).""" + sdata_blobs.pl.render_points("blobs_points", color="genes", size=20).pl.show(crop_coord=(150, 400, 150, 400)) + + def test_plot_crop_shapes(self, sdata_blobs: SpatialData): + """Visual test: crop_coord subsets polygons to the box (#764).""" + sdata_blobs.pl.render_shapes("blobs_polygons").pl.show(crop_coord=(150, 400, 150, 400)) + + def test_plot_crop_circles(self, sdata_blobs: SpatialData): + """Visual test: crop_coord keeps circles whose body overlaps the box (radius-aware, #764).""" + sdata_blobs.pl.render_shapes("blobs_circles").pl.show(crop_coord=(150, 400, 150, 400)) + + def test_plot_crop_labels(self, sdata_blobs: SpatialData): + """Visual test: crop_coord windows a labels layer to the box (#764).""" + sdata_blobs.pl.render_labels("blobs_labels", color="channel_0_sum").pl.show(crop_coord=(150, 400, 150, 400)) + + def test_plot_crop_layered_elements(self, sdata_blobs: SpatialData): + """Visual test: layered image + labels both clip to the same crop box (#764).""" + ( + sdata_blobs.pl.render_images("blobs_image") + .pl.render_labels("blobs_labels", fill_alpha=0.5) + .pl.show(crop_coord=(150, 400, 150, 400)) + ) + def test_plot_frameon_false_single_panel(self, sdata_blobs: SpatialData): """Visual test: frameon=False hides axes decorations on a single panel (regression for #204).""" sdata_blobs.pl.render_images(element="blobs_image").pl.show(frameon=False) From 1b9702b96e8c65b31c86c8e991734fe6985d4e83 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 12 Aug 2026 16:57:44 +0200 Subject: [PATCH 7/8] test(show): add CI-generated crop_coord visual baselines (#764) Reference images for TestShow.test_plot_crop_* rendered by the hatch-test CI matrix and downloaded from the visual_test_results artifact. --- tests/_images/Show_crop_circles.png | Bin 0 -> 22654 bytes tests/_images/Show_crop_image.png | Bin 0 -> 85616 bytes tests/_images/Show_crop_labels.png | Bin 0 -> 42540 bytes tests/_images/Show_crop_layered_elements.png | Bin 0 -> 90823 bytes tests/_images/Show_crop_points.png | Bin 0 -> 29852 bytes tests/_images/Show_crop_shapes.png | Bin 0 -> 21785 bytes 6 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/_images/Show_crop_circles.png create mode 100644 tests/_images/Show_crop_image.png create mode 100644 tests/_images/Show_crop_labels.png create mode 100644 tests/_images/Show_crop_layered_elements.png create mode 100644 tests/_images/Show_crop_points.png create mode 100644 tests/_images/Show_crop_shapes.png diff --git a/tests/_images/Show_crop_circles.png b/tests/_images/Show_crop_circles.png new file mode 100644 index 0000000000000000000000000000000000000000..fcd08b1a2e338d7dc75aaba2760f8e1f7e1d5ff6 GIT binary patch literal 22654 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‡Bq=Tshq7ZWh?re)y;!U>aKcUfZCJQnq`fOXUkXo14 z`EYno4$aTQb2Bvu0v*yx=-H%DX4$0xmNlss0d-tto^j6(0c=hJ_$VmjH%63Ah8XZ1 zjuKhPc0uz+5LKZV{Zi66NK~R@4iMQ$5ND=2TfhHP$`fEil5$5MsZ8UrHj4#AGL+6{DS#y9tsqiW_ai9t?VD3;o<-#s z4l6mJw&CJ_f*uMPr7|M4+hk?4lL)nxW+Z~7pjc2%cJ?pkD&W-(C-am<6_flkL!if= zVE9YCT^>dGn{`Ge*L@b&=v7im@Qa1-p~ZifuC=dUP$ueY9V+CESI@sG-Y+uyixK4K z=kEp?Mfj#cd)+i>dwVn@dNBIOCwO6{&@5hRrUbiqVmeZ36oEkWvp3qt@i?s&r#wFwrK^_}XAj9nsl?Dx_ocO<0x z;?wu#=N!AfW)&$u`&gwF~!SYM_@K--Z3vS_VX3YKKpeU+L61N{s*F(74>-v>xf6!+2Z_k{Y{ zOY{Wk;Rhr4!}liY^G5Jv_-hSS{=BFr`h9}1HPA)j6Lhyr;y*0-aRc&rIQ!m7`rUm= zX>#B8sUV+VLB^LasmGVB=;bW#2{xj9ReVhZMr#!^Db3c{S>DuHz5$XesL@t}Hyn0V zmsXBY`HVPM2!mM^Hl@lal=JXb#8X}^^L^$Ar3 zMwZ*kLsOI=xz#c(pEx1kV<^rQZabfu7_bo%MrVw_8(k=iJUIl)A@(bs>hfk__?sJz zHJlRXwys}$Om1Ft^tHM|?Ru))eD8gMl&o9o?FT!qX$O?jgmUL5KF|#KV06u zK#axY7DS$5)_>jhTHaS^bf13db^Ze>Z*D=~-@Z&%U~RASe?IQM1Qa0eOC`wr<$J8~ zc_R3J^!fIu=jy*#kd@-UU1xzK=Pwh=LG9R?X z>Lr)!g=b^7wM@0^RHQU?&4*^Q)_~I#(weaj#}@}IhR=qe5uEQrn3s=ONzHIgEaGFa zXdq4kuo~)UOn0!B25A1WDY39ss0edI^@64GS=>-}Xwdz9tPlepPkl|k=x9_J9CzbYMvO`b@4Y+7c ztW;<(I@`}O5$o?A`Czm3m7sTDL{doQ9z9x208Do@GN$S@rWDSFcCS|ir}dl0B4+MTO`U#ra#vc<;cvC7aew! z9#vrKHDBa+ZqfgwRUoB~1Xwk@JLmz&=LhH!$@EJ+>T~@6uuct-GpuKy;zv8^?m^(S zQSkN0dvT8oNFpKS^eFfu`FZ^4J^lE008-uvUhWB8g5)vpYqjrdAUV{x%CQ}#kIW@~ zCWtDlQ&L;mn@C#@5+kw*{0)Ou0ZCjVZWSssiC`U(5~+FBFbWiu zMf$|?7thhzpA!tovLqVu^^+V`FuXVvV^#76wuqy|y=&YmvZA=VIrHRdzY`u%&~3xZ z-0oH@cFpyzTTWGrWjwqClycWAGO)Fdo?VKqE5M`GgSy{Dk1$5xk@pA?*9}&Wu8$t9 z{pKICeVA{&Yg+uu-@li0KpTtctis28e#$nO44BEMC%|wzW<`qDSUFf3&zEFc6(^ne zda%OH($)l5e;0-spJlRQhc-s)-lPgrYr*HZT4o5kUjeTQ{u1CB%xa#AQc+RiP`vL5 zzJ-0xg4XL2W!r(vbSKVKS@p~3BY2=9Q2c0b9@bCdcfikf07rTlkw!^4%A{imezt^L z-Je}upHSThP34466?0a&ZptxkzKSHjEzA|K!qF-$=fMyKZ%@1;=QH9<32cDv2_UdG z&BLKTP3)Oqrvru%!d+7n0$G`Qp;KG+Tg&@9s%)I(Y7UKnL9ldPeV9YXl)n~#oTw6& zE@P%cCSqsnmRH#$SC11oU<1IX$d=N3DPeGa*2tm(jVI}aOfnz?t?V;%He@YQ7VMT3 zjnk21t+)_>NxOtq6Jil4oghz0=5j%(nEq=UtNGD*$d1D|tZ#I!wGt1&TY*@-RAhMx z(6SNbLN5!l+K*J51O(&I@w1INkQ=($^4Va?RRi(34>;jc`LQrG{IVCpDP1p$2_~`d zlSbfN#t0BxdI`WgX7Ver4;@y>PtJ&u6Kzy!jUj4qp?wLezn*(|)?y)o>@~B5q#j)O zoBbFyS}YSWt@3F&SSB`>Q!V7b`bSsM>mZQr(5W0^Il|=3RUBZb8lcwapyZNi zC|}4q~8s*rq{YXI76c)MEw{(F}f5ZCDW`td>tc0RB!&6kB}QfqOMy^dA%ZWb)%T5@){aBMSR$M4bT6DU1*a!;Gp1ZS9wb~O3;&5&a|`oX)zATFXOS<};Z zuoIjzR0lH>I{xZt_8NvK(w4xw>TP{y3+3w)acn@%*CdC11XqTK z%~APmj3iSuqE%DKq3sY1uF+8H7X48&tNwtwZ9@ddEUvBWzeOl^F^rhaedGPxF`#(*^$OjLbT)1L7YWrAgco`Xc4fQph3UnqDt(YCC_YYg2wUXc*K%T zMODV79=XwlG05{mw9BBA15yy{+u6y_J?(=F=hrB%wermj}S_32!? zs-kOQ&O$wxh~pAXmq|b^i8@y+pS_$Peu1}rG&HR&YxN*3 zY70nq&Y5Cm>kkqnJ~1ba%^P90u~_=Mfa_Ta5N1!RkC@L}t*B=HXCpyPDi_xmWCVsL zKpRQ|ONOQ_iD*GKfbbGNC~%+j2wLNL|XtZOCu2C{29uO42K{U`ocDOT>tQ0 zuEF24zESyz^l<3j8ARud2X)u?9C}H|?7b-};z9~b=Dw>`B?Z6hx z({!ws*m7q#HVfyhAlOzcgOtWw(5d#@?^1~n45={tX_o*obm$!;=p*!R}~Jo zYHqRunu6t_VqbQ794cio=6QT|TBxEqW#Ml|A!vvN8r4kr;AL?}8SaMh~1FHJinp2V@gYrhxE%>>3M|DUK7^w9=H`An9SpodlOsff@ zaTkKoUYbYU3KClg%!Hhi$h&!f+Aibw!?$_Se`7|pxIAHP@XB_jlil*7Uu>>F6Fy2; z^}qa~Vn<4>JyWeW6Do|l@FlGWaCioIO)GvglVnwWB4=}bbi7m3j&V3HbsQ<1!Z7ff z?y4+I9tTbb=r(04tWFk+eI>pW=ySME2wplAx`axG^jJ&DNrGw8cj|&KKggJ-3aN+5I650<2x~+Iiv!92UEiAI%jo&96y3!+IR-lMCBf@uhYtV7s!#Rj)Q1;H zR)8~0ae$}aE@$c6rTLxOEYhOFCJ9m^q{lMzYA?G)i;7_(qt*n`g<;9hX$!~%gn*SE zOgx~$vzZ~zNCfU@cw>t)$?8N*YKlx29JQH5N%w#R4O+9k_Le6x8C+(DwbvDnY-h;5 zyNoy!&!(5hK6h1Mr;8HbPjIUs=rub26|tB&Q|j8GMIf8kkpY_kW)s+rh(Hl)q6I(W zC2AyFZ6Bmwr-{-$rW}y53Z5-5%@`VnJup#;&OGLZJ1}sy^n{kmoZO6k)4?Rt5=^Rz zQfB#eWuyb(-)Et7n>0=8=u=5UlQOWB%J!HtYA;_qL{g^ zY?WzzyVIAlTQmcV$0);Gf!2-NDtu3f;Gn+)^QHS?f$g_L=X{1D`~w zqwXE+Wj4sj&vwW{HKW(|<3UxZ43u%DJ`5Nsu(p-A|)igkZaK3(l}CO6vmLA zgum3KrSeCnzVK*rvKitWuG-sq{|zRAdw%?&qQg(*VO|3-rAK>xkM+PAxlxe`M08z%G|ZX8Z#BDs#V3c9+| zEck%AGjkYoeUkJrJayjKLQMHq|?_^Fi}y)c_!Rxj7Ty;15rOJLe?ODR@?COfoZq!BcvAEsByPTRhY{| zRo*X1Q&Pp|*TQ8kdtWopvaCZiOQS$a_dz5e9KOUi?p897!NKrOJL++M4WN-Ah2f;3 z{$38=gR;>KUqVC9!-d{0^Dcn6&CbQk#3Ydd!i~YB^!ULcLi7eRAt2OOBYPK8m?AKq zOrl!~yg(ATWOMIAq5k;24Tqt7N+9gw=!g$Q`+f~aXq3~^8_N`SFALAkO}X4PfNx#X z{wR7Cc1@GL1M88*stm*s5!w+6nsaSpd#W(}DXL0rh@Qy#i%faFRJ9j0&0pz6HYVFa z8&<7DhiQYH@$0B7n`af=K*xFM_}n{KP0kIRs%{$_4j9nbJ4(E9R%S?{KJ4~%f< zk;c#OwZIcz&uSc2bWOuD=q}RNJSd!~DFzabVwxF(G20DLR3du)7sAJh2`_>3nUdQa z2++&n*Xw>Svsw0U`X!N=7GxQ#J3TT!%odiSxAT)^`LAN(^>;cr2y9Hey5h*^QaiHw zDRGRoZV-AKl7RG(4_GcEtP%9_wzY!hMREIRVy{=fx$M2RsOgr13!F=XOvF53CXr&y zl!i!}giPT=rxviDK_l1n(PRtClZM0yF&R-Cs&zIE(Gu#A>M-z=3GELamTOy>p$s-+ zG3?V)3H#}4J(Y_l{;;MQ41&=SqT;#x|3OH48v`l*xi5uCaS}~POzt5N1rU$8B;FpCF^?p;pBPRz|iBGqU*5gO08CpBgXWJ z!?@wJY&R_=h`lIc$=3OwVcY_`7Tp%$PHh2gjQGs9s~0tCLUYakhAFQku@ z7dd^mwsJ=urlApd+ynq?(U4jzti41LQEs;Mn#MShlYq(t(SklT=G|$OCXH_pMvr8~ zCR>6ALtXR-q=ZZPJyR^L=!ebT21T%4m)g;GO6V!ik9#1v4%qO|Jd!s;%Z8+CR6NL$ z9b~Yn3nA^>Pm$Oc{KK7($;ABjl2?Hu-+-LIp2<|yzpx5=8Qp$B0Yg0304Ml6BMGA~kW%LDY zc$SVZH5|p$i^k5o<}vq@O08kP4I~?mxgET8@zu&Q;vfEY2neQ=W3t)y7;-NPec9-|x4l0%)dLpcOd zb%!WdqgjQl#Vg1+3Tbs&*uHV344b2?saq3I(+SRk$AX*NJT-p9;S}vc*D-5O=uK%- z2A2;}Nhw|+toxnYf%{DXMQDGex>|aL?o~#TD4J11M`*M|TjNYh@0(%sNUS^A0(Rq@ zX#&mRrh@06$q{|C$8Yd*Z?@F{URkor^=Gz z2@y4a3h|h0HwYNHy!>amxpz+;?J#sa?fd2YZ@(xCwNch&_&1jB#3S==q*V~ z$%@8Q8JVV4?HXVQXV{0h2nv$d_=)p)Q^6YVeZf+_UMVvW({o8@3s4-2>_newnB zPlzRc5kk@myOf#E_8U4hB2lYf{sr%pZuc*UavKY+8Urup*q&0Pvhkp?UZ%c?AcnQ! z7*fcIs#C|Z-4A6hXvtq77H4d^~c25hzraRHbNrJhbXZ=0z&r3}-0hZsTpH?ryWWvnj$EhLSN zpd=GwMwN{dDK&iv*D>sdVmZ7{`LYlNQJ0%ExRFeLdRxd;I-OfhLeqptkI1rl>d$GX zGpC=1hc6fSNIt~@!h#5c;xM+kek{TaOz`T3ayol@k=iJ^RZMkchsMqW0xCETgi!Ci z+R(OE6jf%Om@gFMU?_rZj!au_4|CCJWgCN{aH^381!io;8jO;f$hhc#I0^?3Yr+HI znl?LyMfuFieF$o!jAybEv%2DX?b`k`MV4laSjd@VC1Cklj^XM38B2(4vjF}DG({#} zamb`?7-$B#Lanu>H~L=k_+>E?=jlWsD_dXmV~om@7hUstWUQ9WYw4D z0-(|_)h`vKosDCbsV&Pu$#RV0qx?(Ag!6%theyYPzEG~&OyN64C>k=$6ViP(uWz;3 z!RWB?mHMm|G<}#W-)|V`n(W>DFebddS>9k46+%F&H<&tDHz}2eH3qe?9yAFcoG_6F zQ;(uvTLf_tJT11b05?^IF-7@M^V?c=A(8}K3cDh>c3~;Ir%+Xa-w0xE!wxs1p{Csk zY=9Xz%M~9mdA46VQcuke2|OTOXnQQ(%bUWX1GXx~9hONS2eNuf1D?AgcmORVbwc{E z$dF)iRu{9%`IZ4ATLhD873z;rAFg+aJM2E})%UJxd0M3`|518U!^GPHGZ82YPDE|C zGnGd8SuS=)jQL5!4NI~`8;ixEQbcAHBj8x->Rq1x9+)#H{^3af1IR03?bbjcHeC;B3?%Ne5Rj4KA0g>+R`jkyOF&$RpI< zY8QguKWDZfG=v9YqqK7@^TJ0T|D#6t()9Uw3#~ht(u)WVELjW0lab-+PK1Zp(`L+n8pcb zu#zctkzuAC8r(e;thd zdT%B@Se0McnZ!L8fWq|qpvz(_aR_EqNl7(LNKu(?mMM0XBG+h=*a85rW}e_1a7c&e^Gl z-eE8&iy;ZYX&FA*9Bqg*9kL17stIaAAzuh{Zq`khu!JoWywBGg`fGc zEiC#xJgN9&INDB>GQI!e#N|5ZRw5A^mKHD|8{P0K`0C@0+X5o;$f^$s@LbghGWW)M zXo~6(6V$Q%3{xen*ObFTcI&1>GhLubbU58^3)LS3)~8dLE01ZQ9CKW!6%nI$7%p3n!C-yg69W5?lvrAzJD6B+;|I z=1fqAqusEosio*-6Vxhk;b`<>(#kbhqDdihnTAv|-BU}*$eK1CD`qXE9w{WlRF%9UCv zJ!e`#0|e$;@xV7Dn(>$n^p`RwC-P|1(Z6;-*PXA+@;%|XElVV!>0^KXQpLt|;6W(0 zARFmplxVyORFB0$V?wqagR|-OV~_{AC=+}FZAGuvAympDVB|*1XekW|haNF@7rGgD}v61}1l#xO zmRP9VerwpS9rKK7Tz2+^Fa&LA4yE)hY}diuk4#P%4Ahzk0OrJv7P!ea43K8g?4FdW zn(~Vs@;@S?Pk6!Vm`#l+#NzA6ylGUvlh2**v16M8jLaO9#k5UFNuwzd=w%Y>9pC3P zIl&RNZpJpBspE`_4@_uH(IV0K`jXYx0pa4STwU6qUe>utHPY~n{G93!dOE-J)O=<* zdmC!@0O(%BPN5tm9R*Ze(u{H5GH~T#a1_MQaOMfWu+lyIgkRW-$q+O7_%Yj@4B-q< zv_o}D<^aZDbvb0I~SfX8np;?GmxRV1At<7yOkb zr--exg089|cV=rVa%hU3r;D%4KK+d#AF1Dn1-ey+^v48X75k2{F`0l7_4|HfqMkDr zCLy*k;c7Ddu|Ja~O?a%dpk}a*NV+Zg1YwZp|6_y`_dj4Y$B=<`>7QkNh`gfRFmwSH zF8GvE>M)RZM`oD2cW%n**K3_bRS{sp>~FGiC`vX!GFt||ey`4f5ThQb&foWKM!F^C zu{Mu?zKa$OJK%9FXfVAdrY;e(U;El*Re(n83JjsH zD0>lK-$+g@qL?B|juY+m;sr;Z-Hf{tH$E(oCzWt5uTpD$D|$#ur$oFb*t>u~Sb3F(xRcqrE%9pIQgRAz;Bs>$VRzbRMFJzgph2la_pa{*GyL%vzUbbVbkxP#I zT%pW{Cc2y9e?TqM?TYJq_#b|CAdTJfVQ}u{?|NIBo$$*RJSOZ$xdTNlc7HvSI|PMS zB<33@G0ig{uWaog{Ots=C_HVmU^VIM3mK{DPVc$ z4XWfD5-JDZdPD7d=0@JATci}0E&N?YLHY=H-Y72TY@FDD!X0WxF)A!$@YHP0lN|tK zN7!RH1u0t2Ya(D`1K!gW+B>{tq2t&}8#aave$%vVdiu`93uC>9Ht$5|chxDXFusf(bQ6KH? z@T5?ETg%Qrv79*OULzm+twKGuY^o&2n<#%gme`L?S`*Cefjwf}3#F2$z20P2(l*4| zaRY2`yrC$On>`uuk8NOv)0-7uwHO973GQrfXnJNP{B`;B!pmP%2^;W8h94w$ zVrJzzLNmC@;{6h>2py9ZTg2~=wCEO0rG99pH?`%38vFBXw3v~zE~=4SnrlFVxU*20 zDk1mIIS=Vhh|WGYwp{4AI+cEaX85TNJVOm5g`r2BgIL@#fcu{RPr_hl@!D-95}hV? z3Xc?SjMwQ*Ah@Pt-X9V%gC=}t=mNx?NdI+^`qkI5M1HhcSNQdDw!o_Q1g%+1P zAv7J}9F;Eo&nnU*(nEx`0jDfmi3sbt12{No3a4#C&OI|{&b@6!*>Q|6T2+~&bZV%7 zHz&)SE@4xYCGRdr_fEvKKNEx0`^i-%s6!hK1IXOTFys%aEZ<6ss@ zoyJ#_i=rP3-rvHZsSSyIA25_rvlznFDa@h}Y<;Tl%gajPf|Q<=sDyxk{qHQ3<%-_U zLgX755*MCoGn}Rp|Jo>SlQb0!y50KPCMQz??Im_4LlLfI>s;%f&H!hB+)0A|gF10m)GoF-6zopgRVarj#!2)9w{0L2a z(nMg1x{62G+XA0ulLYa$Fl>rMyrv8RFX{o@cX1pg73hXD_S-Wo%Me|f(baMViSu=s zD~n}axtb)<0;JN{-95y=rWETj^A_i1fPV6GoF+7|VvUIo88-lWS*qo5r!#XiWVfCx zGz!g0z{1-!xzKhPI!s;B1e-OxcRv-Am)D3d4+}kZArjZ->{V(9XqkNF-#$h=C-G_fZ|9h9sx5NqQ}f! zL~%(1xAU@xAbI6*k;xyr4Rrg%QoHXU9rLY}hGh~YjeM!dSL*{`aOW6Q`14Z(e z^fdQluaEgxQiuxL`zSP^8Y*;COh|Y!Yp1^?6h^>eBEq}hKivjP=ms)Y`HtsmE`ls}#Rd2!qf?n+;jr=CH>hhKwOO-ZvBlF3IsD$DewY)^%Z9PJu&T<* z#%QB`z^Pxv#rT%dWdCRDcd)CRP#x*QWt_To_iKFnXS>sN73MF&v0rLy>yau#tRQJH zrzx^TW*NvNeblFsM{>k0(ZIhq?fNB^-olqosxDlS|W7EU3hV-^tN`n)TSUj4^) z;&wewcRKh8JsLWJW@5jzujqfl`%8tL+az&FBcjICn5!l(K3^m$n18<8;nHgCF7xkX z1|!6_x?5ol*FBG!6m8`(60MxS0#DS#Gt9P5bh`J>c9G+`$z^NW;xI}_1kFy8|HYXM zaj6T@ND_~+|1f|(Du(&y;TX@1i@(J5QN!#XB(n!rB@5q7J75ee$_0yj<--pV)4VB| zcSb8Mqd}5Jc(4qfofc#yrpfpD_O1Y_8X{Qqu-5D<0zW7 z2|0%@L-icyPW}vLhQyLMoyU}$p8Mh76@Q9{y27>D^@0|(4LhSVTY{fkmx|7Fy!`Y| zvDqq9MVtp!f$OLJ;R8||>4z#~{mo?o{T5jEI*V?dhYt}Yl{o5$d`%rWV?YcRW|2i9V zAyf~Ea)?a%*fx8ZI%@DYF<><|9dp(*18s;iL#I_=upz;4xiFxzm=IOCw;=<|VP^Y< z>7vXK*tM9t+vbvj6q_8t@}Rv`#&fJ@_vOW)Uvl}ZHK}3yfMgugdD!oI-~kmH?I_D2 zlLpXIvgg`=FTak?9JSG$_D?|$MATaOno>(Rzjj>txM%v~p*^FDrVC=J=_!^yprm(6 z@c1a+CT|gp#%TC6x;0og z`gep{vqNl+bqZMEz=HLrO%~InC9=6CvR$AY6INvPqA2=L%C5h1kl!KGAd)0-s}eiY zZfMLFOo0NaNF+ z69EjR@AAad+Z*;m%<`3(G}%{6PKnja>m&z#OcbVgwN7l1tFUp~2$bt^EL*h|)CP|o zBN09#A@{d5`4LXRnkd@N&NJ#nZ!qkjp_`y7LllS4Ht(d^QbgA0L^bw}(ScW<=~~B^9|UGup(LcnwqZ-8eDkA3lqLFE$EA<_moe_;a8O~+0i3i@_#`+X(n%)+HnlMk>TN|JS0};)y?<$ zo39_E&&O--jH4T5V>OPSGlh%@D#J}>4BXz?Ey3JvMc4|HW`v-|%VbErI4D%WEaNs& zW^EDfU1J_fzz|Kqf@F(pNl}z;?FUh#`m{)s4^s`LHeMhh-8NR(B9IE;QR8I;$AjN~ z$z3Y@Rm=4E!av5{gMmk{`MvCnU(o8^>q?E-<(t3$eS;(8LD$Q_@1VEZO#3LWxksQ{ zfb04UZk5`~AbhqBp4`MQZFbp4u8*dY5GJW4wu3AgnG9J}j7A9Vw()Ei;+QQekzkd) zY(p||g+(t&674*XpG%(Xb|l1csY!jJ4sprw9jG!Z$$x{TIHevRM_E`KoefrhZdvzE zpoH~%J?SORyV$#<-xJ<{H%(7%dvZ8NxIj3^1c4EKQ~uDpeOS$mjNr=)IgFlckB6Hg z!L4vnOcAHt$Q=^O#KdU&WM?v5k&e|r=JZm`t1owy#2$#3-S5S)Bm<0q0@>#cwH;8U z{cdffG?)e8I-X@lf&XQy+xa*DH+b`5ysus_%KUaYdkXL~(p%1Dy~^lb>shFgZT~D? z`lKM&3Q#ro!{*REn(GDDu2<-d0Donm%Uf~}|EkFXaP*t6PLS^D)L$|6(Z(bRW6C-z zIZDlnF(KSbnYI#3@VcCS@WYzMQ`P~oN#y{s>bHBA$-=XJ+ossO3lXt!Mu6`gl8BEK zT~yx=`*S&dNZW_gOm(J$UVekfpeyeqUW3Pu<@eLtkJGPk6zBtj&KZ*r5O<^G9gFSV)#9wmkl$DxgmZ2UhhgpzZ-NWLp8A<1)b0@LZv!R4&So4F zoX0ROldXNE3kTUg#2<8u3tc2cv!U|PzKglU>YjYvL@5T@f-vq@FeUl(dQ>pRoits+Zr9MWb1~SYd|h z2iAZo95|MorN4Htq>4kL7d9_F(uNbhJyacLW4^%q7jH>PcJ#C{k-q_xHtH`|MQ&jXI0xvbpqY6&uHf_v#aL!jw<_r ze5<^uO}P`^vv|&!NRqxh+<<8EMng4fdRN|frKP-5i8?3b)rP~+5Xz(Gj9vu&LL{6N zZQ?m^E^9($mRjuB-|S-1stIj8BYh}EE%@;4DD0dMzi;5S8*9h-cL9FWXYNTl{|z6V zdsY7Xqb+CB)YznRLl=?<)+PhVx;8dun5d;inr-+m72OGjMs`2A0;UGb)1TfEK0TlN z8{7%aAAND#BW3T!I!>@6Ygsb?(FK|9_#swC^O*W9e57&W%Ehv_pWO1nGiC=&4Vhm1 zMX1d)MO%wN-}C=XsQ#}Sdp`c(`4@)x=V^cn6h3|%`tA!VaDIKhGShtbz_A%Z$y8- zqMV=4)9#NcaJ;QzE!*dr1WDug)I-v;hYcgHO2(TRT;GfmYTAUuNlYT~5QN->>ObfW zSAC>7+52NN{DNy|FGE_QOXZR5f<9WpRBIo?Z6?v2w@*^}&;ev&AoQs_Q;(p;?lxRc z_n$s`$K&{OePbJK{F+hf1;p^TqKOtAaCJO?cCM0EJ>si+3XNC2_8uf!1QV@CZ<=-Mg?X$#Zk@D%itK$f-~>?i#T0?DIYQ-`I44L zKMoJy2x!KA>m4IL&gyy2TJ{on>lb|c0sx4f$^7=eVAwCF18jKj285O)_=8fcdDLPI z<4zze!dJ!))I}wF5`0(qoCk$kp+Lg<3mXGa*Y54BV-3RF-rfxolJ~na#8G(%T-F`u z3d+5li6@B&kQTQe)ksyu%7tbdeiIk=eOq2dhb_kg8(kD#4{k8%pw%WLuNjH^!$8p>>3q9i-8u;Jce6#B9RM z8`ls_X*@M^4tDuKg>S!ahTXreE7_wgZP^N%mnadNW7-V7(pkZ6Z0;7M4b>o^gV<%A z?G#ifd~DMdW>E5sc!0_4&l7(sOSluFpe;Be8*J0z8{0syHlyJXg$vsi!6C=nxboRU zJ>*jbNyj_P344=0Ohkh$BjJLAjGX!%Y~a32R@yuqkW(?;0{PB4NaUxU)eI!h>LE1S z8z$1|y#i(I!H&CSULHVk?k_?HbV8p=`tD1D%JkENLLHo4JIJ7rG9sg12PWY1u+=#ePs{8N6-pHV5^G#^u=~|Mp`PDlZ{=tdWK;D)dy~B^P2Y z57ubTB^QDdu)3jM&dIfAqG|n)58t9Yt4dri%X!w6KiPIKpqqCSKF)W#`|+vA{SN`6 z1Afn@`&@*iCLV=~>zzpDU;V42wm-bp`yJ}ZT671vc&MQ28bNpGYv*6+Y&AS3@TFIa zc6TsT!Mp2|6uQexRD)-|_cdI7xdApHu693Pzd2jKOW-p^2~IYXfe>#1yQ~r?hb*nJ zKxG&M0#2zMcD?KXjn{E**zwg+${Q3VxIetyBECtWxQWt<%B_BQM&^cdcLN(|K^jQcLCv>prd`O9i#^Nb5}(5{<-@4Shjv!NsD>m^LD7awb@CVl3d>9 z0ma1`fCk494~7f>3mlq=T;JKgE#1FwC!gA>9od@{yxzkJRW5-t{1>K_tz0auGh-rR z;BL1P1Oz&YGRSMOFD#OvdhuS(?N_)ZIE3B9z5IBg2e0sG-)XLMzxelzds)}{fm?#e z=Pm(7ZXeVXUi#k&_*J?4YNdC6J}&b=`u#q%=(>LHd3&H*ZyJmJ`8ZqHMjFl4et$Li zMh(nSI;i9!ru`UO{YI8z>^2S-l(eR9j3qx&Zh(O`Vdv8(__2ne{{sKRXWe;g$lU5F z57_qW6#nimePW*xqB1;-<0tNQFpnfSS{8~0n%d2@o-BDS(h_(Y5olpxLAB=B4-gvG z)9g0czmB>huEv90!dNuOsfROO+i1L~t+Ra44vN^1cf17%Uc;7Hoo+Hy%dFp{$39^$ zzH@44LfYE~Y6Z7jI&Ts|C=EzMslbFH&cSM13WJNX>ZJK@8NKxQUbAjGzDs0@ zJa0o4ysv6=NSNUn*`n|OVF1?3Xr*#fOh^AV|DMPLy^9eq@9a0mYirYnCDJ|iF|QD6 zZ(9XJ z2xN}=I(|T_y!jOu|4j0`Rrrc7dw=;hzEXByKzpiLyVHTRzutff2$pzz^VUlJebn|Z z2Xq(pWz+cY1hk*_fi}uL!J9w1kIX-QZ^8;*F!Yphh@PMP9%@FK?XQ{zh*<%S1=?=N z8R^zGiM~6cGUoPBRdcMs3!CWO6&vt(zPwooe(qTC$@$f@eA!g|G7YUAXY$m)bBvuPN7{8dA^PHDOr z!S2~|^O6E55z86?W@069O(6grT6o0Y;L`J5a0hHzJCGc%7GWDzRQ*)BG!m>I}C^b3t~r){FJZb({+vC z#SC~}w0SvXeD--iaOwCMxpW_5EWd4AdI;S+Zm+r8ptXkS*lRu>JT1#-DEB95LF1av z`-Qewf6>-%ZWsiQqC9xi?N&kThv|y{akBLuC2-sImJ+gc$Apx?+u5Xs?UJ&cBUFl; zOuNnfFXz(sVZcn86U2!lo}1%+#{=-3ZS&grIRwOhCV|O9RH~FdnVOy2Ox*>cnf2uJ*>n%Y4-DK9hQRKGYJwN^VZ$TnNnrsKVQOVPVf>E< z3Pq2N3>8^*Rni-a4!4jS6VZz{*&%I%sNBI~G1c-G+Lq0QH$hCgndcccZu{?5Zx&3cXnN@by}qs`sNs^Q9y!hG~4Zcf!V)kn$SRUZLAp4 z*Q!{h-SP6!)WwHW<~sSsu-9#4X#Z@jJUTi8&V(fI6MEU^%T?A)`>m>amq$14HO!&i z_L^<=p_!SsM8J?z+5UzHY0~4S0e|*Tzfe+lGBSfm0Kz^}{vqEwu~$V7XDoQ7uQ0qL z1b7_QZ~ltL$@Hx2ZdUIHGl8)b$tu_Gumn|5RjiH$7GlK+ICs@hW@;8kU1}&dK)=ZYExt%M}xw|K)4qz{xw)D~~QbA{cKvikLR(bMq z*W|yLvo4-s8Y5tpt*JYShx zXkM>vXz%SW_B7wyRi8?gHXi}f*Z%GcKP+$~_Aw0H-!&n(1#5oTa{iv%w>_F&*-&m; zsBvZ>9BKfu7yu%NJ4HzL4{=LD6gs3te}si>6$+`%=9glQ~>$JWL%JlBf% zUN3LFwjx=cV)~c#){qjd#cMY0*4e^#ZJq_i)Dt8X*AqmG;U*gSk^Whh0Ufh|L^6PN zwou4(lapNVm(_i$s;uT>m5F?YabV_l4r$rMoe4I zR294bmCHt5KVrUF@p!EF7qfKEz;oaHM8DCpF+#6pBH1bn(gZ!bQMcpXx}zd#4M>@N zU!QtkAJh4`fd)#0FL4Z%3{Q3fBVRI2)&tmH0=!H}y1%Y%eKhF2HXsYUT>;VULy*N@ zlSiJD*q%Mu?T5fm0pqo1##P?;WyJ2sIkF%7vZ4pc9Iu>>0f!!5-uaKhDrdi-=g|M* z3Uakc5q20T5tT$Nv(r`mQY>0z!dMurLKZ7wW^ItMeKyPFw8l9b&w*RbHrT84ug9Z> z@#!S7U6YxZb{6UDD_|iTUDZSWR$5_MFcOX!PPV5Bno7g68uF)+C#*#v=j{1eu&Xfn zv?GWuL*BXlZYt-FsTbo`j&YMxpA1hA5q(AydaK#2mh3fRmV~@F!(N^KyNz5)=}RPg zG7YeBi?ST?Fjt(zxnXm!RM+Cv%wAsQ>A?jq-yJ#6XgU@SHc82VW{*Sv#r~+3OTH=L z;fJVc@9Ilc-T3vEM~fB+t=!310D1FikfZaifbqT1=A}>^dCAEOsK0K$sLDE5kUF-X z?~gvqAzrE$7e(HuMgJdU1~Rir$TE^T&W*nE&f35fH1K?WU*55O`jXO&FS%dW3T?L9 z;WRIbWj37!M@pjnL}fuj7IArpl(Dv2fdsg}_I4Sh4q*_dY_HU>9h`ytZ9nrtEHoi& zv?VLdZy7d5y>@O8i-v=kS#7u>%S(#Oa8pkytf_du*$7u+;-F~YijBF-DxN#jM)}D8 z6&b%hLnvfO*J|=i;$zZo{-kUw#g}Qo|KS~-yqhC$^DUjU#Tl?Q9Oquu6UZ!z$>6U} zRSr^IZ}yXWGZ|b@dSM};@028i2z#=+mW-lddwT-B8s-}~RA@MtxQ6L?jtr7C@4#U! z8s0Zw^wy2oXA*1T?(hSztw%55Hdo;K3m^Vpt5m#l%3FEBFpIkS1Mu=zN&`7rrB&q`U*d4l)ZiGHsUa6TAK$T@9o z7tbC^we+V{MK|A-5XY$Hf-YGPG@SYA?!I2+=?blpMz!TzN)}WN-|TERSCD?fqOSLN z+*rGYl&kLGT&=Xz?<`shbkqcHI)&>buDvo$nirW+Gj{Y1Gs`BXX^s25ZwHNbZ}y!r zZXbE`Fz8z9$25u_U(hD@Z7KgY=#(=nr-~k#8T;EK?2t_4aGi$z6o9za^f!f^ID*D z0bTn#{3|tGwY)Xw!BJ=Gk?06qje%h9|GoP2P~A4*D)h||Ls+FlqUr$BfxjAjNs=@h z!=YM-n2WEv*r~qJLI>P<7uFZcWge?(p6pTALHKWWX;n26mPP}b&#QfjX~uq$V? zrLq!e5h<-jZa7q5abX|YEuz+|Vy#o5!?LLb;M~O$Y5yL9NjHuv0*33~el+lonhlIy zc5iIKKVD)Ig1g4kmX@F^>&;8l2U*dHP;Z*=J*b3wrCXrPq=DQ86GgiGkf&bfnnfC` zk>^5O6^xaUyE|T^q>#=9FSHh-aGpt5(D@GL1!K$Nr7tYpCGjmcjjA7CnwDp)Y{O^m zYfuL4y}i99#sl3l$vMvXc+W8W?>qLCbQf#sNTZ@<`otdl;-*s%X}wy>GGQxR9J_gh z7j{q0|D_$sMZX9)^Z~C6MfJa+%uB^MJ$HAE8ogz%^y!l!#Nx2jx>VREY8qR>9_q+E)E&_)8!D_Dt&vPsZF zWYqG8uI+s-?S1H_*Z>W*X|5LF)D+}sgC@dN|6~35v11iPMW?}B7->x#MzWfe*OW7z5!K*h`y}R<)B*+v5eFi^ zN^8`8gw1U*%Zq6f`qK_@sc&Ip)VY6MN6(s<_}f>F%<%sz*)7uBIKycR@=mlRxM9a` zU{sgO^s7E-b?QwrZWuM`V%B|z4n2D3QyIEh6yt}l3KexXLt=9b%_dxRv&JQ) zwy^1{vmc!75@VoZ|F^W}v_gv}^#_xMgXQz3V0Uae$4^m?XQ;mU94Il}$7%Yo!5$ht z9^RLc0&z?>yI0&MsK>W|cG@?hS?yyP zO@MJX+R5C$f&-hILr8>qWpdemSvj>R-9RkMwqCnPWbj&UDIaSCBiL!Z$Fs7_O?}Rj zJ!Pl@47l@hy}_a^iPvI~Hxn0z=K*fU!RFVk0im?X3!247|E zesetg{^|imrmf8&v_>S(sLS~{Rg#=Yo>{A|H!>YSjcjc{>c}ZNZAwq2nhVZPdT8M^ zMB}%@9NlkA8YvoJldGFuj|WSVafk_50oTy1Hf_`9U*ixk&C&vau328%RCg$9@{Eu1 zve@7dLhr(;3(I7#pS9crxQhauPqa(;t{Vz!iDZgD0k~nH+t_T)tBUa?gD_RYukc*7 zLCQNo&=1y}bKG5XGURw+3maof#qZ{8*S;0E#-K&He?WH2_Y__HJ3EVVv}sd;Bqv<6 zYAd&mR@;a5MZhTIu^u$vV9Uo-^&-_BrE>6ix*2Qou^}$jLSX;loP=Gp+8x{vi-Wn< zu!^9*2+9W|wut#1tuIsSmaqKoPrsWk7E8X+aoQL0y_XmFH^Db>e)7e#C%Q&nZt}WI zv3iQty*PyC0vM@@-UUPpAB1W^v&c-}EWM~iHSer57*)V;`RBUJPiefk5Zja2B6$JEPJQhgaMgp{@TSn>D}cfc zMFFMspp8)?H5rzEvFH|CJYhcWJr-?i?4D?jq24r~`5;32?EG#ja|}hDUI>`Y9Se7^ zD3~!+BzKVMpasE_2<;{OU-E^a)i*ADMq7%m0#Nq%sWyJ{^m02Hbh#|ua?Bb^u;l7@ z1h7<)#)5df?}Ux(1HM7A2MJ}S+Vg{a_w5ubE;|W>Td5OHq?CBHPr^-zlBB~yNtA^r1%HTPwHN8)?fNp=D`c-JPXf*R3w&9ge z!pGMFZ0+ub^5AcN0nCAV9(nE5wCx@L;D|Uy?vVOh_{3d6b|QWj7i6o<+@Ema)w( zt;E>qxZ+`?iZVk4JN^+XSBvU2Zm(>y%a=fECnORZ40hp_{>GcuTUHt@Bvjv+qmOlO7S){(rn zdB&_d4|ymBj=pmA@aNvf&Y@+R%#)%mxS#)K=y0-sS|D1=svXd~xc0`L-jF9B!Hir% zN<}k)!q0D?EwX&;gDV$`hOzJubb<_Y64cQRwm!Bh-szJ{`(-a1lY4=SFt+A-C zAj+gmE!B&oe^h-%POw|y;2qcX)T&ZviK-W+eA#nZ&p)*J1#RM>HczEGmZruZjXDlz zqPNm`-4*E8cV-y;+MT+Mn?BCdgdRVPi-`S3A7Xwh|AWB{oQdMi?Zu(3CZDJHTS66~ zLqnDt+Ljkl;G(L^DEjRg1{QAaeY=8t5!WjSe-U%DraY!P(|`|p4N5g57KhCBkuWrT z#3e35ZYZ9XGH36u;nJhH1*w2-sO%y1F2wvNNlxOv zD~(va^wM`DT+VXhys? z3{QtU=*LY`QYa#RCY(}0b32d(srUpWqt%b*kcm?(?0vtyN9*QvZ|;H$`Bsi7Q;xoW zECzFYq-x`f?*2>L7yB7=Yu7O85cBu=8BtAdZgyQSR^)7S1*9tB;tYjLDtRuG1B@w} z$W*lyMw=RO~#*bWrFUq|t?vltlm&B!%NB7$C4{ml}1$2Z|-5MC?)degogc z=F|k=2%Qm%)~!8!cr8~Ejco9iT{>*_t7|~d?+VGJR;AMe9dwgakg(HuHCfTMWYZvP zVL>Eqzuwiwu>e0SAPTTBmCQQO)aYs~ftn^y+d=%R;P!hC)(?uG0u6#~4vB5J)!6`V zuY3HB4xYBTi~}dS$IggqtZf*bg6SY4KatY}2o=UH7n^s<3`JkNU%aiFrTzS7QNtPw>Q7V$~UXJCs_ z{Yq_AI)~NzsTF2ry`&1g`;jccrwy3GnM7x_)6TbZqKlH2tmOKaBRgJFG)7#Rh7~kG z_Z7-psCQJOu_TU1@tRRLSndd|t_@^TKV22mrgAOBh1JDX)aDKV5ZC4zTV!htfzj0WYxga|X1X}b#=o=I zSb}h994g2&XU`RhbJ3xkLpPvL=;1oDQBlu@;4b%_ z2fn)dmN)YtmJ*27(g>ASKZ~t*`IqUVO!7D4Mde}V(X5kIt=h~5N$*c=BMisK z?Y*=|N7wgN#a1 zY|J@FYa>nDhs1uzqq*Ay>&tDH%b;okrb=`hbZ~d}O1cE`o}xc`?Cj)?JpHRcwrM^6 z;H@$LsdX|vrZ^`zm>KpHJZlX%9BPKy;VM?$F^x3Lrn$Xb(TEYlWhZ4X3o1_>A!!0v zk??=jTgTq#TATC>EJVHs_Kf4FrFIl4P)L5oE~YDlLQbh?e`>o_>#YU>S>&Lr8AM6F zW#dYsG_m~tt65P+%-AyE-;_@_PrcXtmV)SRgbYKkKicl*XiITT3wp^{%oLsU-jxLx zUC+E0!^4$_YRNZXb?eiaWalFFlc`BjhYS4GI9!8NWV&^KAqPC9#^YHl=3VnWc#hWk z0$^|alu>gYP(m3{P!z1>pUiOez9|D0^qiE4j1TakhptIK(LxO> zHR&&jL=RG)$rt+G)iv*yG|-5%-60poAs3gdr2*xtGQA|1k~Vi0odv?qQS6Z%C2u5p zRA;{-0(Q8Y}+R{yzz}607h#gSc*_8wNq>90sMVl~d`KzDrLctD?DiHHX4m*$-ayr9N`e^B>}#u?R|oG_5fZUk=}DeI(l^ z-#Jx{l7kVm$(ChTKr0{|82Jzl8o72RsO`u+=i#aDo?`6{$CD#d32{PD1BY*E4cTMW z3LP}VDr?xDLF~6#I{-kI!~A-wdCY6`-~jeK%AOQUX#sF$jhHZ1*ryQwU?$j5&m)yO z;#NFxZBLNXSsh(xa_xM4;tx#5b4-{>-4ar;E_o|EkPpjgYQWWEGRIc494$A`R;8#7o|QrEq2v_SGc-K zP(rxe99`|qL&7Am{Ah;&a)ktPN);YbLvGN=)?4Ov7H!Voy!5RoRNmpK5-Kh-ArGE% zWQQ8DVuMuNyquIfsq&x8s{JDvR!`@yYu}QC+hYP?TGFXls(>uW1p_oohLj8W%|A3J zt9S8Wxs?CjP^9SS7&40LRAtXA@@@m3!SSx<-^!Yu4UgKN>N*K6CbzOD#ec-MbbD`W zrd1oSy3zVPmU!K^ewDLCnG86rm&_JjHV>$Y3z7mGCa;8zTO|7S??hzjN~F*YXIp_qBi!N$n%i79$A8rM5~A%%5pKL7`BI}1gfxjYLy zQZW$nE){^XKEjQeHVW6IknEl^Q`JNy;BJCN$ryAa!|>Cjl=vbb+3H^M7*Eib{F5&`HMLR_r^={{)un3)XHfA+nwc6sB8H^e%8S?96n*)C$?qe=1Q{_+9-%LeHqYHRlx2r--iLG3G-!7j0+6W>^pZj zr?9FsX_8{ZyL3HdvUdnieQjz9Xsu%eY9tf>k#d{)mGZY+ZeKbGqTPV&@&0&op(M0g z$YLR9VJ3sr?h2{G?Wg(Q_L|+h_ZIe1u~pyi0+#82laT*;1tuh25oRd~qPjzBqJW#! zI%86qQU**Pzc&5G9ent!#;9R5{g_h9qKtR)_mZqU;>22T+=#GG)L1PR@LFvCOJi=L zR_L7HfOx6K{5s*vvMt;|ME{A2W6y;rWG1t{%}+r@wPN|@ z?g;c_JhAx4i0SD1l6kpFW$O3T@z@!W|#R09ouN2D2x=6CxW` zG&r|!qt|EOuS18Wg5t1)JXp-*1|h8+DteqHhRtmprJfj?*9TGq{;fxKxzkJT`9Gyw zouh~1U^-ua?*OVm>}v5l%%QV)*SxkMBq=210U^`s+#GhKM$XOlqKVjg@(Pf1J&V`K zx#H5_7lUeIr;}O=|5JvglL?z7hn)TZNsl^kOn0U`<06!NF9V1HGblq%bAmf zyUQ9&Qk_2Z=pAsm!^z_1PQzoYU$GLVY%A_*gj`Ucd1L8E$H?*w374@hh#D%;(%XeY zVGtS_isI27w9fAfmO;~FhV4K|rvOesWLkF7Ek~)CC~q3cHil#iC9?^qvp-;ZL}&=a zPPDnpIW<9^nJQ*|li%S=#d}dz-9TMid|a6|`Q?7&T3Mkc4pm|d6}ywv4@Sd^T{Z{( z(y@I<73c!wK4M+hE0-v&{>qD)CuAtltxh8A>@Bm~%<^Br3Qy1fU7X{Pgbj`)N3w+Q zTOY0{H%vORaf6eVqL&5NF}Gi?ye|XTmm7-^oJa*0%V5;oQbn|o1T(%0t=x*Ddf{RB zz_r1jzgpyNz_#3;gL$N&c5?8qT1ifiy`D-&;XFB0?`l1KxzuZ15?Pup94bN-)0LcR zdY(#M6E_t~_t}rPo6>hX2hRmhCLLbsSfTyrwi^)&Sr7nZo~M0Ijop}7fRVNB!HU~o!z6hUY6dDl0YuJsBuVLKqGG?_1Pvd3u^h(Xs|}TCm{5(G zwJELjzz2|_MGWh<)X?i4ZXblnMjSjjjC8Suk(gyjjiCTYh!O&F{@5PT$ttN;%Ds*r z@gC-=`PfLB!pdLE!Ga~4>m(Osy&HYce#@MB@l_r)7BGdWZQ(l}@T$(O-}ch+f6vMw zkYbqD3C)`7<$`sZpZ#kwz<`38%apjKRv7q>-8&3rd^oDmO~Z*ZV|fQYy}@HsHkyC!yJPNdMaKr~FzCp+|NbW` z{SV3fYi^XxqYnU0g_Ur1RsnL_FzP+A8u$eg>>NZ zxzuC2pt9_2kf9PZ!vX(D=VrX?#1@+>mcpvm8De@gjuN2)ympM8$}UG|^-ph9`oc|ZJy=yw z=F3Bz9i|eZXg!}&tld^v=5v%fKpzNp;v}je*n=AmJ$UqDCvAWzH4Tl|aYt5qy%IK3 z&CPioX?+e;ebJ98*sm71g+l61uN%qXeYGOwLPj__Y|K(OXuJ2csqzU}rV&L|zTg#O zIwXJ?`4fvxqWWa7o&%>B2|94CmB6WV(aTYS+-O)mlZ{)Q%4fwh+u@%_|IKjbs-}NP z)=4%bMks*3wk?;NsQI3r;=Z5S%y-|Ya)<~HTUD<>Eik&k7?!>oJHUA!jk|iL0|M+U6k@sKRUxQeB{FBIW%+DPV8#1{ zGfyAQ;mRWsK+p5s{M_8%`9|68^I)Ra`&C~__>_r(axDX*;ripRfx~=qQfk;j|3tqi zN+ax*Vp4PkQqD5IfetnemlA;0J{vuBIpcKLb>nPgRo9dU?d;0%AdU`JzDD>u24Dm~NGR-cmoW_RzF{UuVyP}_a9fq<#Y{-ufsjlp>9ftPNLB7+AeZdnVrLL?D8NX4p}9{H{Iy) zP3ZhdyOhuqLG~=GG+sgG*!V<|clvT6_ML@cf30O$i<=GRh?_@da%MI2Z(ph}_&G@V zh=$s=@-_A1%|Bff4qcFFREm;{UxR#_-`!Q{h9JsBc)I#>jS{Ke2B#s}yZg+7K&FTN znL_DgXL4*P|TFqn;FWQI~sifF0!D44ZiMz56*fm{S3DAS|GgUcAN8x3!Ei1LGj<_20HCk0#p7~g12l%M zZgI6(MnZjwoye*}dd_jD;jC4XY(?GTqJw26>3cL(I~@Qyy>w5utsl&e<4?NrwKDin zbwGs|P6KkeAy2nZ#oqEq3xv5T&uU@Nv4I_$A?t2N!sh&8^4Y5pXB|ME%v!`MX3aYq<31FzAW zWI2V!V@*TNN>6}%`k)Fe-P+J}kaZi_I!rfw&R{T#0Th%Bdegs`oLN!3{eWU})S_f3 z(mmnBN9;y}^Ptd1OCAX8PT|Y+g9k7=R@SfU|O-SY;+tCbbH90S< zd9417f>otx@0pY#C2)up;SajY`RoY&Emg&3{=)BZ2 zzSbV`9&rH~bnspG8eQz#XnIL09Y9y?OZ(Joy9wW!+LwE$69}Y>$oHtvwU>whIjKelT6=j`rR7c ze>czl)U)%_YH{MEC8e=qmilEUtafS6O=_tH)HccaSZ64{VdhtqHnze|Z)>-5eItmf zEw{H4KIY1dM?dnt=TR8f;aX-x$Z9`t@`t-(rv+Zj>|Pm~R08jT_NeQe5Tchr*{47t zP3H0o%m<95bbTP&xb|&5^Y|RCHdu7Mly$uT^FsSpHXdtIIxn+8-q425$AQiV5DG#2 zHR|p_OV7`;FT>Ov+ZW~GZ6xb$1ZZcQ^13h6c?W_5(SG`FNb}PHZkaN|`Ttm2(dcp$ zf3M0&0n;3QclPUZ{=isRw~Q#o`H=Of^N;;OrXx$i+(nIRAkQ7|T$?$(%#s<0O21of zsA;+*CFhC7i_T3F{P_dYFQ|qkmcGrs_5>VL4TLE>;4i)|V!HXTH0!QV3>R8qU`#l! zBNyW=HO0m$Y?J$q1VcS|;We!TcGfx@e(5h+)CSF;^~??B#k5LYF8%VQ;WaSgVEbmW zdl1ErWj&^`a*{8$XjTKk$RUGr%r z7Be8#$mhi&>s6EWHQ44U7>I(&_yjt{`=Vc)qdkD|(9LHc9_D4C>fv0fL6oaX z^0UJI^q2q>rmM(>C3|VqpkPTr*4l?BI&f~$R!|%I2%g)|w9xzbIb42G5@NPNbK zP(vVLxoFs3LND|%irQPT;~(e2DJI)LbTo= zH`8RENArF#c!~g&ADTA!+HKqa{=4GaCu%ye_aME9&wAT0;=eDs<*hnxTh=)4W+yln>{cV7Rsfk2^npTGjmrn7d691u|B$TJnZ;#4)$-E4k;8N34R{)M9e zh7y*uFpQ~Qsmi{5(`z*vY=UPwO2qr4zGRb1pLWkMc_bx0l*@*oDHfloJHW zm%rzzdBo&7|Aopk@$`>T91LjcwnBUKIz>D>|3$jGls)&khR6frMk7?9DF)xfhbYWg z{zUcJUmdsozliq0zFt)IV1eHbi$yBbrAhfXZ`sNK2lRKr7i#Of9!ROg?)ON zCLw-{!${Xdi)u7S+XjU-^<%lJ7EB^keUlh{NzX20e2*zp16svfdtJs)y(xoIr{4Z$S& z2%tZgDz!Y$G`3nR&wwW2hrMf8pno+w1ek`Q;{CXe_5q^rph%b)fc*wc;bF2~rwSgI z0-w`US$oIFNe=Ok&SB!OAOzuA+-32*An6H^ioB#hE4a;Ts+N9L-ju0&Jr{&*zFqM| zA(wtcQwVvloQy$eo z4sv#$Osi?3I2PWi>*Scj$cY_=y!YZ|V|KQSOz3kk$f%=sZN1Gs?S~(H7L5OkgMcbs zmJ^NNfD1#-1uC7?DP`u{iZgA%TwfI8JoRlmh*-BDxh=TrAWrSU+eA0{SL%hR<@)O@ z^A6^sR{345s>fMI_iU_bAlcDf^!7o_c~?s zOd<}sY-f1gH+4K)bv3s?Bg};x4Apc_ylC)1`>$CxAm*xt=zwn`dTjB;xdQ#}w7c1| z&;Mkfffu*~j;`kkpbvKIG5TXhz#ZU_g@51KaYd7DrG_QZ;R52Zqhvu(MEH2OsbTRS z5cCVTO69#v1?c+xAbyV}ejnd@P09Lf$$Cs|>L`$&`zC34mA+9$RM?q4Y z5BG;C+m5NY`38145+Y9 zSN)M+h(E)A=pQ3VQKoLB)C7ns4)FdYYb@11AJu`3?R>cRE8^X;_*hH=W;U$%r!~xE z4=`h0QvBDD`rj*8&OpzySCY%&LlPIF2x$X-%a$rTPXsznJU*9}bUe#=^jZi(&%RUy zC@(NB05rW@e3@uH&xgFvBed^wflyAj{n*&`SRmaK$jfH0qgAPlX}8-ObiI4IKLajd znH~V#OM=w$BHjb)FJRct7ybDQ66Vr*$n*J*|Iz2-^Lj?){#Z3l(w`1e^#CJF10hZn z3?{#Zrhg*MF-ZefJAZocnQy;vC*K;uE^9noZ-5&40Kk6-&wK(ExbpFwV(h%74_O3u zmqSTxDqGMVTV_sgUjLE*c6hYZqPGLt&m6wB(GihympV1%8lNtDh}yfs_1S*RB3`=uNZNXTs-u;9 zWavH49`j_)gcTHmz!AKN;Y1MxpS1;{^hZQzNB{e?Pw|IeK2FlFwLwqLvG1a)zDnvK zu(Xz5`2siNpF7cSpW2U?-p_!ySo4#{3Fu3~JwZP`%-Q%WCKSFN@Plf=c71Ir=? z=5hlkY7e1O^6ZKb>IePAhH2P<8SzzD$A?&^YjZ6D zF%}VMt1Wo5OgeZ5=Z|y_0$3YWW4hnD+;aydEHx#yz3_O*05bTC<;Q~Yag}Y}Bkcpj z(@!YRC!i**JmdIi`kXq;f?5CGM>mykQS9W>g)(U#Q7JkrQy*Lw%-TyyfLDn_*^88n z_*dgE#Z?bJcMTX>R4}CN5SJ~06S{pbo$~{3^SPGs<6Yp6@v}?d@#@p9yIx<-7Gu4p zQdOmV)C{ysk0lIqOovIF0CwB4waR2W<0;?7bJpg{;Ir*3Lw8YdN)bIo?pvl(MT8Xc z#r^(V`h3xmox?DH`cJE-ZM_|S?HZ^?On8AM4X%T%-dE5*zyo>(FAVn?%+U@kp7`2< zeJ2yZk^lhJ9PoNAjLgSo=RTW2#n;|BHq+4_-mlb0k1yjOlq-fLD)m`Z&y~z8B2#Bz zJcwX24T04>rNr!Ob{FL0a_g!VRA9@nd^68RJPn!?rbdbbb#N8lwG=beKJ(j<) zEzNJ1aR4QKlft4xj>jfNi4)>607zN|P4vZ8g@jh_BZ$qeM&X}&B#sWDRhjG_YIq2& zvp70yWy!~1RO^*Z=7e{6jwc+3H4O%KLgk=V?1bx4TK2BwrzFFqVfqG1V10uWf?`!e zvQWy0WI(P+kpNiM_suUEI|C&^=j-5}Nn@o^4;-)_gQxrSG=m5$j)(@Ol~ob#7g9Y4 z=$6Ye4zFhN9=9$9TBKn;Ocmvbt`QXO!O3Dbc-7;8Q`zaWRmVDmFXqbnlGnykkn8Da z0xdHC)ArYIe0S5rjBX=RAfCV$j%Oe?yvS=}$#Wv>MZxFvKeXHvF#qK?<*^A|vWLKc z4H37%3I5-XaRC@ZO7a{@dfNx)kiOpP(@W*qd-<`^g`a>h$g+x{VZkP}Em=9p9Kv_v zI}7{A5gOPjCq6Sk>HhoN5d}+|E(#|X_w#@xfeEI>tuW>J9~wJ(`Hl>M*xM>;aa%ii zNLbJ}*ctkS#|&Hb&`Ta%==QpiG#B(#PLF>h9tusVLf;3JTNT)xIQ{f6QTh--s_D)N zk%oT@DZY0!XJvd!G!r0A*|*S+4|jx6SEt*P(S*q)3EtHI<>>abAS9wD1t$Aawfz!o ze^HDRjU*ofEH1gGiXSTh_FF5>2$>}?;#((_TBZ;QnZAf}q8{={bx8<`^m3&zQr7kn zn>H192HQoRVOQy$C>Ce%Am$C7I6J4o3#@Hgu_rnG3d=JQ@904${Vn|*T2e|h_{=JRT^btk=bXSMZU z^%WrlPEP1gU>gW_7Enb(aQKu(lUok*8WpI4eEYr%nMbNTvrTndPlMz4vor#JWl*A! zWi05xmZ_;Zu9vb|SR9%m2!=;S0osqUUb{3EiKPQ$xepA=O1wM!>F6I>xav%Md_Y4- zC0!#OC7GNI&}q-rAZNT;Cpf9nOHC^+XXzcXs1!m8HkWTE?@L2L-H|<;H&VA-Nd|^n zF%On3?17*WQ1!RfGj4}`eLN|t;>a3+6EUmrssYYZNi_yVdWZN-5X#w*r=v;YzKo5R zcyr(&%sMiSKc63Ly?@>@QeNoQpjh`k)slotW$-&O{bXJ}%ti~$yKlmDq_?kZDB*b~ ztw_DY6YY@o$g9MDkmY&oAJGlkYcXu_5IiQ36fV9zqcm)nT7Dj14JiQ7xec5nhR-_h zWj^;`^!BZX#-^6nuMO2#G#j|5B4)|F`r-xx4+-&YAxFo_`T6-5d|BX5Siq6j5vc6{ zn>$6GqeXAyQ*YzInD?th)}6%Vqxa<_5gPz?El(|j(H}MLw<6A!@}>6*#k`vlqz2Ui zKeXkY&iSf3^Wn_GSo>%Y7zlBuhR6=e3T?lhZG8k*u8|v$q^u!FiT~gAd5j;a*R{Tg zxEsPQ#`=q=zeXjBVrB}Pra^nO&^l7mVE?IY>c4tSaZ;$;gyIcHVVL*N?RJ73FDH5l zk1ofrciagXp*T%J?i`OWa?@m`h!p7PeY1%&ofd^tPZ=Gz_SIvDUPchDP}8i5VVF_; z{Sz!Pjhov1%5q~{uxx0(;QQPUUt5D80{GeOF|GuVb_Eog*fhT78LYiBeU+Db(Avf3 zM-nUOB(hP_es&d+1()3i&YhFITs=XF*#pY;K6@e5hDRMS+Gh*fBXYjXQzOnX07wtZrOl6>d zh3_*re7Mc)K?Ffb1Hoyo9sXF>*`aTxM$h0SBo314t90M#)UEtzJt0W zFdWXpE{=1nGw;*L3RHH4!fNqOfGT?ReJ_I^~#00!yFg1 z2bE-9vxjq@a8$W6w7h^q#X>=cCuTc_fA%G&^mtO-B) z#whii(Ncd;7}-{XMEEN&?Wzl2s`I?yVu7H)`EKgk{ZkDJMsc1?%#7Z>Z?TZcSIE6>S(_P`zqNH9qCL;nnZivH znnuFRdJLCNR-Tw$q&g^DGZ%vns_+q9SssZG#2-SK#?6?=>$jsd-RF1IpM^*W=?d4WrIf|g95;&23B#vGe;MeV~M{0w^*jagMXN0^(n=0 z2D5$3J5Jn{6I<+_3^*ifYPdtitmxI<;6+GF-j}-uh5T5T_5V0J2ktoAE{w*u8aKAB z#0cS#YyB7Sy$P! zx#T*@v1fgWQ~7XWkc551Q*PnH@g;WXwr`dsm^@}ClB*%u91|u(d+tSHik4EI?p_pf z`SMC!pO|Q~cxTeoJGH44erc%Ih&hwyme!{@tQ6EoBs-(T*&u(^yTG&MPVm~=n(rgc zMci3)VTHL0XRBycv`!aZ2bHiLd5wE4KON!se=`x(N(5ex^oz1)!IQ-@8@QSHVcX^z z5~{*$xn!I0i2W>Y-(##9Rb{3|B<+|mYs=bWl-W6aN=S6%xj0Gtz8knImny-}*(#Ul zZW?n|vNtd_1-0w*>`wsnFcEMiCCv2GIuEd#vgTSML(B&)-a58Fq_yeuFB2_xZY>8@ z!wg2~R%rmWoFkL#`v!Avb;eJKKKd5v*3E9ugbR z^YHl*z&ZwLE(=}r!h-6iU zIAl>03{Q&k3 zgwborfTG{D%GK0SO)NQ@;H%>6fmB%C3kWI@YW((PZOSa#dQ)S0+hB6`YYC2#k&--c zml_pbwq=?HNl`YGe_5Cxdp(UNZ}REpP^fnf*d}Eg8LiV$N`kxN>RDcXjT%|Tl}Q@d zmv}4tt79V{<&H+vL1m3_7_^;cMM}Aex(bIy-@*Xk3wh(&tU5Kbazajbw&mA)=RVyl zRd`qV!b-)xB*1c!FC$S3vph>^Qyb%QFrgCgbqvg_v+gofnW?@fr>quoLQ=`O3I?n% zkyos#jPdS+amxAOaim;R@&Bi&4VtWgFy7pL1`|%l`h8+^*|jB8Sa_f^^qCl~ROhGY1zWZ8lkIQgu~x^5(~KIK z*O8Phed@ZgMNtNUhZK_+r!nUSo;{4DqEPr{G=J2Kt=9&pgO(qCWo+15TqxW%iP#Bp zc!#tZUA7+4%48sjRm5o2zE69`kL_2JFApXz>_J2!--aF%$ZC@Bg`3jHaY7iSVdjfp zJ0xv61%yjNfNLk8#S%GZ%F)-p_P4e}04fCAJZy>1@`x@RnY_3&^{KjMD3Y`xp^PVP z3InGSZ(ryxDRv5E`1-ERRMRr6R%>cEh+EVPD`RGbC$RRumFnExa3Uq7D@-8=OMCEz z4vTIqBE%qw=&e7IN{**AW7x*4+C+0dMAOyj7aQLf351k=ax)(op^T1BAasBs5IVMl zYa=7)bX|{`C$O1bpHWe_6gi#PqLP+V)fMp(z@xc7Z)g4=K7?`kRVzC;!di|8J2Y?{>5TAbp}AC>PKOtr ziIoktEmL{&OnQ!^6Nd6niX@*!@bcKUo`Z+5U6-2fW=v#ebvnW8ifBQSCBW1cbFr4t zg?lh|Env`lJpYf^h3CI=28J3;_3k3f;<8vNG-xw(s9g>upqK8rY6olpabL)meYe`) zZ?Pzi*=oHXdctDWW`x>9RgnmYOjT+>6j6l5wYvSS2#jbZOvP}oXA2Q)jLFRHuSnIV zIELaatqbvFxR*BUznj3P*kSjyt!}_`UatAFXLeKA+19*TCs>;FB0PpTQ+|h6KHKtS z(5Pqkyq#NOF3g>H!Ap}V)M#shKD2Vr=p2+y5?`co!?j7o5oFzvY_YgVjCClE{>Gl{ z7ogt2QD5%nZP0TF*Tk{^E4xM!wefz>Q>p%Xx(I#4@!?Z|fv)aXY;Xw{097NM)R)<` zb$cHlz^bd^^}s`}oww_?3z}BXnCj$t7k(wH7_1eryx6yYPE~4CtuXH=>YI8AM|!G- zY+kUHNT^qSQB2B@{VN_HtH$}?3q+TSE#fbq%;Ei^fhcWGT=t5Y*&n{fG!?x34OfX3>mRo{tr}noqE3`6iBz%}c~&gLDVCE&2%WO#@JmBOUsFrY~HhBdq?#M~Gm&tudj# z$Gq9_N<;sFmc#COk>`83SM}?Yz^K>1w*i8oP}*Sd#)c4}5!5l=g3X9lQRzeqb_u7c zD(Nid=KZ9I%Li^RrB2*SG?VsITXhM$n*Q5P3;HJ3X?iS{O@vnN{up4R76u>LS~Ar6 z(UM4^*)pMycPo4ojdj)D+{5Fij?si0)`INo=KOCPaMt;8AKi5y@NP9_tw-Zp3N0_d zcqFfsme<*g%I9z_Axl#v(yy4A&S{kpkqyj2E>)_^#?@FdiqowG%*E_%u}JAhjtKCq z>6wbV(PE@EPxinwJtWM9Gw~$!jeGJ0WrA<_YzfAVe%3tL$b(bw+b^LIH7WDDl4JW^ zCXG}6>F^jcSIqpb{>YE zAYG*3Yba1xJ#TT>Rd~BsPk47@or@xbhZo*-Ua;ODE&6p#fuJP41B{Pm|5DceK9VWuXnuo5KTm)p< zLvw5{ZSm=8UDErry>`kZ)K~xX+4EqpI0;Y;RFI-_qzi#@Vu?g>jaPwEKTvx556*f7 z|Eb^_46)JJ2`M3Dtym=0##O?UCr3ATFtLi1ln&`}oS87^CR#{@iWf`pzNg(2-j+30 zxhle=Gs~AYit&B9DF>;7RGb#WQ1&%vVmXRlIwEf9WfWE17$tB=xLCnw0F+f(ydh8~ zRbW!`oB07n7IK^4t*Zunx)74%H>E-nmI_B2R5(FrPI|Zr{Si3?i(l}i>E2nzjMLNx=r9Q}4Xc&AM!SZ< z_y8&z!rIUr%S@Q|6809_m|RywYTVvxKRj}znouhsgCF4b8&^^%a!;?~?=*bD^TU!B5YOW?zz!=zAr=!a|8{@cw7C{nQ5w zpGuIDdu7BNTS@1)@A3nes~Udbm8tk)tkIL;864^m(G%4;Fg13*pN`bZ)><7$=;NE8 zo0|zOL?h{7tSKR2!JPGic0aKJ!ZGs~9DKRWHoBL2GYr+L(}KZ0L!SwJR){ORH-etQ< zq(rbl%(e~rv;{xu7vm^gW$aFja)d@qyixvJSfVBbjW63d%vA5P43zpw8NHG4ii6Q{~{%gIHF>%u*>(hQBCPdQ4Dl3l320ZiSP83H-ChXaqFbX*scd}wL zOMb;7u3c4|wpU>BJGD7gizcqsqt5E(Il|=PV^9l`cY7ip|C;@KTxXPVk>?hm*gkue ziJb61Bx!hgvCDdheW4zdtzL&%qO{}?orwNG$=^-z{`S3uyB6Iv-n_tlE0n{MYgghS za&KYrG%PvSD^+X8SuCb}q|B^Tgui%FtOo?+%5o^>_O5swcwMg@btDwkvQ_?BJlj+u z2QqoG;fWlra8%aV%o$fJ08F!6ia1+!)~qX)?a*F47Jy|iLVgUu?qM7Y*)w*5+S@dY zP{s+2hm@QKnu6L8{E~L*!rXK(x$_;j05#ehvRVV1l>P+&&1T^BQe`7zZ95^@)f5UR zM9l_plTs9%gy~IW8Q0jIm0+3=ofoHhxruDhHV(NNBqyF+l0zFqYO6+bp`}E6fhY8M zXV|n;GuFVbY!;dvbd2|HN_KY(Z^_!A5u(8yt^$_FoFiDQhFbNMW_bvTwSlRaBDXvMe#28ZCnzZ7Q_-0Vj!U1d92m zj0O1RlJc9+4aG4xh9^1jMG!hf4d>H015fq)_8JQ3=zABm#;kJL}?cdfl0Mj zJpBdLUY8$Eba>^3ojg}HICoz9lLiRpl6vDdqBA6=wb0_C;Sg7$?e?f0FbXLj9G*Op zzapZVx5=_GDb|baLUIbAF*n{|Zj~35%Qb{qQgifrS%;FkiBSkBo8+6#bFe*l?072Y zVs*Ev>(X;0%kgtHx*}t^J?5Q*y3FObbk=Q|ul9H${sr%uy6u7or0T!Is7wLo0OGu5@SdiWyWyKd+N7M4vPXX*rp&RD!Z_-YA0n z{)CIX8|p-VE}TX(E6QuxTyM>ByhTup2cKh(X-{@$k6EW>rPSo$T79VRWjd5K2>l2Q zNXSJ~3v|U7 zF%VuY)8T>K`~2mS{b|YU#cm8D6#|%!sLS9#1WBhU=;fVt>KvG&Hy=13GURDn^A@=W z5)_lBYGGzf&}b^a4RQ~g$t zwv82Co9h%cZT)wAscO(<_efv_$#oTkCm2XRJq7-wQkmY)G`;NP_#HmCFk^93b81O* zNm_CMoq~^towqs0x)uHk`$7D)bg1EkS|hy??pz(p3NFVNIWzgn-u&#aqMKC`OE-;< zYj6rKj*-s}HlPdUM7l ziP+kyV$L*X;*?#)bDr;AOy7j9#W_ikx~|B?tv1Sj7$cYG#AxbO^Zab!BE__v zFCdY9g0KgW#UFG0%8&Kx*upnfhrEDn+~H>u&-%gYiy2?KoGZC#LY$#vyvm4#L{Q^@ z6g#f+-USZ_q?fNciZtzHIO=LDDRxdRGSZ;Y9^})_vmx-~T+^GT3zNXN=Ow0ou?YMq z+Oh7c0Ns4l!_>lmB4n^XMQUh=4Z1!Vc9}E;PXkXR;AANe@#j%K!%I0C7iyrLc?j75 zCNS4uA(<(+zE!S2*3t zi6GQtv@^iRN$5J0OE;A(p7*);4!gzXj=if3P0@|sW{#6 zb9hqIhzQkw%Qu_E;(#M;gJDjQ73MO%^J<1j5zhHoSn8P|&Mxw=?>F+DpY|1v%Ok2e zm8sesjL36XvS2GBsSU4;MA}q~9zgL2W8y-s>7a+XnXiV@)<#l{He$~vw(QMeUUR#E z)?ap+81;+<;5!F)ky7My_|PLFnNC_~>bN(5Kmn_~ze*3~I`k~!sA);*Dr;t;Q{2b< zUuZny=@++;CW(V9IVck5n~bka%O8 zQfoFa!yJDGpr34sl4V{x4Yc{`@vvT9yN6MY(K1C$$|GFApuT8&_N#mgn|0lm=u>7S znUi7po89uUrA6}c;plT!D1Y6P=!qNm{c9ZWkk}6bM3O8vxN6{t%vVWhX z(d;HSp$-z|w$$q3Y}0E3K^uO7j$R&u9$F{CHqz1-l(yVfTAw{+S-JXWq>2f)1x`(k zvQG4ye0JHmDv;lGGV7=vGBrTfOjsdfQ1Pep1BzK)(m7XV$`Hkt*X!@Nu0Cj&do&D~ zkhU^O@dvB?5Dh;1s_=VFGZV6*D+yec?WgceS23w46sZQ;qpa%WeQ)WnQ`NNOm zVDSq{b0~z#!g?pW7YObqV)FKA~-$gS~xev~DRMu53Suf*sYd!K|x8fyV9sPR! z&6$CVThfzqil0=9;S{btB7R6fwYEqG4Dz0$?A9o;FEYxkw(y`Bh%537+CDrb#t(K@&EWDMIlNzTOJk=R|*J(YS}->hC|{Sxh4F zcPL8MR~HBtA~wH24tF1A1n0p|hkM8pX;MUruu>+K&LBt`b9Q?c9#(7Gdt<@1h0DZa zv_KTC9fI(!9XiU|N8h-{MxlN(vFZa>A7XMbHVlO^=dsvG;mMw?6MgR+rXC~45TPIh@v@2kJxcQ}RxW{*#xUu_qC)t5XN12dw3~u;k54Q*w z?B_$32?Zv)=64e<w&P9llAf)YA)%pT`Ue1wB809o{4a zKGU9zv6J2kG_8;bk0v9PONo|;HA7X>5|i;ze1%OV&*r7~?KU8?vo@;i``Rw|Pgi$T zU3tNWVF08-V|pRyg58I2mPA5;T&-D0lrRyc7v=_8t87R;WG)n>LTz?7G;*a)qXE zWoiE}A2Hv%%t`>BN!Q0`VI5mXljjQ6&HLK-21OvobA3GO`~lX;Fzr|4$DXuYM;$)F z(Nvg=vgLWfstMzDPKiUQm-5}2j*eWKI0O{|M}o|($xaAVt$m9*mAig1TuFHtGYh91I zGbv6XBx0kwZ|6$MN9%p5rgu#76s6+fY~$nce-ulHh4fjg2yHWP=tOqBkXxj{aL1L{ zHPcoU1O52fGwU5{UAxvb(SOGK<`#4eoJDyBZaOFs^O-F^y!=eN{3jPgm(?B$5dB_S zSxJ&LxiV?`%@gqCnh52Bc<<4WamS|ecW5?ZLs=WoVijD@81jn%(8~r)l|`-+fi$1Eh0&XP*FkX=nL}> z`5CRqzHX1`G=9-XtWthzXyZll5AtYx>SF|aUsNl9VSDNNZHJ(I?&y>ug_^Fds2#1-_;r>3Ks;K+#*oB@Bz%s(3L|i0|3fqnTO;nT- z5yGmp`agjmvWj6;`G3v)6b(as9uZHj2exN}v9%=DC7De2V-%gM3lW@cr=OcS?T5?z z!{|^mJ~_k~dii4-Ut)e&4&5e=ym^$|{9phE#Bn#kY(WZSuzM8k(s}bhO;? zW|7wX$x6<-WEC-mZ6L~zfEIbs#F;Iil2N~VPRxPRE#{i^v=9b{Wd=}`&_>5E7i2gk zuV@OYKu-y-rp%P%1U32Z3S)V zLswWFj6YJ&s=2bE$M>gek)S2Tis9D^7WVMaowLYqs1YV7Vk-7{C9VouN-e6Ew6HRT z`7_HcBAi-PiavRJ`qaex_#Q<%$5>DF{6LW&CWNd#y5@n;Oi-Q}jDo9ZvwosiJ9VbH zANjP`+0ix+1Gdmfg;M{Y({G(kaq42ltAFB_E1Z-PU)zw-9SRwmJCeF6OP3jm{x0b# zU(Mb5NukoK*4(7R064(wdb~K{Ze{~6RGH_>oB8SAV}-Bgj#VB6@Eql3ZmeHFb%aFh z)xR%RG;^u)8=fGk5bK*!MZ*u3M|re>V|I3qsUsus{;oZ?Oh%yN#Gbg3Y!G}7W$|q% zK=PG~UAtIuxDL!@*@HJ4*rO4r|4aUrip>MjwxDlyp4ff3YpFEry5;h)1=T z^ctKL>F6_mO+xp8<0TlS--KJz&cjK(*tcz+yII@G=4@``>fmzAgR|pG#k4t=pD}sI zKwo=v;Uk`h;ukXH=QsSpbdguG+!&QMWY(*+Z-F#BxgQgOz)G0)6YD@D+(N=kLZBK2 zLECOnna2w6*j&pKY1&+YFU|02#>F}8%mCT)2E{!EXv;gDF}AvaaAO;DSE>G6F`WlN z?l=I6$H8-J(0vbs7vBuYfU2WUWy z@gYVPD%nuuF!E`VNc195dT}@TEG{@HCPe?TSL}At;R{-X$HkCCHild02ftqT!cSUD zDp|Pjry*R78a~T{t^2yawi0=a%JaPDpu_9yzjf#!k;<>!#CC<%r3$#{5omG*55h?e zO3Ncb$>>Pqgmb9aG*Yp14eI7ZXR)xsaLw7gho1l4SPOK%_wVa|qL<5b3NHJ}^Tu+D zzVAr9qM@v~nU`8p4Ov}Sj|T0%x^DVlC$7y36({*hDOY5)_yn}5M`8urL5yX<5un>6%z0< z&X}vKkv12&$Ul$(cWb5H9E9klYIS1=IfkQaY&*-J?QP=yT)!c+kJnKE6f0Ys-#Q<^ zj)9z0Fvf&hpv{?)ccONxSDYv!Kc5uGnV`1@Y`xN<+La5S4MAI$*Cff$9GF`@uC|ld zbi-8w__Bey5o&DIspm@R2wsu3lnot7$qqX83EG}xgphy7%_7X-CMz&l8Y7doGOVK# z5rpZgk){S1u>HU_nWKs8IFkW74(Vo{O~F5w`O|!mvi>U1jNcJLK!_)>*e1loQT@B| zbotaZDMMBHw%WJ-nL$nMPv!b7(Xpo+c5yoKU;FQ?y(7~D$L~t(Dw=++fqtaDqGQSY z-iQ`zcp4`+0-~@6exRFYW@CwP56D2n)w6qkFY%WOXkAe4E<=tXwukfU3KSn4t6)d&4IBMg^U#Prsz|PQcm`K8!2*oQDIO}Y99nd6~785lv91+}1-Ee{*3KfV^H zu0$NB$hpfGDC0%vi=R?s9PW3e6BWHP>fOHT;_$O@3@s|2Ub`FtENS4)YQ<^#Yl5u1 ze!aoSXnl1@&rYje|4Y>);4VOXRCIsrlMfR67`9vk-9h-n<$42Tr|0#S_d!Vjp)-om zUZf@HWK<^C7hQwC6^n)F^-4ovDle^Q(5^K6oA|ZaW@uF?1>7tPr0|Qey!;WIy16UH z*-4yjzSbGr!(?r&zT|h0PfijGq0LaPYq`l>9=7VlZYTCa8Qt_$w;cKmz! z8owQcL>0Ijgj5QANc|4dYGs0y4^BSQdSFnopA$)cC%(ws3Zc*Q+mHU+58i@D-hXdG z|E$1nI^qN2>j#m~;PS+z&Tt2z2#d&FN=^G3ZEB4VMt|WWtnBOwb_Xss^>m+2dpfWi zwOlzNUt@-dBRY1_5^+BAnsv)7)=xq9_v=BiG{bRsM-^eO&)u|p*5}!Ev~`qqShSUO zlqpSbWq9bW`RM$%$V!^-Wr(t<3aWo>o`J}Go?4pEc(%W`k`vPV*xZ`$Hq!a5{e3O_ z%Kpl}p56)i7C}AT|EM2s@tntciK4@7xMm`|Y#ag9#8mRBiW322$@o9X3U z;WgrTlecS!#We%&ovL)h$j4^DIJP8N(?)M88YSpO;H;MA8Etv;bibR|SHY`udsXwi z>fhAA(XB0{Yqat0GVa;!arAvrz)5{K*vM!Uy|NeR- zUk;xdkcu*J@Ae}==ueo?pJQsFHxOlD`7;0CrqD+t>PMp#v5)u?$PV*bO8oFk3ko&_GA8#5*q7TO4 z^T34&!45CWw@?(BYO2uWrXlhnxDXZP*U^m|Oi4KQx7cW1DMG*s;$c= zT(c%9r|%0VwM;<8(RL2p&tdktkU;M;IgRrW z{bt~=J18x|uX`mIrn6Pq@ z<{-`?Ar-Mp_7N{EF;9W@Uv+hnYfdMf!AP8Pd`$h~i zlAD)zz){x&0uA5Zc!O=Sb?uHQ_dfdeKEBj3^ZuvoV)=i*2KT=|iF|)@`fqmN?MvQc zlTG2WUXAADcnl#xHo#6l#o`&SGUHdaQhE)m z0_iwAT7=O_t@zBi#3dgh&%4R_<5rz}dPy3Ix#ba_m^94D-hLy}g5_UB-#VyTF#Uo_O=l<(Et~d`2_{A{ z9W7rq6fdLYTyjxRFz@y`7?CB;0IqMFo+k@_OOA3rDvc&87=N!w68M_a7)B#V6VlHx z{S})K2;zgDznIV8KW=@%KnUR%9B~N3IYF%wDnc31lkuWxIu#6d3o0?dtYXldNc-|NKErj z#A=z@A5qHM)>x*}KZK>i6gEq8=ozo-*#L)3jZ-+lnA)Zr>wAe`P+X7;x^{JwRao+x z+-78DNa4oHsc@~<`HC$IEb4F*O)woCE_;#6&MbjQ1a2%*OZ@149GJ@lW515=a!g8f z>|k4~invSEEc3ZDzWYk5aY^{g`!5uiRxpMR zqB-D&3ij+33{c@A@^WOU6E^6lyp+F!&p550A@PkZc_Dn+xKezQ@W{I9oU%H}PE0z4 z*0f#x_3QDecayCnKnf4CfR94d_rfpS8BFlKMChG=;F15!a0}rLQct~T7(Hu%jEdji z|A0iIQ6N)N|IKCp%@^q0f5hK^6aa!W1HbsNzkmONUdLa7`O4@k5bFsF7|1EHhAVvC z)&2ip=l_-I0HnmF7QB!73KDpn`qJL+3%yw+eT*6j%sd9Nw;D~x-f3b2;b_43!r?-ENgqAwd1vC3InRZ$nHW_yfdiXVhh8XUg@4XmAuhs z=e|nPa97H3(ErJqNZUd$}4pHqb78HPbCU&QDzL*ny48JvEJw0j|T*^o6pvR zYfZepll!hk2^`FSmZ5?)r-6qd<3wv7(lLsEI-`5YDD9uUU{GXrPh_+ITp+k3XBR@c zV+TTCA{h+1qGqtyW3JKj7#=0y$qoCCJ;HOx_Z|2HJ+xbeh&~tAy*~f8{rg?Ov+KRi z|6iul%B}a3%Z~xa%jAA#)aCE2LKsqqCKr4zpp;H>dns4wdN;oD)&;(;P@C12Ma`L- zIl`6&eXDvMmV;PlG|M4dd;+ z6KXyLg=rsM0D|ahq^TLG=(#|TR(t$|&10cf=kM^0JsG~WdCBZzWpF2^L!~wO6ccN} z1T7!R^+CZuklvy1cgG>te|3gmKY$Yu8<}6a_uLb>E*117C3NdE|1tjW&-b9oOn(^? zl;E}O()st=dEY6u{D-eJ9*`8eO3VJ z01IdA(5A&oE8(*vgEe7m!|07Ok)++hm`Ak}Q0)E_=ZoNlcdc=8T>Y$obZnqGudzG# zX~OYR7ZcRtsKrUQu1CKM);dH*s9TLQ<&&|}=lG6%9 z&Zaymaab2x`ev{dASB9ktb%Z$JVr3<6&Ig%3l_b?(Ok+PK5mpH$wNzd4WhCPyvYE4rPoEuDy7LYbvN^yas?hUe%^tK!)mD z#)lZ18N$uyS?oTsZb*kO6sOAH@c1XJz*LmujM8gWbm-8zZ5Yfc?Ui!bE%>oH-w)bt zDgAp=VxGoe!5Y^yPjpd=Zp{A@?S7egi9x=+ud4JYP*6}XZ~{u9`HGn04;;V6ZRozE z9r~|614m`ziab%>dkb!TqkgB*r^7`l9v_wau6vAayd4eq*(+X$8r!6e1T$RozXHbh z9R{5!OKV9@_?_rox6-63WoR&Aa>+jGu`A1Vn(roTh#X zG*BGb2coUAjug9*{?E@HCV>Rg81oDbM#F$=!m`;d>*kYaLMO?NaO7idlPv||gqaDb ztsqT@{~`#O_B@q|gZwtf`8S5Slr))%A5h7n>bYP=9-Rs5Oe9g>GwL;9Ngt-raF2ZzF!6)zBEPdz6WdLaM)+BpvXr&Q^^bl}nJzqzmAm>;0c7{$QXb_>*u|AIha zrL4{F`epaj1{rH`V({;zzyI7F@0{z@{)Uh!bBZepE-@j^)kTgw0d%#M9qGlh;U;`z zm@x&zWQ`U`SlbR`nKCUQh z1Fed~(#}m=mnRb*W}uI$O8{LS*a45GJ5DjfEj-?8ENJSu4}rv9js-#ud&{VH^?bIIsB&GmYpKdW!mQ z;cG#Z^d~y$>!bjbe4x~Kq0!I{;vtP5QZifD1iv~cG|1r%>Kli{2X{{Yt_MD+gWi}2 z?jo4|LEVI~;qxmGZN2}cE$DC3zk5)wloJTij_W^*`+t*H6M9xt>D@Sq7)1B}c4e}W zR-vUIOv&WTc<<{X_^?TD;jNQ*jT@EAZhVVgMV z%oQ?Nbii_8JgE)tEG6a3s~2J?u)_6%9QG?gJ`}9|{ysh50hyIt;+MyGm2c{UN|N(( zswCw8O@3-OS87PWsyw;aHmnYRl@J}cxjGVcBA!O>B(AwX32JNC+HVs3!Kz(Vb83P! ziij@YB$a$HCZnWbrZH)b6-I^f2Sces$iI+nnA&Inr>B9TXYY&4w{>ZFiwqFpq(Ky} zyUsAf4R-E4a-jbR#gv6%3SDwEZ6-)KJr#Xc1dZt62&I{RG~~+#i(y}nwt&AgGkjX| zB1P!Hb;yxa|GgMi>mb*E$SnAoz~~E44fxd&@at=>D(m~TCi==a1HryVZ!=bcn1i75 zo#ynp=JZJ)bke{u{jdUxwgR>9w=eJ=boQWxda(Kxcy;?H@%E2f(9Qhk?%s!Ah0S}b z(no8)mcspKw5w8rc@ieg-&-v%Q~IR!{~I0_};?d<3ZV+%ykV^u76)1UTU zYd7qPMPx}adDXeB4^obo+p9ChVqE{>U3$odFep6F4$!CaC(aN!7l0L zB~}DLS!^VeR*>)5*VZa~-5TI|LYRd2ubG5u)VQ~vBN?1^VvM|>0YwbWBdv>3(wi=*vM^2;1ujQnOoW!G>wG{Z@gn@hR zx%qj&+hj(=KHq0&o)N^Ow)vp{9*sV>)(x!#1F>4k8o`n#90#c&a^OhEYozMemlqOh zCMW0AJ9>(^YdI^Ha+Y{9({ItOLH;{gu}H#6GN7wG3PP$G*(p3!d8F9z3du1VEwkv% zk^P0pUq2vO`>J#^^+EqE&3_IN2vSHbeJemcf zrYY)3zQw)@o>o(~mkiH-1!{Ide0BjT!p-<>Xw3I7r?{9!J^%u^@hFhKV`IJmRexp6E&sxh`pc(zcp`@e*$z-VGonDM0bmkvq>@ZTM9kjFJ54kAm=s{)pbfMp|q3P?Vdu@={KNlSI+BjHJ?`OtWhEjmgik3(F%vh7XTO!*dVfo1HL5^^>Ur z))6rXF=Fyw(dm!@k@HXNe?kHa@!bn8yUQvHV6<@Xcg(sM$i>T$?VqyM zB!3mBgp-9np~EKf*nw$E{V4`*?F&U948k{i7{S04>1D)4)ZdhA@Ci-S$)jy$mJ0ANtPFyo>#8+9H8I`<*I4P|niN)2>Ygof!MUj1AyYAG9fF!3}(qYa!%Yd8ET_vm7^b)7t7lWE8p842Tq?jjm?O^p#tr< zLVBG;0aH)0?x({U?JOA)&zVNTo3g*f?SFWKL@Xc6H5EexIb)y{aZ(%6D!4&+XSUPX zcVT(8sz}w4S5MURX4tBM;@cH$L0#&%Te31NiFzlAmPd9>^K^=-s^2)O@AnoO-)YWE zC=rKvDTW2aQW=%7P?otr9X+()>tT6L)2V@&o{R+)HehK2wb6{ z!h2zxG}NiovTbNaGH2lQ!12=5aZ2SpcENbTzfYJg6s12F7+#s>QD1cL<}J67Jnp>T z0eD36yMA41DZ@H8?ikZcb%+Q^g;UN$O6{Csn|M5;8PY~(Fl3q~?NpLl)K$`>cCUWjTz!n0&i2v+CQEkQV9vR72e6GDgDvl=@#YWlbRe44l1|=C2 z|7BJdyD zA3u{1ml$&6)qNdTu0TT!p>#SCM}`CiyS!o!+TjFO5vP4HHlH1AwB>UKgEgG`UH6RD z=n}}uvUUaUB~1Ez>aqh;4jLUqFPd++#C5Sz)^-h5nQuvGi-r57z$f}IG@oQAV^HOw zC_Diae2s;ic^l`?VC!3+A^psR8kO9`QrR#mP(MB8sN!JA7je}JrFxs8v(Gt%=)y6i zjPX#P9Ee@lR(Wh2yI>*0mt}X`r*0}s<-sCox6P75artUv8Wlawt#_-i!6@DF@=lmC zsBlg0#xas*BAx#>oe>vQJ1$qAN|Pcd+~M;Lp`G%t1T%RX@Ev47X{X=K>9vM(V>DWq zEg%hIfYq~>4dJDh36L>ZX|?16`-wF7)eZDvix%M&l%bsD6WsGRp|P*hH=#MVY}g0y z7N7`9suhJE&Mcom_0E7?!WLwz-lHr__mCbNkeam{_k)h;Ryy2cgKsk?T7%Tb z9%R4&iPPa9G1~qSg~`l%w#XUI;Bf@%(3EpV3TyJeF-lB7K!fAM>(Ij(x1`P@M8l^R z5s4Hs0&qqeeKi9aQKM{R&3|VT;ODLR&{9ZKFe8}DQTf+u$W)YIMQi6PH(f0-1u}VprEDcYDKb( z$pnS-FIIBc_@IdDRj&`S+j3=9n!=6Oom(s;e@u5B%fw%|>Ll|!Cvdm{XC%T6d74tG zlIjADM!!VNf4OkbEC9!#CM7v^HVKoX(ZwR>GEw;Ust=ON!oAkWJT^=pfga`%*l$vj z`_M9pjfW+|N~ZMHJT}L)I`Sm*#Q`(q^**N_s~rYyvK}|%Y$!D}Q+P^C$g8}jl+JfV z9rgs|{<4g}sc9`FdZZ!qXz_rGe%RlG^D@|r8I{bU<>4D@B0ub}Hi=6;S2S34IKt4gszcyR2*P9S6Wayj(D{vBGO>H#N<05$p#ur-s8pMwkjt{ znvh@lKi(As<4g~gVt)A4X6EmkU~IfOO)&}f5AYn`VW*~Q4t54>EI+N%hk8*q{)kY~ zomqF_@?Zi7T4ylL?>hA*>0#*w3NL`VETgm2auVI-76(Jal29~Png~5%;fNw@5c;rC z0)(U*Safv0Bf)jx8YO!BOcAzS7Yh3 z@IJZ6>@GBOe&v?2Fgh9UguEdPum=le9G21Ffr#zRfH5R-j2ys6NYl8qGL%i&!uXj& zb1^kL6kDqVn1h7g|2VqpfT*4>N_UrZcZYPBr1a9#T@upL-61U?-AIE-cXx+KgQS3f z$Pf5tzrT##efwtS-h0luv+vAo{PMjQq1B&&*xw=AJII!Vt}Ubzyw;wy5%@MaT5AO{ zx$TBo`h)T?)0(!J)xU;kN8u`SzEFPt@1rf}2LXi}4l5gCU!O8Q--jPLmok096ngMB zWv;0hNbebNf7v=b=%MTqI`~#uF`BhdQYpivytkR_zD~nsJJ9>~JN>$)>imye+nqxV zTph|yWaEdLx;`oVTZ*=j$>If9ZEj4sQ<-LnbTp)glJ8*cTw?Im4;RW9nzg;E$zGJgG%}9Y@$&xVrLvufiaa80aedMlD z+P*xf!nPC!k3XH6N3I1W4^UM6eug^Ed{yP=)$UhjGo4KBf6>g7$HMHeE|bc%O{d)0t2rFop*4T$ zla6GAozeycy4g#WJ3edgiJ_c+cJ)X~La~Z7V9VzaqTc`Wj)SVSK_(=nznC*w@mJk~ z$}#mel52$&#;eADZLGjz(?&kt|Mubv*_a;8bqVbV1?O}P%Z1nM#gRn9)Yv{r@qVO) zy9g*^6d``pkzv-n7J(P3LBLGgr`%jtqJ8&hj$ojh#Hb^$G4?HYKMpS#|CHDbzjyk- zO3`1HB~|TYYZhMw_kaE~lvcC;E*y?e5Es^V{l#vQjH7Ii7i%I-5od0i52jiHr!Di~ zhvvi&41JigbUi&IR4H@5T_bFYjSBo2O`$kNwAcwoQKb}{vcqN490kQCGQ&Ue$O-bJ ztM&=FN6Z9#p~jl0jNviMWKuqkT_j{np9PWU#0UIeZ5~t3=P5f6M|^(ukr+nGw{5B3 zPmY0xYO)kkw4$ahqq{N&mkSR^341u6fX?a+>` zU#IKVeP{uOJw-$+%53j#R9SmWEjp*CX5!WygZKA^4)03*t++f@$(8X1-cX7$YWH4V zoY$s9^CS@vjdoM_AiP*4)v{W#cZ}hHMcA6Lw>u%+R4f8oDw3`a^D$ zV*5%aeLJloj#q2$A7N(Wo1s;UBC;F?kK{mXngxuE&uO!>8Au^{t%hOz{Ju<5<+=`~ zn>e;Va^(3vUFOx#S(Edn4jQC|?YWGPaX7x!_F|59_oop0)#7A@BMri+A%E2ij}X7i z9}ay`&)d~VnU~9%onvjr5%90ddbh(X#PCV|$CUl`a#up3{+xBc+70Sc&4Zk2J7t+? zzV6M1ekteOw9DDoi>)rvW370%(>`bZxNMVRUun_q!?wIjiW(BP5?XM~LeurKp z!;vuU#WixD_@avrwuyHsEW1c)WOzxP{1W?kkRBzh8TEJ48zN>B`dWwmeg0OSE7Qdm zO^5#ihr+*g)i>;c1xIe)F`X({8S-yu!jWF-#Jt;JW&ut=vh-km{DyC}FT; zB*rVlQQ${hzv0$lhAGuh%;1P>_+?Zznb7=zz(5AcF|EKsld961#fft;(tFrF6JFON zUl^M@?$mXZw}1U_917L*%Xxr*nlU8(x$VBat?FOOh1wA;jTBx#9cmH`ZW@&)iL_>N zd9mCFSJz6qMyp@jVbVGu_Guc!HId)+{nn9s11k#`A6RR0#}w(Ux%%cqZ0@jD$jcgOs(XR2f@I5ghY(SFe3FwS#r z><=Wsa1#IK_}UN?eZAhv=s%4=#tG8q>0xd+RiXw2U3{#`t>4BLDHcPEAi>6VX8@=I z47oVDPz>i(hO{veiezxcBg*m%+Z*GQwcq5|n3i}wkuZh8 z1`D07pIC|`j64aVWV6AJ(y1(R(lDTTPAgWWF*DQYmCCW;;-T`_ohW(e!gktC=ft7d zzp--W70YG9rKQrWb>-sLu_%{Ml`4&7eIQ;zn5gaxx#79j9mLZm(n_E)?Z-`%V~n}XYQk3d z^6|qM8ma0)kA$Irq6{&Nzj_h9ZZ>J6Qhhjj0d*bbVdvI?M7;)T0W%rFN)BDuloXqC zk&hf4mO~VG16>CUDFmCOq15}b+S|4(b}zxP9tB2UNK;u#<22V|(z2BJ`5Q3~f4IeO zsaZL?di_I10}e|yWuD-Y&~a-`6YA#A99H4T<3mGAxna1Z$fDRpvC^1*8<6+BH&UwQ zgm1@QAHTs!)2(Mwn6NSlXU1VrdFo|g!Kny2CD?BuwHz4E;vuea&E$vqbtN076ZdAT zZSaoQ&DtUgDbX}`jIUGM#s>@1g8(P{?ihYIyUTK>X0U%hugO-`UOzhYu~Ks)b|=B~ zDAXoNKgod=kC0#u=~g~YRQp3~Ttubl{9&ZS6A7$}zTxAvv`r5unGGq)9PTHd>E@k! zyZ`8K>PK583eh`@PFpUfOI$i#h7$I9RgN4B>Ow}TFjnZH<+;q2F zm0}Pf^{uy%4wyng$Ln1PRxD_U@~7s}7q-}OHZUQJJRvJhBR<<9z;RWZ9BkOaP~MI4 zh(-`*7>hw_zCryaIy4hcNyHvuvd!Uj>$t-<_`6K1u43ma`&p)AfvJIdZ_&LxH)QA$ z{iuLji&RFY0(S{MsIMyI?P8*M2#K(!+J1C&GQKqe@k<7cYTtkb$|oT!sp0*FK_~AF zdf(LjD&ZKts{%3Ud|5o)kO~1_#WNj!9pWGAXiQu#2A-o;_3Q~SI(wg5!ws?1PO;Kj zin0IO^jVGUDdoVTq+%mfM-pn>+N4JcXoyl^Z!Lelc$URn^9GK3SC5uIWQAjD_l{?) z7fFRsF)b&2oZ0~e^{q|esIB(wyXw7F#uX9>3xC?AL+2G_D%gOKR;na_l%&&1E?eXU zDOlU0#jGEqsZ~nK08y5%WP*)JW^G75WQV)064w4ouq%fLE7qWtfkNU(NOms2S7L6I zlo`lfQgT9e@m9`MiH>5?DFe9*ZDFYvwncx6uh($ty%a)E3>r54nQXbnv^1xCwL9%d z8qZ2r8Z$$ch>VPkTq3ji%o^e1obR1Fp?k*0rj@zn2c&M0k8evD zQ~kfl@?K>te%*4s*zv%t!?DJWL4?=cfDwJPnscG}!MeKfdgSViEBZ)t>Z&OUuqwLc1kO zGXjV6m*hvXbu($$@~@~msEA>#m?&yAuOLU|BemmNi*KIz9<2@&nJXxVj8=^*5h{5Y z(s2>u6eFTTbKA5-X*Hw2OQaF%$W~G@$ScuU>>}7?t)ef+9iDl_@G@k`*y2L42_sTt z!;#`(#{_EOmWlV}R?9AAmoRldbcA*g#2$p^&2wN9p=COthavVN+QyonTSV7-nkgIe zX%ZK)^5FW@+PF`nYTJ~CCE_Ve+wZQHBG?Gojq8%-HR&$Uv!zc=ZZUL~#&V@sO+qfK zi}=$GFC0f5Y5BR@_p@EGE|og#>t979z|0$4d6bUow=~Ssgj*UCTk<_pju(A(|kGJOrv#36FZKKTq_8t|BALN>aF#7{ikx&JcwpCJCGg-@}@Cx)$ z5u^wntRc}bEX~(tQ7!MVbm^62@DRN^NXlF#J76_J#!RZLr$}1S*<{1Xqmn0K+-XpR zzFE*ybH^n27Li^v{-poiz#$wlvE}Q@9SCo%rWVHDrnE`@VbF|F)BNU-&M5I4_Cm`t zb3vp{=1Ic{URze$c)!?*KRpA?v6ypN<&BxUd1(rIuXX5$1nCGuUw<=1`6@e$pOge& zwa4Q1t0`5mEVtH|hb_+1M%Ub3wck~jeMEy3gUI^Kfm10vLdc`iJ(b73G?)I>G{+7K zmvTStWCj_;y}wF|n#&jA!5?&$V30y}2?AG879%X8zTs6IfoIIw>3%e%ORDS`@Ke$c z{$7kWkvCS|`xlv%;E9#-5eMJGGCGW2dVQ3jso(lDLYTE!4IBgh`zgs2v8Qv#&J;{= zT3!UbRRF)mZjM|JT^w#v+|b`hB5sz~qq+5dA;ltb((nW}?x_UzJa;JcB(%JJBSjx1 z-=uLW6cvzjmWQV>`}%7tE>`H%!;S6qTRJA-`mGx%V+B71;SR@!IHe$H7Z%Zra7HA+ z9)v`Y6p19;w&~!oCsZhgSRsna2QMS~!p*9|e%DeTloO_j;>E?c4i6{T4*&KBZJD08 zb4n+M&bFO%B=Htyn1$L=5)St;36G8&< zD1N|NW6aq%qMTY!e#pbM`nrVz|;Xc6h5EL}cdf+Z)6d+ksg zOXK=vsHyQ*`=(1A}C8d6!l$^8fcLPZxV&yoBAtH(==&AlA zeL_n8n?-6IJ3K;)9|6NFPeel5ON3Od$gZe(n!*o$UUk7IE?Y#ZB&i>rHkuM@?DCaT zdpM0-jLz0w^^DnkWIBQoe>%p}d^-DM>YuW7T`!W;!{(TIWyyml6Njp7MaVly0MeI~ znQ*?DcE384)mSzLX8cb~NQ0d=_=n+|g9Eg3sTH28#V~KH)~;d12z9@}2BRt=Y0+mh z@(V#MFr%4krC(+jC1!sc=86ACjYcIE zy%SmaH=$GcQuuqTFl+7vdtE%m&`ANEqCaS9r(&H2SOXfm=GOXI(vg@-XHK#jRB2RG zMbv-atJSd8wHtc0~~6H zjx^C|ge#typXyN3p;h=;0Dn%<%B?SD*}H&)SH!~_uTz%gib+!_6P^{%PGoN?_ZRQ(v;J;Tau(A+{EBNEUawyme8<&wf001LH49;#kyH_;Az=C|1u%&zuF5<@dc={3wy^d~6~`;Xz1MR=-0|8fyN(_##JGrFyWEH!+vProus7sY|HVC607muxjP6B zq|R8e?n6UI4-^S;gpvk7;dA$gbfx-PU^*ck$#N9lsuNg}ku;5Uli(~EA`HUW!B7)Q zbIZc23rKNFpf2A3gI%uTaZigB#D+OTHw?2LQgxE1h7rEbUra&mGE@uoP{bNHLyE%> zZSXno4e6Xp%gRD)YQ%S!`F$qF08tZfNUnBcDWsoA zLj3XDlhtZX*)^S5%v9`#Lg{yAxSBWhGWQk1`Xtk|nzhx1A33%d!VSVV44%0ij)gx; zSRx)xO=Biu(%jQ47^IipoUb?Rz(Wki$-Sb%0}o{{$&EF5AmAxyg@&gf#F+8d zl*i_TIvRg<=ks7a>1$7A?&Q~k^^Lfpo>Ns!TV*pdFZfq zMc2|tYG`6{+hlDvlDS{&O1=zzj!hbuL!PrEL@Wncn8HG;^1^}9hE?DFFfBRdFg$H3 zg$*~eH<7|^SIAsBh9s9cGmRq4!>iw3P|$jxx8U<~=1R(G z?F*#{#Zi@6_OfGjlGzb?A4Ls3TJFzwZ(Lj0vy!%mib@--(EHp6OG)+l$5M1tvbZH+ zdDyh?%`6v5)cbl{S`V2qxZROsnMIY8d4)n=OXu`jYoJxVCT2&+V+jv0M2%1|frlgu zc9Gz@)X{A!8vfkxuMnlC(M9`PZOA&E1+kE}Ch%@knH4IeW*~C2;`q=BUygv(5S}5_ z=g0>us)^{9$P1ISsLgUDm!57e<55N0oVyekYfB|%VAFC!u4x{UicknA025cSCBR=% z817{Lx5zE&{ofOKN)32F>lvcO7mK{r;LKo!0R&w%2~OXN(3r(fEt%yQyX?f}8h>;Z zas6fB7E&4`Bll%SZKk$s^D=H+m-U5_{R?6jX{Mw|gqWrZvuUi&u&;4Wb?6YNu}ige zK74QeYKPIg7(qB3h(7443(ix;@l(#p+x4->fuZ_JfSAQUCXF_|gYi9%D5a>Ch}4*4 zQ1Z2H9;vH$j9zJ$4sICv#}6%&0&ZxmOIPedb}akfyTX#>uO*_G3NT)5GF(L|{$0-q zTm%l~+bxmn!V<6U_QfK8ksC{0J;}Sh4^IWA6G66Ra-+C?F!Lx?GQIg)!3Z&JTerh@ z5v9 zia6r*bGyRWDXnR6xfR7$WmhTj4;t8I#Y`^)1l`(;(~=P?K_2zuqRwMdDUbmO@hw?bDJt(dXGi5ij_?uZTJ`{JT%uvT4=Nf_Yayp1Vk zvpQ?I4d2qtHF)_9(yQ5SVW(W_H|XZPG&AF}ur5bUYN1 zrk6C{^CY%KD=F-UaF(L>1>0esD-#CCiKnJHch$bi4(^ldpYzg!fv44+ke`W8N3q9( zv5$N$i)U@36Q;sNUUfwFx$gj`*`ZU}ABn^tEgpY~n zq4HGY)0Zf{*0;VPR@6Q~uredU&BlR+H4bA=_F(XyYWH9j#zV$kQmu_tkYnH@jfky~ zN~ws}!kV#os!^5ygdzinAB0vyQ|tJVu&kYi7Gs8(72>1A!&te;o?sxugB6u^FV&YN zKjan6ESL^Ui(@SZ=kBUZi_`R$GN(d%%%**mrIecKEQ=&@r~z>$H8w38FIZelah)y) z{b;;ve!nC&rY^<@mrDyj6WxDI{@S<(VLfA1HhM5@unHA|T1e8E)kE6cE=R2DP&#Nv zglB`N5b;uKUTzT@nF_1@;a6PNSZB;Ej-CN_;T6H3G>4U>M_>ygvc$vCd*_=nIG zMpjfI#PV%4W5kMJl>)R1ROTg2qSS4D62@)uYXlu>-M~-3y5C`;dKy>h3X#X_Rj|bu z(Me4fDE%$QVUikJKWmJ|`{XA@A_u1+xBM{i{U#L8+E$QJ(_x>>T}cu6!=W^~qf#dg zYVQhb!c@5y6`jbXXcU+?R5fslhYwm1m|MTmXu~LiHNUQ~bSsS32xdOvc6GXy$<E zoR$s|-dG?F)Z_8wmLmH{F>=BLhuU}GMvGgI&7BmNy^gSKlAXsJHI2bZP|}MkYNwUH z879WOFjzg2)~P%zM|71Ft&h};9Kot-XTff$TYmD|RgNOm(ZLG2Y`Y-XqFRZrI;znE z6^3ZVa+}(m1_o6N8%8bpwS|6kfp`r^6hE{5w+h;+Jlbz|1^%OoIrL%h@@1kOqaV~c z!q6PJ^~*MsM}GJD`yi%ofpFU}PdFx&p@Gx|V`r+;+X(Q&4N&L?bE?UTC%M(t=t6{e z5et#9Ve-irV`9SW+~|VM(0XD*)AHP_CQ0oI5r`t{Kl{b5e3Q(srztNzJ*6Nxa<1K?LoE@n*JCLDWs)g}B zOOC{;UiWT2ypj&!S3KeVd@tLdEd*p#WT=usVe|70+j#<}7B%FxFWJ!DU3H3=%QEQuN_@VX@1qoh8i>{Uh~B>BJfh$T6$uvqqqJNc*!*xgvoTKVIdakK`u{0T5o<|ovJ|8nIKS3I@ zH@G3O?_o|l9$=yzC&aY+2IgVDzWVzL*+ZV)Dh3759KQl4Wq)uG4n|dX!bwReQY2Ic z^F5!l6w{#Un;TnmMjP|H)SHYwxQb|Lw?6IjbTGo< z`Y>n`QH^sARr`cipuFZ8{Vb;+E}tFB$QL70LAR$DqwP63ozuM30SkwcSgHr7G2SP2 zqB)-Y{k!I!j^KXuH5YUE*U9R69K2=q$OmQ3Z$Fr}>0!=|V<~k>bdXpJ(biAU-kxz2 z*O0@xBKrQ*dMMkG_&@n)s>S6c(wdu{Ml#`Nx}G)0MeyVp!@8oTqNyD%qYqY$8SShh z=EQ08QP>|8wJ1+ZF6l?Dq+k14BvVqcC^yA&eqz-@AyX=))iGr{f!Pqm2#3H~13E_d#x zaVCkMTCJNS*H>7J9I2cr6)Lx#mKU70%7>57;|n+9m9$UZk>ib|cCdA@9UIJTeaGT!XLi?y({)6b^fz!$;qR3Yjhe(^!>EqcF=+*zuJBGc z_0kkbK1?Za4OC+`TV9$9Ajbd+@XD|qb*a^zmL~w2nm%}-qwi;$KR2waiknkWjIit zcDRmDsMTenry0iCfhh`U{zfY-5L|Gp*P}OFs^fZ+018ou%mcX0(ZGwbOez=BU`7!sTcH9&cx&B;hX)C6g+Q41CHfeg&MR?T z5O(%-r{7s5W**{6NQE3mL`>&M(7}v6v>RrbynH#hmz7` z)4(5KKE0w}9#f9?(x_WQ>GEEy^rmKV9mGnN!7E*q(4!u!w@in0A%7 zQoct&RqM6p;%q0Jx)A-U~jn;RBgAHFyZwmptWArB^$}%w` z<Og_xXL(f??xv)eD zwynkE1^pb-wDc&K@!td;L;9x7n2p}j5yMzoI@OWm=yGdF?|*dU-ojI#cF?Ph@iW7T zXyB>%Qp-uFY&3tViTGqA{hfoGUaqgCq(8Wg)B>>&JWKVFwn4eVTr*_V-T;ZCKe+Vg z_^0NBFr?W$%l}3-{1b5$O})@_mJ7#*vRa#4R?#%`JdrU;M5Aziq-MkJee(U(igH~| z{tMBJd;4Zqn?#s~X$tJzY@BWiUk(k#RN3CC1@x{!YFT?zO4krd5|?E2w2u}IO45TV z!ng635WrUDZ^Nkpi`Gw(#|<0ap;gqd`gByLmLyG5sQJBE+${XBay=8uScz+h(Uw28 z&jql3{0jG;?eD9I3(VMi4FdmYJ!Z|W>{~CvzjZwam!fim!uJp0XX*uESPu5~_KuEx z`VM`eh~-}b|KTc-yMd>*!BeXN9hcpYzskQngCj|CartJl`HsL-tINm|ze8T0e!g_w zOp8`8ofz2Wfpl@F#Y@S2em#@Za9BV-swA$8$Yq7}L~Rqs@=d{AcN4kLGiFo%623=h&?#pqK zanm#-@wkH>^i8WWI=X5)i^p>Fn_H6P^S1*Mboz|%2L*BJqCzhj zhz1$7i`F2hM8Y(cU_Fi*%4hZ?8x}MOCwv#oMhng{(|_#ioP+*}bwmxLrjN+q>y#e6z%WBjj`Hl*3NXowFm_COoI zDJGag-CbNQ880J}K2gNin#rm6D_728A|k625-MMQ387`+lkz3cD0Xo;qZg8r*ALa6 z!kl=6i(N8ox~IS{kpiI zlnne>sl$tSlR~H9<>l4=yC41O>FMp;w?oqGGj=o0EiJH$qrMhl76}xT$H@+U&JAMh z(>!VOD?7FmsCdkD1-#6NqOK9&LQ4?TQgo69Xq0yFSkqI=%-*obkI^*1QEDKT zEZrrlxj2`bB=N$wP`A*crY*tm?vP|_72&+Wvc^{5=XV{f5idlOV~$4U{&;5h_LlxA z!|31g9GekdC|mp8ofj=Ik_sY}B;Y9arI7j{d8R3SfrQ`0@E8xPWM-k@grLfp$z7_- z;Q@WkHhtqE;mK7ompFOFb3 z>9?xULjD81W~6InmSj9gNUl^k0)f5<2BW(@PR3OwEzN=>DuW*yaHX;sj`)r%E@T25yz$QXEB`NSPOIu2rFRd zg0VEvHIUB6%4UC6|1Lz{&aTy9PO=jGZ@Zw!8iOuOUXD$-=I{DSx7QT^3YhoXyF0uT zVFjB=LqkI}H6p&Y*4D3vEy{9WZ5>(+&9ly?O0_C|B>r;Boi5k<|J{k|`2IcT^Jn0H z5)_ia)&19}WxcqtLC@{-pO5@Qt+|v%fJg~dVIcVdt*oW{ta^-9d$x< zCM$iERTbqf4Sz*M6u)A^Yj}hTSQ2Rz{x@$%QFoL1#H2~G(IK386Yr3|DMss|o*7m? zu)5v{+>1B<8@esptR_j8PpNDCpb zgEN$}rjB{Tk-*WDIyxU~J16mZd{&`U-QRSq^tWNsjzvBDg7;yzEv5fi15>^aZSd>2 zu&)ILGbgME?HaD03^Ig|;sXzIZ?<05kuGm3t~Z*31qr-s`of`KU(nSR&=<;dzwVgX z*6rNJJ^}hH^SdZRlJJzBgO@ba(LKinBe*4XOo0wnEq}i~m$UXyzjK{_1&-3)P`Fqu zv}pU5SBy7H%4A>_HhFLFle&vg`S%qrqc1A*Ngee$OhMIPbKsAE=rcXP)3nu6jAQdG zw`mDpPBUg!umz6!Ir3}hIIb*j8S*mgz{z!UlU~Fl0)1p zuE3R!t)d#aKeNGS%!<`j}{fO-~5K&V#jz(dY7R_S4%-5hq42v6uc~OtR{ws;Qfn zd;*x&cB8KEjvgvA^&;uM`AkZU=6l1XGm?__^CdeTtO@B|ALp*09bO#8Gxc}@Fs#4t zd2;Ex)s4H<@mwf-yHKwF0^Ck~PAbd6*M3qH`L+K^y&KR&0J1(d-GAm){Qdm4?z``^ zu|4}ynf}{Gmiz{&PNMkT>htq675Mkm)D!@4W+dGQZVvz;C%-B*i$Q4`Kj7uV{199O4bd^NVWs}>uVXjy~ke?s3I!5>?m7XNBd>%vB(eV^eC=|1-$&(lE z5BgZRYxU;v!Qf72stO>t;7iFQ1OMxJKJCf(TsA0vlOVDe&nMurX?HLSjs*_{@}hmk z#6QntS{N{4KY#znhodiFj@lc@kua-M0?)wu`0l6duIz9-F#^)}#T!t^A6^^IlVTu%X96xfhAp|J0)}D

7

+K1E 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 z z1aLk7^(&{1i=!i0v8D%YM5b!3%6M{NJlT|~R-oAEn6lLYIH=OWU%=emSgd9v?E@0?J z65kb3;JAevySko0+EwdTgM|ZUPysXULv=!r)8k|AiR)OVGEIStNHQ1wR;M-a*&8qh z->cmrK%_&X{{#CyCIGzwziVW7>`cBEyS%s%pj`z@`&#TLxH+DvSEe6vd#k1KH!`mN zz1B~NKn#24@6#fK5qQ64Y*zY-N!_Hwt2W}#-9A`hey_7tnwnPd!2$413mY5$BNX28 z6r#&#hpP>iq9P)cLI1f8xGlVX2WmXDfAPcH^k@?>&*izfE6^UG{TBlY%h|=n76@q= zr^j(^z5$Mw`Yq!CN@770^9B6-19A=) zEZZ9um5HF2`=AZ}Colt>AWwk6arO7_;Mr?))BP;?9x4)=t;SLTHUxk$OyHsbjG^sk z;3Mc3Ik^Bxt)-!Z@dDfs6hCP30oA@C?ixxsfzkxDxiR5J+Bg^5VW4^#Rlt(`?>DHg zU8vr!_{O?fE%LZ&PUO-h7*y8PQR=oUp zBnoyQf3uA4C-6Ymz5!)frRE@l3{&wI0Ym*sHK*NAdi+D_#sm_ox0WU z0&bT;n!OJ=HF}GC|91~qqi*?s@jWE@yb7v*J+Sol?%bn@mOf?socd&*QwCj~OVCFI z1nC$M&VYZv%7Ixmm!P2F%bBg@BcO3#%6>ul$6kV3ROw)_q$$Fg4)Ubya_cl?$>KqW8`dz<&C~f%?Z?d{9W#4=1yWtA73+ z7Q_<&GYfR~GOs8;lUnX;d#H1`tqwdy{IsTN{NNh#l`%KSdhf2&cleB|KEL~rIY5^L z|M7Q}B*r$I>BBf^0bD>EXcylsFE-n&b!)YtBK{Km7gTrvY51q>GGK-{;Ef$#3fRN- z|8qPCiv54N!hozI+^y45$QfVFBnCxYXVfP#ZvfPUVT-L)itGK>2+@ zShKt5frgMwZrv-x`NTI$|`<_1)*Lbpo+n;-|#GJO3L?D;|M z1OEdK?d?G3NP=yv5_`YvF(xvOiTG#0DLnz9GzK4qk`Yj(B)}hlhMAaBxFrJ3QPST2 z06NHxrbm<6mPd}Dq4xzC{oF>Hbt>b`$)vsplx)zqPr!1ekLxrP7ybu_&c(xO7Z?T?DJ} z7p(Dn(B}fJ89>5}=~4)P9)pm`685ms)?NS!9r$;EiYRcTRduWzEbEV@`T2R!?hvX5 z9T)$p9R7(+t{@;o__V~n{*PDSXwjk59pWSq6 zKgfW-2}+@&ap^!!{R8}xH!s9RP2atH2O1DIwzfy$1(4mh&|Ft(wNT0Ad|DlmSO&|! zwG{}`!Jt!set%MIrU#G^(6zDL2Rq*iiBL7l^=%u@(!b&aNDv9nlf}fuL~vW6P?>^u z65{Eq#1k}FkO6_j1?-H3?{JcDhTPqe0dr6Cp-uf^Pc<2%%;j>BXzWgz$ zyBjn){LA$+7c`^&aDC*c|IUVs-{cF@M7-M`AER7x(A$)%tM^gH)pipGnE%o;AC8B! zu^$Fo>91Z<@f>?JAR_5>npfAk{BMtcMBDvMz4j#3cB;PV#{E{$!%LH*|1NN>il}(` z`Rl5AXB8#a`!|1mR#CjiGH&|guQOF^fUJ8m>ra3D&uFSJsej4gpFbIZz|+;wWt~$( F69E41*LMH_ literal 0 HcmV?d00001 diff --git a/tests/_images/Show_crop_labels.png b/tests/_images/Show_crop_labels.png new file mode 100644 index 0000000000000000000000000000000000000000..6c935ee36492f8e50d44b00cd74a743a34a97ca0 GIT binary patch literal 42540 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 KnpMy}qyGn5A80lJ literal 0 HcmV?d00001 diff --git a/tests/_images/Show_crop_layered_elements.png b/tests/_images/Show_crop_layered_elements.png new file mode 100644 index 0000000000000000000000000000000000000000..663dbbe294f895f852d3dcd9783cc6082f5dd4fc GIT binary patch literal 90823 zcmX6^V{{~4*X`K0Z6^~ulT2*em?RV1wr$&dVoz+_wym${{c2VJ=vsYy-8yIQefCwj zf}A)4EG{en06>tG5LE&IK;nQOdT3DK6Qf0kWB>>NASo)W;+A#s`MZf?Rh0mCy3OTp zo9t71@?tq|xs+0QkP50La(28BQk;PXHW&ve4CIPatYJ{_3jplP&~pYF4t^*%x*q2S z8#|C69(28_-wPU^54kK=O1GR`H8PV_mlJ`!xYEgMrJbUIHO5(Ifus0o=dULboAZt>TS~M!-vc@?Lq3p-y?R< zzMr+R?B_mji1 zL_Oy<9bcP0@2RnH0tH_JO9ekq0dL*k`+{Hl zEj^!?`rnWG-;>)PlY%#3f;X?Z-><$mP`)=&=6qni+FN%i>oy&ik=-Ye|NZyh*A3G5 zO=ZtpC6U)npL);R;tL#_9xyomKh=j9Z?Oo4IkLIz_i(1&h9dPp_Oi3HmBxbMu)5zn zdNL1?K6;T_-|6&jBY3Y`$y#rGKVrXG{5ZQ#Wx0>D?gNnoT7AF2YCqR%`5ljam^_|jhc-Y);Cg0biqmuMLwzfTY$+Zi{n*2SF z+C7iIbDw?#d(9S5)_&D~u6LJ^`tf!B{q=f(3{s_5S;}`vGwt)#_})Fuy$wv!wC~sb z_Qw%tE|N7sMD(ONAHb^G>d4Ri^7!%;To z2ap8ecZTq6MI!-Qb^{2pZ6ClVUgHccf1T)G|56Fu0&|D5Ls!hV3nPEhZu9X_l4--^ zes|F3cr4*Fx$HFw3_p_Z*0J|i?B_~s*Vkk1cLLLELe_oG%l@K$adagKbY1=jgxJ%X6_LkD{-UMxaki_C?Y~PpfAM!t>V-x?c{BbQINFT#Y%n8^Yho1{O5vv*OhZ^2QUl1Pv*W) zL?3~^b@lZqxh}fP&))Rk73y7QdxMes4`TWcL!8~W|2R6X|8@7=^ZmK~R=w@HBY{ps2B?0N06+|m6K z+4J%blesT{sY2$m4~*(tVfEDaUclo&eIJeG%cwh}rGCHh_+`_v?%$|nJ-v=71L z)@P-6pJC3okK?^f#P9L2{gLUL=ooYTHCFpEM&&(6<*e&^FcRI;OD zrlBd;e+kxiyR_1O-w8w->M2f|{<@g{GXK8F)pgx;<~~lE8%?Cre{Ns?+++GOk~&SU z^*XH7d#nJ1LTr6kUE25Ebi4N4?&#?7oMd12+5sbanV9~V*#5fQ_PGV>MlTrB#nqL- zsiZtEmgh|$6xod{Fddn;-8j*39nV{ySdoLkeh|6s_`_i_;`6!PENR;kOs5t>5xVUF zs|JPp`k$6+waP>)c|G6HM_|w@7taQWzHWexVu=L5!dLGr_tAb3>iazcL2mUg!?s27?^3_k73^r zhV46stFI~7ZpV5J9sV_-fcD>pvt1DyXYsk;{lj9{^Va)6jILSL5y>u zzb%FR8J3ZZ=YK~NyhZybHEp@?ZHCw(hX1mG$4!(FaMsTAWjXw>Jy5^*f$cXpHu$_= zZh#~({|0KiyO&cr+g0Q3?2%vz+&2qm>)D-t`u;726_>+-M9{?Z<$9^}d~8wrCJ@*( z#Rl4id_pI#KD$^xyEPqGZ=KWcoyd<~1Dsw1Jug__dkD5}1LJy64M_<#xSGC;`#@;} zs`{;94!5Hjc1U$~H5E|FmUUgT8AronZf6m{hWTlTjQuOA9>(xvnR-EygH*r+kBqTH zl*Y`xhRj>vZ}*3L_UO9z&U?Pj$(Hr!{=LW^uom?CgC&F*a=G2?paF^H+I6mLK9$Ao zbTXsyDmuCICVH{@tr&Pf;JU$*>!>>C?j9Z1gW7>HSWdL)APNu`>fKY z^LA)*a`Io+YJDCn|Eaj|_Otgkuv$;&@c+XkP(+9oKraySxo&_+%;I&un#uopuc{kE zb=rW9hliJYBHIeAEJU%qz3on-D<}W#is1FVz%}q^W-dn)=|nI7L@%Y^54qhJrc9ov z()v8`fgPnuPf6ym8Dw7wM_-q=zVAq1J4oH1m$rg-JH2t^-O){pjS_$H$+&%~pr_1+ zehmA<2;I^g>w^OZ1tUyLShU^GOBdiQ$6@olAQ1nyvNk7|{c*Jp z%X_`Dh`s)652wi)mj`ZqrquIa=Dbh5$<*OS+r4-UVLWeNyD!l++x!a$0obMc@|$>o zMh}PT#X#%vts%Z@AN{3HC-lnFQc4F{*5$1m>hf1D+v<_s6H5N-#A9vM^-|NQ2!7bD z&frr5)pRa*Q!~>nxT5EC{b%pRT$--%JU6*YOUj?=vRe~4gQ|djHwc+w8GI%Xm^}EI z)%n;h_xHr_+}zJqL+oF(8>TFbV7(D6QV1aUye=2(J)i5ocT~Q2&%WQ!KyG0X33#~y znbGOSqCg|X%8)t^MAB>y>_W$BNoMyhUiU7rvI3P*@ZHvT@Azvz_u{)s{X&n6M7jVD z9e+dt1b^%XgYPFqw}_?)L{5CFvkwh59q|C1m!EkrNhs@XkOYn)xSxpxB1?mJ%J>lWX)zu{0=pTF)*&Z1yekqEl!QrD&Bibm1m$kE`>KqA!Q zbh3r|U{8oGAn5IB;1I)659}lZc)?Ad6L_*Gk@#O`I^x1ud)03+ya4#7FkCLKh+A%( zoIZ=&9+ya7MAjWX;2^0fA~EX&05E9mIKPD>r$6mr9>gHlXiG7PC=vz%I1;q!N~qx` zTh2LEeuD{2m^_Ye2UuRC$3Qah0?82?LuiLk2jVnix>^l=a)OB@9M8V?dfomu|GpHw%n=Oq0ii4+Bu(=}lp@X# zGO`NIi@zYQ9akdXR{XTneMhJODc%y_42j~cez91n1<8P zph(Ds82Q}nu&=v(^yGf{+T)bO3tj=N;6ML5Em)Ja=`aS?gEGSp%od6x0h9XnaJsp< z3A7?W<8agce#PtgbdmovR7vW}=WL-IXn(@RV+jYVTn>S36uf5>Wb--6aqT%g{ysTq zo_4#PN`L2fwtwc)(U8=nzM^C5xS>c&c8zx}0x=CX40VSR$gASI=!c?hq(7DRAjuNI zcI?8|jMBSqBA3nyW6WopnZd&xAr3u`kJ{q8v2@2zJ_ZU zwrqVGI%d4r9Z(99J1a(%P;#ITBG(i?K7nvt@jJ*fz`^uW4TDeJv5Q?-yRxIfLeRZK z8}}px;XvI~&v8|8Ip~P1yy%7MvHN<<%z4=RK6mszf%2{5^`Nf>9iw|w-S6Kwv_S?0 zq6(3M@XroT%F>5{r`ZQ;AZN4SV1>jK)ytPl%M>{e39!sgbV{EkB#;!(J-0~@CY1iL zwmFTDuAY8bm>%)D0<(R;x3c9@Yl^giFiRhYJl>&}W1_`r8`0HD-mBTejyS$39wGRt zWe_Tdj&6m`b?K!8bLaq`~OtjL)2y^-qmHO>F_Uu>2~ zP$Yw9Yz-9Z3J6>U6uiwt40oR-RVp)7V`~CKW1IF<6F$8sZ5v*Qk4CW)&vazxg`?aJ z0ujf!P3>GC)=1_UTnadYlBPnql%#Ixf`3R&OTWXz3If*C_Ula>l5c>`?RWWYD_9lu zJp}XQJkzfT(Yd3eBcL?oZu)+I##=$|v`u?o;cdSR0c}1Jx5M9wt;ZVIe^%vdj_Gr5 z&xAkG`O?U5CWbW z>|Oz6oJ|_0mlZt~4OG{uS8}G4JUl^Fc>tR-DDX$Z-x>F<+0*&b)Z;t5e2uBAICG_m z(+4nLOKqr72OYVB)Qb2+EojQLLb@{oO6Eexv@rN_1LE+XV#pi2VvJlnVw$v@CH5USV^hwvtc3F?(>rSj5BjI_nV$v*>BWKjVQy~t1aWuuQ|ir^r>$osI11=?#QM6Mo-D3qvnqs;wG*JH373Bd!USZT)yom0ZrOtF;);Y280i=8-Qi+JS^lpeGh{RWkVPBMc&ytpFK8To0|;hp)m( zrc*oA!W;%Yq>O_e#cXvAd4Kjz-YYYj>=JK4)2N+K#iLG@W^(dz5V*;X)xk)^$DIb= zM-A(Q-TyNPrfD^(nRgN-5S-SAe%3$8rzPvVmyC$Z`RYO>6Bn|56oGQuUqmD|AqJ$}hSJ_B05E6jrhzE?fde#-xDaCn-+_8-=p@miBK< zHBEABm&zm|3o91uht>F5jJlDC%nntVNxMWWno-3h-7BRO>NF{sZ?z^%rkITbiSHkC zh{Qi$JAy#S=|7gaI$%-^vMBmaH^84Tc<{rT(sJcxy1r0P^+<-j2{&^Dnb@I=#{4=7K z+s{A&|ClBEoaMdlWE**jeM_8DG1&@J3PUa;#X-j=w+&H`Cr7U@!-a)#>J_67D{$+> z!(pgHd9Z#F4#kl%5XP;wQ>z?c1!$yH$H9*pihxqD8sM8axqJ4jo53<_bYw#dW5#Iy zeyCrJ1|3?DOD-W%9vv8Mq?*drrjQ8vz374Q`D}JM;ac8}*dI;H4Gm|TC*(lu`k$_MWMe2pU zr=75pKv&{lzEPPb_ahx8>BYZ7bB%_Dd%TIs?2ZAyjrUi(tP1a!HfZ%H!2ZxhdgwJW zdPqCN8V18oRrgj2F|{m{6Uv$fm7o?uO*nHL87wf9<&CB^Z$_7lL*EyE6Lbg_ARO9< zu9Nsz_x^#M#?;uj@cKOxi>dwHG3Op1037lOe&sxO9#5pR6(<45XMFeR(^=+~ATMXN zUuPY_ISHU?`Y^VS0EckYgjo^`K+f9-9RzI;_=VJ45CocxLgj~&f96>w ztkOuVMIQrUo!8GC-3#C%lL%JV0IAGtI7Cdu{!iIOS{q`022nio*Cka+2NkFUK8leG zRqL9XDl;fGIX&io@dvb(9^CI2?S$LMhBd=OG);%ke?bD3V)UJ4v@zzZW#z2pv5SZe z_hsdYSpu-7)KE81!YMQu0(tq0=hCsb=wmX{vM{?bRY2fwEW-i{OhV?S0`PVW952>} zqJ;k&hQ@bj7|{45uf_Wx!wYdB{10mX-~BYm!k08rnp0{7U$}Jei$oDCVk?T0iUxNazU)-V-cscG>?Eh%UNuxq*2q^oqu^SXuezYoE;`2( zgO(9g!FRDh7-?u|^tsg&@)S~e3|ksH4{bpf25J@MOLOPv(FF`_@G>p-qpp#`K)|4i zk-~_b`GL*~TV-;u4ekd?{5LGiUvVA_(?q2bL{QNIHIj!YB^1EJOkagbq6+1tpf0zQ0f3OW0gWBNzX*;4aKf@*{KXaMwzeu1>;}N~7H_f? zPH*a{uuo+%m8cm)_F~I_tdO-~{ydewCH1gxuj~zlRl-$h@QRC&iZ`bzM5lvjLq>GP zEQPXeYirc{$+~EfjsgP<@$+uA3yVCF1SOoA80DyrVn+gOPHIR))gT?7K+ea4EPJ@` zoaxLD_LsVg$D7sP@HPVGsVpyCKL>2hrj0f?Gv`?>xXKbEXFRj{vgyNi*5hH($|KGx z_-L5=ypU6i|nw zk?#Ke6!3~rFtds~qVWmh)FllOa&^7%0%N$p6xU8jVtB({^3H-(9i;PBB!mEJ0UmBh zPdDIaZWs66FC+ z!Heq9P>>dNhr{YK{EWly2F1=)?s!ymjefm8EJ}a$N&7VU zV;z?aXRwJ8b1v~HL@`hb7Z|DWhg6-|Ce23MKsF{!B$x*A^h%ju?V`>Z7PvDfMN#|p zA1I(kf`dyyT*IBUlDA7l zvmqh23aU{5ZWrLz84J*Ha%RMeQ@}6p1-X9$RWMKsXEt`EB?xfl9e9PB>LR=Bd1RU1 z-uL3W0-XD00092FCrS58p#k^`=;{o z+*Pji=F92868k{Suk31cX=%A?|6xL-a-aN0r>Bc@;DnV^;dvK4uKOvsI-*c2c(RU_ z)#6&N3mPva>BxFDAF8Nzh)%ED<52$;Yt(v}<83?O=);_avh=-{X z^2DWs)Npz%9af!ahF5&*XB{hu9yC+VCe&}{N2v3gjoVo|q_S6n40Lrt5% zcFWZccBdsL-ripZt^J@xJ5olNfLX%(vZDhx z1*+$AEe`9E<|!HVE!wCOTzGtt%2UvhBNh%bXttjakenK!eJ24_Wk19J;vxTXrJWyW zqm2s&O@2f{T}Po)-(Nqnmu#ZW9_orMGrO@RW4l&+o(rG*ShL2421&=RI@{$_twkp2 z1VcDe;7LNML&euK5rc2@hN@+aOVjB5n={+xMsh&Bv-^nycaZNVVdTG7_`_*H z=l3<+i35&0qXCHDhE$vy>vX_)WO84U?jT>Ld97kUJchF3lq}Sxg7F5O!RRl<%B_eT zKc3A8k4Ys1fLaHMX%Tl7!0(kj(=R|zmV^uyfZ_Ze!WNt2NY#?t(7eINS`|gJVjGRZ zqL%A`pokA`O!a={jU;e$GU})uxixMHTAtyA4OdWY@Ns9nrZ(?YGif?7Jo<=Rp8v|J zeCV$+SnZrX`x|f7v-ufTj$-G_BOYar}l=q zCnjlQ1V))zK?|0M>>^i{8_R!#Wk)+HXGaAZ$%}0&mYAw{Dol{*`H|uYbZw}_;B6F?#2CUvoH@5O z{;So#G+Uk^&eW8$xIzSo1cRdG&6iH+@VM8n8z^odcguNs|BxCpKi@Dm*EI@b|Aou2 z79u69&8EI`^}>#Bg~zLw6qe@8j&?L6tiqIp#tMhl8{U{Z8U`IP zx7v`9p@Qj$CuIWn!+q8In$k3h&CQhu+eL}52|cBZxEv(6r70}zfhVC5phjvdLK(7o zX00H&9AZDg)($_M45tA)A+4XHtJgD5({JC5)#5l~)%^y9gExv6H!VK4 z%V2ZnN-4qqgW$xUM-yR)UpEhxXH&LDFu)_!f`)_YBLrShYXrxJ>dYP2J1b8t$fGSUU= z^4v~2{3sMtj+fsCe_Zc&NbjSP1{Q-bmq4eE`_!+})(K)$Px!;jv6 z!d|Jq4t3c;5lUEOhTKq?kJy#^KiX!f;Y+4l* zCS=oxLKWMUgCk2tcynoC2Q|!=ol+JUy|`CZZPdB8uDuz|SF2&8mJgdI_>-~OxNei# zn=C=hUzz4m{R-ccWvhve6M@jIYMv|QA{7Z&c0awnR8nU)ehNv+U+Jc8)gaOW@F_e? zGvakm#FAzS2#-49#Pkw5H%^_zyR9{!>9Fen?U@ZUnL)T0bc!cq3L8`gM&5ZCiFD{1 zs$jbe_?y(Qve)Gl%HRX6YC&4sY4dmZ+Wd>2ErYU#-@qMsG8Bu#6G{HZa1>h&S~(8Y=0PNu{8_4k$GL&IZ#Rvtk%3K z2Jx?>B8X)AbIL*c@gYjd$eXFWBLHAE?bo?&*LkmUYX7j7>dtJvvb|Ma+P9W&^^R-1 z$bRS;CTCQ)m7WiK^1$qpq}Xf8Em7+uptg#D8S5pURKl;GFM_MYN0H-HnKJmr09RWN zc{j$!#tazmK^*S;#ta0w0-T5<8p>NCEtn_45gdYOu2FDQWbnvP3Q1K=^q3u3I_I>z z7DXGtohyFV%1$AImPk}WB0sbY&vQhimn{j0S2$9n(v$w7pUM`PUwt3nQ|PhPZ*jNg zb~4yVz9-HFByNTa^oV6Y{Q!E>5NI?t+X4yJB)aaj5jenf7*h+Us(GQvjMSo*#FF4GKLxQ<<%L z&F~zyCdSyv=Wt8G1kpy^c2E~}aR*A2C%hL?u}$#%0h{G$(^cqn1aa?m6omsAp##D(07mB`EK zzlso8Mk*Lp6^A&xRPz*_*RF(kM*zC8YhWd*P&jJ?tc!%AiWH$WIbV)2&Irc%LD^GA z%Z|bNEI0G=>(E=TA{>|~mmvgKoWH5IkGziIj|M)6q=D;5IyiboQnj2!Ze0_5Hzda!`>x4ypnk377kxKnGZC2jk65G!gkq%*~fs zI{{V%>s1G~7f;2J@>MNaLncx@X2>i%TUfDPfp;tm z4lB+Oxp!sAGDv_mSDwJarG%255})BaS*6?w{4B`9wi4KmGn7K0@L)G`-rJyq=+avYVk6-^8LgpQ>3 zgpZNw){M3GH?tdsHzE$4)aiw8L>QDiawh+k#xLN- ziIygI^_{R%Dus2r$PdN~cBg)G5de+MA|PYz;*dkGP$8Jzg`+eV4q0-l-jA*I3HLNy zMcwvMG{6RHxiTa6>~EV)yeyt(3nJ+TU4Xk#ddA!shO3SnKZ_!qAU8dZ`oPpxFjRP8 z|I$Vx3V=4XX_ct^G3ET)cjxcuee4sANQb>Rj|V^Bl0ZMS(0$qtk2Cx8dx?Hd=;HCk zy-c{`ab0$pzu_w7lh-1@KhVKSs7aq_ebHk4osnh1ITsi$fJ z3k(IkcB=)WdYd(#vtFMchWtC~CMLeX0wG#=0PDfgDyb;;qGR$oLtg)$ihP2UJpqoC zdb~6NpYYHkso`t{#-qwIvgL&VGiU8kgRMo$@JS+05c4&jq4G2|Qr4Nf{bHY&s?yY>b;h7X+Q@)63Rr3$0WGx*Q|2;^Ld7(+ zKuHO=!8#Sf(8%W!8c~EUj!=V8;zK5*hjwFqhJGF$9t$MIAl6_?m_i7#K7%P8m?#%b zg)Tf;QXE7`JqDUQxVwM`X(A2S@!lD_1>DPggAt6*02MnTwQ+Dg*Ucw{7R*D&dWTU0 zrDfI!EOdfn!WGveG9;=2BOuv=<*;R|XNz!c&De7Y*-y!JN||x{^XU*PvDl<%k^5g{ z9E%DV2Vj$uvwyp$Gu24(*x7%7?NPL7`CF{b?A^d&wYJ$G#H{DIUwgX>I^1okKA8*# zRtzvVwpEPc48vR9idMacII5P;*tuT`D8klMsIpmze3wn(wyMO&h?nGmw`~aZh3`$F z!gqzB7f&C~F&ki8Ueunkpuz4GiOVL(!McrahvVWy(Aud^L|D@?DQ*O-lEGUcn~5-t z>u>UD4bWHqnn{!60>GvsOBiNF56w-q5f-N38p1qn6tG$)H6?>BGCyQc9}T^ za?I?87c|aHWTR_Bi-w^nvNW`UwdvHbC)Aqs?qO3~3KP__um8;Wv6YpCwY{myfO)#Y z9@@fj@n7kaeA~HygUk;kPAh zWs}&2xbBLRj^Zh|Buh2)tf-3Cq=vwPi1(qd$w@FMOzlY2$>F7BmEDMw_Mx!2Z0J z%3-WSh``2hJy=u+fAP?ovR9!ttr}@?0juKkwGpeL`T`pTQ&3!9&IIYl<7K4nCgc0h zr1YGm3=9=KY@kUKJ%+*cApSfc(U$r+llDJ`_L zioZ(2^c5(}Ev~uSb%v7RH2_0GiXq3CoU}qU#p2$64unlBO;mi&mHI_g{LbG)LpIC$ zT)sRc{o2UdgUFTC5{X2uR~Pxl;>{1CTO8PRp86cy;d-@JWeZYZFZ4#(8Gl<_@D6wV z=uBXRdk6R{pvN+4CrHm-U7c@VcF$|N4u500{s*PsuZ0u(8UuAIg3&{K2eZt--`kBw zQDe1t}0Y+T+BFm{Z$6$bI(N&G+_ep?uYhAo1g3FPqrC=Z0Xu((&A1IRE&SF6QNs*a?nJ@5&-&W z9&pY?o^w7zwoFiPbE2(Qx_vcc0Lw;ubrydd56EBzFfUTFAcpoqV21qVU3={9Bjuqt zNksaknB+JR2;Q8wqIElsB=G`w*~HqD!leS`TKdy zxIq`ntOKf@h6i9Jo(95ns4Vp;KH$tg=MqdWdY^b%1`Iu!{& zB!Yb$WS|$7LzE#4izES7qpf0?#l)P>+df`rPVHsIh<@5sM#cE z)r(P{QJCNZ{O~DbC%>e)!0z6TOJxc8Z&RR@M9dY9Z7##l0U`>x$>Xx4~ZXrI^s>EMdaM@m07htU*YeFMBAGTGK0ya&>=XzWrz6y=uaeB?hd5Lb0op*jDgav z``vpa!8=1~NdYT6j!kXHE$_YRr=ag63-r>LF9qh(0e>b9X3X|gq)wsE-G z1h8s@5$Xco5RgjY!QJ?ipbXb49D_q-B(9%(ac~7fJy@czuE82jO&LZMcCeO4{i9;%*(^Pi_ZF^u^SP%}?Ok(WM-Sd6%)NQ9gA3d7cds;PfsxI#zG)%jT_)rpD? zLV{kgQL= zf>Ek@|FtL`NN#kJ2~-#M>skP+N!h<&1%Jpo=cp=hd&??@+h0i zYl$68u$AY2Nj%T6^M-8akdz+weKg8Uf|46`lk8re-HJl0S=GN-s@j|k?G(FR)+zJ- zuUv|i3bK*Pu1c_==$@3$eR6_LV{~zn7|-3`%$!$$q)$!4tmNrC9D{268=}}I%N&Es zz8P`?YcusS^JguMU1xQcUhI%k(&F?Vp%INg5Ur?hCaR>kA>dRBCWLoFNXzlXqWzd) z{{+G5Ve`vq33$q6WGKIPt zA;^>$7}db4xYCMQ*8I(9_i6vjAWe%zXv0*(SJN;ZAKa6B9;K+7yQNRUq??$e9^WJP ztwn3j5G1WAskck+lNFViwLM3L)83JXIahZ8j^+Y2M$7SqBNP^jZ4wF5kgE-`N#m}og5nN{hs^Y zFK|5nyy3m`g4WLG#xTCHXMIV6jg}b9?h%0hQy2ew*F~^W90!rVmhSoTd9zQQu8EZr zk%k0E2xk$;;0&9FN9wV?N)FU28?#y5rl8HMd1Y&Zrw*c*PJb%AIp+yC8E^i?CyLu) zHV}C(Z*JS}z!CAXw=i7471^lQI#Ec8WctSN@Q~Ta#1pkr-jR&PsL5&KsRaCPTpGxOU z^gtebf`OqL_5phjxkUiH|B1Wkq=0U10goR0O5>V~lev?(MxWk#`BK{9ims|qg3=?E zI9{EN2B_DB&@wrF+r&^ZqQ)+AdxT2F@t~RS{GUyu^8y5y^?7d%?&$s%DfHy#-&C2_ zSm@&F^_VE-Sk@ho+FbhJ&FA8|zLR#j*+#4%CZM>Hr7|5NhT$eFInG_sJ`) zbjZF8=S6go3`4aSS9?5_3DjSnOi$8s_^n61j-i=^UB_Ut6EAx-cXh+GX;1d;$yS^K zQ)_pN=|&9Aup#cIMwTOjBzam_N-La}O}Y6=DnZogEG7pDAv)4(yf{^^h7eUJaxC^5 z(4(G!B^9q5S*ZfA)bH(+Az=6NR{~voRbIIKOjlmo=E6A z#vC-9Ge39F!E;=k$;a@k_jqu&*Ry}%z+{#4m%>cicCJpsR~#dhB5pZM1|w}CF)@0O z%R4bwT-To%dIK;~k)MC7N6yq!-Vcz=+cCE>JrnV?*4v_O)E|&ikSvbi&IPGiXEFGN zFNo}aAJ>UNiwz=Pb^Ni~uSzvV_rsCwlJ4v|18a!qDdV)?Q30r}#K;&xWoRWHA00!c z2j5~(|6-WN`f3DWOjZGe4>IsNTshQ$QpP%%?pT;4&+@~^S?>0q!FY@(hJ*jEehpDT z0E5oLbr~dsi6>ucRww15HX1A9DJyN)sw;Gns$e!h`GJ|I>RA?j=}(#3n4No@W-)P% z8kf;qBPz%(WQ6=DLyZ?wq(s^EH5xd@**l^bxg_7@bf5Ulf122Y3#n0|`8Ih)OiVjM zUyrM7p|D7KG-h5+wv3DQQ?yQclkz<#Cmx?qmmCZ$n;96vsUjLw|as2lPzS>+VgnTWT!(?Mc|h;o8c0UmUw= zd>S?LV#56j50~7^0h-99{*s3PDzj|o;>38aq8JGylu~4eA8T3R9JHfyDY;XYKCV`7 z90+knCm}D3gejeCPg2q5ut2<@{3V zZ9XpwRje3gZP${qF`9#JJN@|~Br$*ZX?F~k)W$Yz5jZMMexyKVm7c#Jc?k=Ggp{2h zBYBw9Ik7&d^qQKr?L8qW@+y2Ka|8WHh!C|5rHO`yCo~iByE~h}>ykW^DaNqzbiDO2 zWoH{q>CpZxEaqC64h#)DjF9C@jwLe)piB!wn4wijxIjBlcG<*2Wtf3mMJu!x6~Thm zUv;%+NxhIKT$O^w{t}~W-FCvj7reYpnrjIGcDm+HnT*fhlBay_cM(q@d~(hZH_+%` z#o$J>6D{R%Jf@fNyP=zVFcH>g&&~F~MQ)PE_SheSVj>5N-d7}fhhi>oIM}?OoF3XN zXDq|8OQB`C99H{D(f`QGDER~1YsFesB1EEP(c>-uH$D*$O6j0u6eRHvKy=&65yYC> z{j$Uya2S9AofnCSLtP)3b&}Q*yb|8#S1=9`|3hXL_C`)#amE_q8S;pHwLd{8+GU03 z7N7UWxxM%rEMX?>b+lWw%R3z)!yHss#Dl#q8u_ga1;-VcuGYs0pD4+SSMU@+5Pp&d zXdB?o50#OM*>Y4j6ZIsKGARr~W01pCW6#&jn8*5b+DV?bbzskvTIXh~txE1Oa|DY% zDg4P87nXAdrdgIlE!nl8%)hVvAheuuCKtz9oKCB8|9UOrR|)gIUZ0yOXMNZF)~Uc- zkdb1${G|$a?tr&DZ-P+SXX80{2O~daF8^G9ueiIRgAk2W{U(8D%)3;yipI{qx>;Dy z($ZK#X*I!XsFXSnDLM)h_{V>tV7Ly3zJSv6oRo@-ufbyfY7DwyG5bQ%nnapa>Zk~U z&MN9mQPmTdS~L>1*C>rSL(p+qwz}sbuCtwjR3@#Lx4CVRQmyISar%Em3w%&-SfKwiL>8w2;XRoJFUHyqf1$ z&n1c?m=u|C*=O5wN;7WjY-oQAm=|>nwRxs=^Zi?Q>vf|_S`>O-qf}o^uK+Fe%Q=bV zF`Umr#+E#qowu5Gs{zA&@>0$FUGG~+?|R-PTm}{1B-8_V8;c&+ibS7wg5p`kgc6IU ziKpi#^ISm}%iLHeb9uO%VbmE&8~iUu&ABHNiGx>Xu3+7x-#ORmY@+L~v%`_4-fBFt z5pRlet72Bkc@6iJuw>~68%faz8w{5fjR!IXYbd#pT(bk6pU440D4XOc-kVxn1yXt# zk^^hl?OkKH(!Aav9S8(`<9b;bu%$UagF`U}o?u~c zQtO_4pvY3|`; zu~k36W*N<3Sr4t6H(FM8za`}t-?zS(7%7rBH?!G{i}DSX)8zV8ixEdFY*(Vc3}PAm ztCrMAEi6UsRPM(rO_YkYH1d~IsM`-qr<#ZQC%Djeu+Ya0QL@_(@voF)Z+W zyXYB*O0@ybct5HH2a;ScvVT>%yYv4RH9zrJ;CF&d_fVdY5j9s`MgC7?_;d{vH^)fn z@8Y)0BD!Q~|F$zaN#jz!g%%b%gg4f2p2a%U_3k_4?ET^Qe@1Vy7}c8QXcnYuVN^ox z$CAT?yXEiMlsulJJGqjS#kImjCA`JvES>&eiMR-OWjd(Evcx+5lV#&-Y{LMtM5aK| zU-@g@G6(pow+GOqW!|y_fz96b_Lu{BBW--e%WWN(VEavL|{D zM*jNbq64L54~0nC1z8|`nmxHRJJMOW z?S*8+;g=v)HYsSmD8ZB>3m@(IW3d{CcA`&KSgkq z+Arh0tc8J!j$l@SXiLwXQf}eV{hAM%;nR|x)Gl1TVp)B0tUNRWUxDkR%042K$2Nuo zJiP5YxNqD$IsB`j$NHQUWK~sbbNJY>z<BtHPq;xVU8sjQfLkiM!AzTOLRWBKoYs~f|d;mR` z;7bf=#tccZA}W^;a$Vxc=FCl_=g7Eb-BMSe8G zb1+}@QhFex6>QbPW!bwZNdbfb3)yP(uMMjZ%|}2KBT1(9rnM7{VTj4e`m7X;l!VGz zhH5fx?%=QWXed|E>3AhaH@?y#!YD+lhJ3f`hi1z|74?2%co9m--vGA#Z8MW*DLjV6 z2M0Xh0lhKqTtQzSbMw-qx#v&dNgWPO&SSVN9_O?EU^p`u;HgaDq4rnt|DE0e?qzn- zb$vLQjgF3veRl+ZCfeE(P>8@cR`XiW^D{_lrpl|wcu>9n3M&c|kDcur<=pr=YTQ08 zp2}SC92r|xM*~a$xP%jCgZ3M*xbiuLb9!VwqHzWcy#Fp?p>Uny*nsyxW}w-1xb>rQ zZ2vXfs7bg*xDWpes^L}ugU_utC6tRFzGAiiNlZlw0$h4kp*voPG}mGI65Qi%_xTHJ zy-UL-wQ40vX>sTYX4HUyr!qwyqN>h2!0Z0ZWH~QQEPK05gC2|{bFfYFkI?^dbXHMq zbz2z4U5dLyaf-XUy99T4_u{m;yE}wHad&rjElzRgr`S#JOGa|?b~4sJd#`+RF3YBw z0n}V2fO|~NNJD;{m5h?bE1=(O1Tf1&3{@%YK(nzfxC;kZp(v7{0^&K~)WmYsFxfMl z5i;3*g(b3|=J12-M`ak(8c9$@iC4rPB?tWs8H@H3V$h0@M6qlT9j3ES3uWmvEjUF5 z5dA})?pr@rcK!ZA6RBX@`~{2y|3iAgVLXW7PU!#s5x^N;hcvCb-(MFCJ|3L^i*#=L z{CI@~gYKQL|4`lDQ>ky!D!nKEJttr|E|V`RBR+Yu$7$Etf4sizmS6Y3r8pTBOu4dea(^8 z(dA7$I*2C=*D0{YNYUi5<12d-N%llGN&}4(TZ<%y_MgWKVZy<{%z(VxcEPZ3QyJuO zPS{1Jwu9`KSLNm^Z<{>3FIh3eE5-UA%!D?lnEchhgqK$-jUppVlj@S1Oo5-6$Y!QR zeVV7jerElIGzLGr=M;pNBs|TYuA$Bhg_?qK2a0bWkcR~JaVEb7_q1od`ykm1zot5x z=O$@zE5(X`A_2@X|EuIjMGRcQzUC-zY52nno55{+>%q%e%3&yF!q>_u)uIpq)%^z^cF> zr(wDSk5(CZm$>XW(nrM-q2+xT`Lv^ns`+xu$>1z!O(6*=iCQl6hLLXkg7vstHM@Ys zjiRXS1Y(Ls}rZ0E+Lh6@Qkqqc=Ln+D* z;MNg%^5ukgcZ2|u*A(Lh)Uvo3@T?F^EmNhJ@Z};u&-@D z_6~aXHU<~PKljJ>_4nu2@8_+gBHz1G&8)upjw={}O#onE``T|0+1RH_XU&rYf}@&? zwnW;+qJN0X4g!c~Ka$w$Z66_xDcFxdBNg*ES_83BS>xu|Sh<9~d!xf8{7PSd>jU!h@b!NvMi$hTQBcto+^M+Fbc0Pw(|kJBAPvT3=$PVrEBzl@ z>;3D~tp8X`=^a0fB4h#|u}fE4bmRA76#Esv4=2_2fM ztsrW-8OHYmQPV?^Ls0Kkcc^np3L7n~+2a9|K^?XSX4c0vXiw_|ECc)vN=xryYF z?YN&2m<2zU!K68@$jdmGgQosr3a0nRz*PUmyL6__9=X|h9;AzvDmcY2{aYa9Y zRLE~u=otd+6nQ{Wpr1T)^Y-?x2Y_`kOt|kWPd&pU+#o8ha(K$&0|G^HBe;!Breyx_I9ia19=@lsQDZpIKY z97<>yazxY!s_reCCC8)eE6bI!p-5_KggXB0=@#2Yyt2|72?KEZmwvBxm1m~yxM#Sm zlhYG*YwK%G%}z{0u%!*uCOrl`*QS+vt4>dQ*+D54xaGAkL?#xcg2#c(7>BD0hgJAQ zPNy0QU`8g0@m?cs=@fn}+wJY{-gYiCh&;nn3Z?;MLBxpL@#18T!7U~|UnzxD0nP0y z*`RRkUPc%=p)=>;v1C|_u50e0k~d!$LL7Hx>FId|2tgXtaMoNy$3_%(gcU&PUX$#x zLMlG_NGXLYs99ON%XXoS;MSJ7ltBgQ1e>^09^3+AX|J6$o+25jn za-LrBZCA!6ZI8DqdQu_l|2UMsOu#|y~0=20PVAsuU$@}ZGv!i1kSe9U5O;1zy zkPg-o{425DhjJbgFc=>Q)@1zib^P*Qt|t5bU(fe>l?SnI7v3B=21a$E0-plhTt2zR zi1RltKflX7-7!-wC4p-_1OMA~5hzsr_NF?~@S2XO1AE*(ASp6rNA4*qayu6h!etFh zP4g$2yWV|};i-Vr_2z%HpAX0mP57(g`sY(C7rpBk+04TgB_M#^t>%@GvON)30lsZ1 zRLBkJU54AhXC@}!j-+h#Z9hMy)mw0-yVINGjSkt!Z{z%6-1Bgw=KAHfQ*bqr;hE)= z&FA`-Sn&tI{{Do6WU*@Q?*JCPb`|eSPvGmv+jP*=qR8ta+2bhL=)o-l0AeOz=#}U5 zc=w;M0{wjs9c<}2$^E3&!RK57Q*ycBP0(&EpUBiE^_7nxqI@0E}#}J=3)xVG;HVsk?~vV4yr>85PD((?SR<%+iQn; z(hC{x(wM2Gb8&VuAwYcu$a^%F#Zo!PAvDX(R3!;HOQ%hqnj{VxjkU2puF`dM!xL~& z(RHl#c{G-UI%{4OcJoU%HZUy+b@*q=w-~IK`#nD+Ebo=>!Y0ldeJF|^2%F4uaZ)G~{%dEv0 z@@NpAluKG=FH;tR?dV-B3a2;iwemy|6V^Zraj0n4 zFA63&`*4E{VkfSD+Y9ceKF9sfu-L(>4I0~Ky>77e;&lvc!uluHK~(VxEd}eco&$sa zKG=Hm#CULk-7a7|5p|iz&F}uy1#p0DZtT_lWX7<|=N9ZwB6EC?88#b(PV(|@>Kv@y ztUw_&jXz|C@2B=iQUF0Pm7ifYloJf{XZ0t85|Wko0e&#eEw}lirV9Eg3j;jAqbN|D zP%2khgZs=vn4{&;;^G9&8_QQS*D#RC7gBtSncA5f^Jeg#NP;%Cg8=9|(M~if^O?#; zo^>wbMNpRXh@lM(4p~&N_TUut5?(1w$SGdcd5U|BE*Ffh;fb_h&bXded>qSOW|4TQ z`v*+tc}ora4!2-{G%39&6>xSdE6TB2k9x%^NUD3GPENt9>OgzdIkg`a=2D1!rn1WS zZ13JXZA6^vD;v8E1R*P|GC>k#5`hV)dduH)(X=*ALoK_PIg%z>LhXj|IH~ngXRk7> zzv;)@65E<%U#hg=Z0YEW+E^f&UXa=g5qiXD#?WTRNZiD51?v>ge=*?2BS%`vB2MTi zP=BVyk}vgMfH$m4&VGwvFH>X%_+$>@HUm~H2!X{Z+upm~VBHCL(R_Z7!lG3!5Pol} z5URO;)d$;f*6Pjw36CJcXMMnr4Z**sB`SUkDf{RB4WqvumJ&&0bKMg`<=P512Sc-= zX=!npgk{bjj-}=djMTq`;z;BRWvIlKYP(_ZVI}o=gqzYh$*iZf zei}QlYXJ4l+SmBATAb+wYFZ_>tc|FG@89Cb-+$7`Sck@~=_Qyq|J3CrB<|%~XUd+_ z^AEi6Q`}bi31JfaldB(&sJw6)NO=GEtG8ToYBrT1_W^KyhFKmE$24_pfCSLn+*1=H zvegx?<}xr;P$MR(`;WiEV(6=aXcIT+al5+9tMqNI)JaW4nz>b4GHHTev^oknF*eki z{xpM_v*Ll$xcXqr_}fqSA3hDs^`T|_s0H?J^nMtBOa{HAs=TCTl1VQrfK_4tgi-(S zYUb80@w<$mmkh8}>%JJT8=;SD)!_c0hG#YCef9rJE$|To>gL}z_Xj%J_hXI%zVGjB zL5Zia`c@co3ZUj#;t@S)mWTqXOtxXk>P%a+(bJMSx5>h693sB&mCS$kE_zbgt413w5To1zDfnL`c~zsri?az|7vT-eWrWx9cSrcdF6sKn!MhB)TuCYY;g507^>9>M*2 zU|6%hI5J*)<<@w;fwNwhMV?z2K^?6Xl9q`|plPNI@O&UOgr_+~Tj7A>o*uAcF(ubK zOyF05L28r_@pr6JGZeR#pT>ZbaSa#spc@NrCC(e$9tY=DV`(IDGU&~Oj35~2&bWU0 zPS3t?%?6%$e?I{qy#75gA?eDtz?Q(#c#_vzu(Rp^vb~e*x4i5B;;(rF|30(^y|xAo z>jVsgj}~gIe|{^A8?^;pBp{@1LDCtxPnM4ccEhyOv46d^RLJ? zRK+F!kVLY&A!#l+jJt_IUE`>l@Kep<+I>xG)&zbKf<3Ho?6Tuz@hFmAJtOZ_5rPek zPgC(t_Rl0(Jmkz_$XHdiDCU?9^^kTDUAv#RdzQYA#p%M;gmA-cZOx`gz|A4YMNfrY zy<|OG4latA_8@(AL}+!EbSThP!F*7ZTWq6JIuAGyhr2=t*H7(@l!DY0X{;0?J}_9z?u)z42Z-luHD`?>V!_65p~Twqr}7e9+r>@ed?q`g#HAI( zhpLq_8NrprD$;A5MBWdMyf_K`K;}+^%9B5yc5}6QZN{aO+B|nX{`=#;P}Be9ZSlnn z_ydpeIuEA^%07VP_r~3u&9CTejVX@-B@lDt(}GNv(f#sqb+)mrL#H_BV*AJU5)96A zf*+pd9_9)eRmYhrWskbd+{zrsm0ww#-1GO{Dmn6QRu+unmZ}q%491fFiy^tuK7Mbo ztRoe{)$W@R*nLrMX8Ya*R@iATR0RF4`21&VqlfJ?tN+c5r2MKa_o&=F3?J zU;7mh`xiAd*va317n-cYWtL6&Tmx(ym}X#)@cN+zDMb--T+^RF-!+k?q*y8kSGwZD zQ;#I0F-#Jy+|JzQdsAFs$w%ait7sC5`9~J+KH62n*q;WQLV(yHiqQp;pSN#6?Yw%j zj%o5Nx}#WgD>r7}LtzH(G##3BqvLtw{Mk|HVQG1IL%y5TtQt3+JX5E93{t%$0;V}1 z69NeEq^_0`u(K>W3#PxL-oS6kOh zn-+sJtKLi-N=X)U;cu3zccu6=S}~;B#K2iVjemIDYc_#EiI9}@*vi^3yHNf%yIQlpbvlV} zH9gL7?58G9-+mQHS2k{#?JzZD#c_)#P2Z$WyXES}Odsb=6Krpd2Ln47cH|0NTCL9J zPC4<@gQv8u6o??JVUYx~AV~HG&K+29k2*HTl~p*+X^;0T|pt)l;sMPz4t_0R13b zDJ1yCGpxfQPln%gU%#=q_xI!DGV4k7F_R zUm+dMyz6fl=7P|Rxi66=`#UJ5ydj!`URU*dCz6UhKH)gX_hC%^@J2c9}dbT@tP(4?Ee zcyNRZowX;_87z-=K0}ON4Bwh2Lt$-Eed8^0zDSNWQz(QZvF?6YOu8#sk2-;EqZM?x z|Gr5)EOwLyQyqehOtHb9g{o#_D7KQaZ!>fRwf0Y`I9D&0XS&VNm6zIVW${vGw};!W zPNyY;39G^+mnpYxQ@wnxEhElw-Me$t4k3T4vl(7j?lc>9JUy-KjRwmxj7FzzhKG)8 z3#?8Yda?kmeSz zFEtDioN%P}sxV7d5-` z?O!7(5g^qQ%35e!Wjo=si?*XIr($YS-rz>#uEm!lZb=Z@5+ODNj@>R-ig{QRzhHiG zfdF83!t{w-%tukAUZKEGq}Sm{XVfwN4(6GS|Fa7%jdGJAIsK z%k9#{kb^$7It^zgs|ba$v^GZfHKZ13eQh+xL`Kw8ZCS=g0{W6~r(v<**60j)HA46V zLQWQ3YDIeEN?;ii36a-aQcL1H4>>r1^@_~vSyoJWgrGfWW4$=*YL@ zJz{=ro3?QJZS*ukaWEk})8uyM+iGy|EZpJwVL*FsNR5?43b)qbGlTsyyX6hqY~LFj zho7mLxh_xDlp9dZ>wtY%R^q!tM4ukxsoc?n)$jKK;TloyetH-Pvy^B9-dmg7UkTL8=>>g-Uy@DMm99t`w&u?HQK7TK{E0 zC^RyrSW3-}x(Ms^6u6cg6;ij1Qzc30`qPU>9WVUppO0Ex9ixWn1!wi2ct zG+#&)5Md_kFb?JJ7~ahWw;gnLybh zJ3rZx#!PT?af;+iKA;=*OiYGAgxTB_-ka@I=-<4*fznsJ$t@#q{s4>6IvSx+ajP5X z27BI{?9oO3I~{Jc&Y;)5)dPoBb(>L@O9!@7CBqIyl~__*e?!|lv_NWG!s{Kc9r1!g zUQm)QfbziCmIUH$&G?qVBCQ1Xt@6=KO#Ix*zXwsSomYDbB z&aO;c@FU?&qFPTfY{>=Z61#&GYVOMTY>u?Z0Lfo*HFn9-RO(v5c$r(fwXvrQsmI=t zzj;vu)jz^TM0;@-mvOqf??zGkyX|sz*bGR|G7ra>0 zatoZMmsAGD9pb3WGk^Sn>)KSLal!`<9fX`zeNc7#gY!hS>mKK^W!UxQcFM5?8&tF9 z_R?3xOA=F-uQ$iTMgKXmnIjg9D0&66hW#krk!<;!f_XB4VK25oK*J|DNossI**gW! z7%1GKI*Gj4t~%{{JQvwteX9 zN;+OPmbo7a7yX4H)QFWWp=t$KL#d4>CJ-M(!^DIZ0oBOLn^8EaT~}8(hqxdg=8L}%(AcBTedxL_du<7AF(IgtPfPOEFO#s<==D%6gcnl2 zC@nLthTI1euprZQL;uC`itgXDvsVG73gkRLiJws*Cqfx3OCx0x9`x?j)BfhBaM)!= zKyJU<4Bm__%+Q##msLWos*CfVeDORau4;PggTiG(4uHmk&(-e_r#wQTZQ#WQiQ>V# zfCYJ3+gp0D+%ap2{Mf!#ZAlR!qh35XubCrR;N3f!J;)NV(X@(n&8qfveV|= z%9HX3{9b?Wk?0%*f<(uNtLU`gYwqsNF5~cT`}EAeb24Rl>FC3^%sP4b@_AU%BpZ_C zVZ#2Pu4o^us$9A-lDcu3JBs#P)yPtny0NMwmCdM$^E`q|PyJhiOteYsilNEwBX|JX zj?-FUeNjp|$5uA+(aP>34*yHB*)KEs12aifjSC=^Is%~r(&Ch#6hd z)YVXY_M9e-ylR6xdZ(gRO-}lpsAzkiA(%!uMYmE>2lqOTEpHkrEb-+gv}VZ-Gs@U!Bz!Ra%)Ht|}@2gIp%(;v5^R zp?VFtSyrY{vTKK`j|QkpN1-@@IzmDQ%nMuDa25`h zkW=^YH}j0-T*do*&NtRf*E0XIh!9>vO(VXJuOT zlBU*5&IAfIgRt9-fC6<{y=jvS`Uz#RZc$RvPS=%Q%J>H(L@@n^kTsYe7$EE;mYUR4 z);xs50U#>KAM=Rpb(HA8-u`5CV5CE`3$NxGFVXA#^VcTp!8-2hyr#3x|GoHAwjt($ zg{H+y@v`_1hE}WF${MFxT#C|05jZ;$zVVxl>sMVmYbWt2m`5a6cl57tz+`Gr!P@&m z2akEE3XjU2t`FQ-)Fcj->=Ua?M7Pc(nyH9aX6x4a!oQXc7$lK?Df67l4mvbSz=rhkj4$cK(^&PtgH$N`LXw!H?zo^^ z_!0)S)P!7QE(=i?i<#F~ySkBs-z%&@t61Za#YH2>A;4NZnwiGi5e}V6jS6sqY?klL1NR)9*8f z9lmCB`u0WEjtk{>3D&Sh8)fwVT*w0oU^I8x2*rv4NV9Xo@H==dV-k~;VM6Ja%F>&s z2G*_kxcEgsY$DXp)2J8wcW+T;Zf!Bj60-|(4E(3@u0$EerPC8}esC+u-cDB+dJj!~ z0RpG{AhjPn)fpM92yMyiv_RQEPkuw7G|Pcok1nRJ=?*L@i#l?(5-0Jb!rn?&rrb(V z^_9c0oJq>r4X$FBo>ZFG-I+#IjZgoXFxzcV61d(YREfOrCA`gNrO?KN(e(kjSaWzA z_~NvX_qFP^IGpOS$~1!wO?8?}mx$}ylnuFb;!wYgx(r~`OfA30L<`&K#&QQITb6-R z!#aS$X*cFrH}Qa%a(h4_y+v)aMf^yLYQ4=%MQVl9z^1T1ahNw9R|tb)uyM zY%GvN+60Kva26`}8MITyBdR%#^60UJ(V_#{-dbe7J05X6PVm3vFE73%BE!K`J@!Cq(>Lqy0FK5O z=bCL7D1L<_34&FQ*o*b1s)V@PS5_kp>q?D-YTl-#V%b;6<0+k~7`E9 zg|&><$|7|fsc1QuyrW@3(*x=pZ`sZO8p>r8TO}14wCa~In=wAxOe$ca74j4l=aP7iY9bF%YeEZ-dCdOcT0I5BJeX71O6nPTID}yc=%y=wm0RS}u zhE6tIPX!Z={yaTIZ$FVBD@7T9-iWz1`*oq($zUwR^4ReZ%S-{t(xhumxtDW^E}H9_ z(2$a9ODtaAB3`vEY3R)P7@0VpXow*vH;;$3HT&+6q%~4i0aYX11Mi@uX|`ryd-%!# zvO}{Ap}4l-#Iz8K#LBR^m97Oby~l z=}AcH7_gHU6Q_tkcQx6bWg_}(Ny<`Z2*C&x<-*mWlCgnQVuy$^yRrI@o-w*sOT@{p zKx)T}-KlCzN7pL9qfCW*VtASKXhdChu?BU44Vmj3but{NLNvvU%ebI+r)T5!L|1vK ztf^!AC$44vN*9hs%-MkG5qwy*H zi_EC%oSDSra>G*3{q(kzH3ccGdxlGH=J>jK$imPz@K*=loog5oc{6S7^mogi_k%yg zQkTR&AoVw@KN2+g-zn9q(my|3Xk@(G>!PV<-_N zTzEJTSbd>P-LMedM`j6VlwB8q*=<9{y}2VeC;&<7n0UYH8+hm*Y5Gobd(X|bu+f4%KI3K&E9p6-@%pWZ@FV$28k3t)iq)Y!15H7X z>dH8nqWYjli3loAuH|HE9Vw;?bW7D4Lcl9}3-8BI=;oDk(iNLXe4CV%T?9>^AscH` zG&OsF^u98R^^nfp=gn$2^fxLC5Lcj$>n6?;cT}#3HaPBANP;t^lYAH2->fvz%Od)?TBE%q1 zY-9^?Zk$&Pf%&7tLofTNDA-;1B$uI&dv{+FLIFoS5l(IDY1=j z^-7cN$lr%9roaI(nq)V`z|y)7?OGZsl}aEbh?J(+q1-J~^OsL5_*M9rh^O|ouianH zBCNFwxv*Y5lXUr>y#*2=Adpz6x4(}jINm7V@@2KUFtx5X`x(CK7&Jza5bZ>VmLh)? z-YrXDHq+C)DcJLQ6OtD=$cmq{%k$KL%=9q-)0b%tY9C;ej2Y)&W@WV8UQ)Fjn;l%r zvi@Cv>+|%Fe|o+E6B20nmG>UL8d|8fM$D2+Lx)hFppGi!_4yljf|IfTD~U`3F};Me zd{1M*DfDxJaXth$s#>@gi-^4I-*cK^wsw*f3MIUu`c)yraobviD=+nv!lib9~bUU#P!#Wx8P6 zsgrb8LuaSS7#f~dYL{)pKn{0shU4FR98^HbDAp(EM#Wc~8o8PrWb&q5;xK#hYKA^) zF$4Qa@9Wgmj;#(@a_vRIUxdV()8^7426RoKc_d@?Tfz$=9lpF zl$MkBDxsB5~6!?)#0Z7bGJfQi}_kN${%)#tj{`0!wq(Q~7zqwrgW@ z-k9Y<)ad;B@rmGTU(w}0T6X&2zAevRH{Y{-c(R_?_i=75>9n@sT2l=GpmCw3gxG9B z%I6S~ovYi~O_HTtjARKCMxaLmope2D@EA?vLK9QeCzKWtJ-RzZW`B$ux*c5|otjik z992HxVRH{E%iG^N`yIuJ&5lhemAHuf#|0agVO|4KEL}Z{Hj%~-iYbG(?;kBLyfLhQ zEvW1@z4rS(4p3lo?ZT|m**^gQvflr=FbPae`J1+Q9VDbEUphDhuo~1fVGD2dx8PmdlIwl-44#V zBK|Yajz089bJFXrY;DNDy?S|@n(Lc&!yB*tX4S)B%8f|1jq=}D9D2W|*LUkt&PWQm zDOQCS>w|+FeF+!2YwK;_%~{3mdNTBMh^IUp2!-sIu}0cAYwSGhWpiSXr8=t{PB9xO zl3lPFG{rEkIlOtQQ8BgRbgNs8maNQ6lbU^=!6ppDy2@{k1;Yui_^< zfrGM3=7xPlDMzwXv;4`V21fp~>*%ZT3I|*pAnv%cFhR(4%Np&(OpZtzb@0gQRdSWL z!wUftwCW~Gy;~k<`Q4+LkkSL8us`Li(Vr3sT-(kbcOUcf4LqSqC*BRmCp`Yl6A70cB82CFLlb2ZL0O^SYMKP|Opq!%bTWP3(5J)k}?-p1`4)sYhQ zsTgPllw(&G{lH*B6u5nMv;wSrV(X9-nibiI##j{g`G7J zeD>NsYo3_MYJSv7oU4%s1i*^Y|M^|)zf#ln-VrC@3YW%21kiEOyN-Sm}YanL%1$XK+_6t zSDKlIM+!v${p)Mq7R3prf)%Sq(_71z-+T>NoE&`km#CJdc1BF0Ev!GrrKsx?5p6GT zjHD01dojooLBC@;rRUOYV^%lr^L_cTl6aY;x_y6&7$eJCxK;&#J*M!&2R_xl;tftGz_XBFUut zFW*i^B%2w$8sjQGaDjJ4Hc%i;$XRU{N_zAkEzgFnKKsWmrKL0^YTDjHgr_OAryMSM z90vaDwc|758i`kYb5MO<^@c14ZG9UkW^h>cyj&3o2iOGdOLsSBuXD)4f%h|;ccD|z zn48nWdPs2&*^Z+4KGeJ@)%)*_&b@qlZ~8mlXG3yca*LxJ_jX&r77D8S#bZ^6rDXsO zQzE0OHJ1ThbwgSz^I@Rb`2dNu*76`Ze}DUkSF`DwMv|)3f6_nR^}{&6x$k<4+peP^=v!j8MK>MbK^=0Z#aS6`fZL|(1I5#N+pPybs*KML` zpMhCnM2JS7!k*RQ7Yu$6>aiHHdt&7JueGE{TK>Qd)%{vuNrs zu9Uruw?l4s)kFlmzn)iV6Lgrr*82D75z(p?@Vz9e$S?3&)r*U(9uNJM3>L|P;h<5z zDuN`L@BjNTRp z35O#-NZaz^f2Y*!yc%96U@;X7Yezuz z8KWr`t<=m)%s#?U#qkG3Ii`lH;}h{PJg`x%)j3JW5wFOa#DSJL-{;XU#-tFf@UDYy zNE;GP?G@Jhr%DHCSc=Yi_4a=YaNg?H_z5|t z(~)3>SO#asHX$BZ%-2M+PbAu)U*_(#A4dk#@-RCn zq@>L7VpL-zQZ-PpH8=~ah?SaI4rk=I6j>uDOu5A2=bSVrV*t6DSY}`8=x!+axBH>I zrE;oO4WptHg%l39sZ#26y(<~x9U)CsZCf<3D->1XAfS8;t;fsY^nWt8tBGLo;dE*; zd{y8o*BRxfyU6-wtKD7pTM;kPl!nj#GWgQgUZX+YkY9uaJNn&Ea#txHI) zHtL}n^8;>e{TOlv$MO5(F?-W-AUgmK9kMcx2gPJ^SD*W3M+HS?3u^=A@uAvdlb9sp z&aORfYnL8uy%!`4zc#csV=83X4_iAU4z)ki2;teOMY=}#Jl@A5+~cqO;g?xAJ(~g7 z@Sn2TglHp01-%LQiwN||9xp|KueI+@ClB6R+0~l@GBRd&zH{0;Z`$#U&ia^&-YkDk z`#+*q&*LgmmM?V5+5e5ELs z3CTLqen(eo=T=ZmX~$?VaYxhp&%mJ&EZD(9(+GCX@4y!`th9JLEhVh`u|gfs3!@4L zV)p`9!V|CEr#Y%;h)lNg%&{BpZeff?OY}2|R^NGc+m~WzII7~)&ioX;K{vLL6(5VII$rC*L zv4vrW7L86Tbku?=jUaf6n57;t2OCEa;9UD zYX}}z8>6(>A_S~gPhi8|W$GvZ5rjHG=sMA$ojv)97q17w-BY3VbXSTdAlsvoUA&GB?(SC-5 za6+uf*#kc@gZtey8G%vH(lxRJKHy}#Zbdt8XSwFFeD+G>eZikDro_Cn$!daRn0@vYSHSp zZr@mRPWGfnB&zRn|1``@wTD8+KopBL;54U?r$Jd_AlWsxuZXqNRKi`>N#{1LW|Chr zV;)ni+u3mW8djDCG{ZkhyW9|%P1V&YcWz7($Sx!EoJP-^+{pJ$-q#tVVbxL1;r?zE zJaW~LZnX5ew`V%y%vmfy>tuPsh0ynU2eUHk;*hBDv=clg_6ggZZ0Dh&eA&*^7cfR0 z{YnuXUgev_E01_4S(Is()HTOk4Gaoev<|sHG2g#_h4bN()Trj5Nz`IX>?0+wxo%t5 z6}f0jo~YgNbFki>r$Aycp(-$BiLs}-UaMDG54)FfOZ$zlUaCEx%SS&fOs&EY;bQ5h zbe+64Em2N|{rsCP8vZ~_4kZL=-~NAPJA~zMr{Q&EGMrn4ot;$UZgIQLnkchNO{QH# zyl+YUS6KqXf%^YC2nS+shtCYB&#tTfGzRMp_oFV$d06wtMwrk3bU{R*Y1m>gY4&ZE)8{ z_B?O`d;UyEN_r4^fDqWo)o4mn;T?G}qs^y#?x6)lBbW6+qz{oin|qW+1gF!h!aP~E zv5884P#62?RXd%nF|9G2+BEO~-QEmyJ++bcnsIz2TCtYCCnBsVF54nu$NzmiEwZGd=uIt7MW^6c|#gA>zeSOh1T+~Wd{ieyZ=_F=$wD@ z_F&I_l~Sp+36&k!{|l$EIb@QGCHM`r*>nK7a*hg_c3L3bAf3$4vND#}3{0hMPVCqV zf#2CIg}hhGdR!+Y#fs8I-!uxlst>w4n9h4sN@CUkUv5UgQHD^QP}`Z?n6no%e+$WbFv9grkO_b1au z&m6k({F7``CXTV-$!kixcW5FRG61D<4a{BpC*1^lASSoB?N<=xI27pP$c}PPkVh-b zciKzUqdR4i|GbqX@Y4b8@yWj8Y*jm-{v;j$Sxtx3iQJqc+MES!>fR1@UsuN!@u~gB zk4L5zF3u5Y<)Ze^M{axR^eE(1SgylZQAIHou5-YRpoFo0^+`gTZfsSQc5#7fB>y4x=+ zPB!MXb$+cznpgfopEL9Zs;v37gL{;a4QHBc%RiIsfK_;<|Iyr3EN1WUK| z6H^t1wf}$f9wx>u2|9)*j-4CH_bB$PJ2ltZ=y|*^@IiiiQv^)>nO0EGb1eADS}Jwt ziNy)V#>UbB^m9ugMuGx{S2QY6hb#Nf(DBy8%{yvst{igAq=eWT3i~61belx6>^_*1 z7|wRQ(lNv^+6i(MC%RH1j?^d=Z__XEX|ac8C`RnRYt{99Hwr1E`#TB3e0Bd#+!g|p zA7FYU=L$TmbFo5&Oyv7p#J7OGJntO>vTpDY@7I4h?;m8}c~2aylJnmVX@hR@f^I{g z;iaq3df!_=pMC`W_k&vG930~25I*3L{jNAwJhhB^%HDB-S~qqvg+qa#71@UXs6_Q3 zG*KGSi74$rnLVkw5ZGy`q$Tj>$dmr|%_UmN@EhkL;o}odi(XH03Bz`tQsd6k{HTcO zWqs)3XF+#RLI+dLgv9Mh*0r90(5}w&6|lBvevWhXn2-<~R!mHABI+2wpUV2Tidad$ zPt+=J@w_B_qN%b44A#NV)=Zx$3<9eBp-gjfLbggeas*Bjo{VzmWvy+`cNYI&&w2OH zqq*0eD<3_;NIEvH5}#3^;ko{6%ah)D;7aanz;P}$%H;6VOO1cB(P~8)9O|qWKXyio zxgG2SYbbB=-W5+~){grwnbK5s_pkOPn_slS$ol%|A3J0QI`Yp;v>-2ro}Y~!{+iK& zluyO;rRObVeD1rQyJ3UyZ081Ou$YF+bRKDCNPTBwVmuP7CFc~OPLWFzepK`%rO>vr z)ZL%ycubK<3C$j!nOzp9B9cJz{;Avu2tA$c|mVqK{oXI4X_x@IN? z!!8TnV9zxqQ^q7X zl3(z;NA|Jz51F7ZYwdZg`8Pc<5Ik$!(EqZT??ip#U&R04x8S+dtQ;7=i#a|QiA`Hbk4zX zc5NJvjmBmhTa9howr#s<)Yxo{jcwc5SdAOo__psi*~uT9nau3j=bUpt=ed8^rFE~1 znK+%p>$`k|TGMm*cbVj6Lwq$cnh;w-%VUY?K!&D^%Sp?fb{(9w&Rs}Q7l!hPuNpiVDX3j++fFpE-X|O zQWUaoP_o*9AX*2rVk@lD(frH`vMeutPWvJL&V>kyrfGru)mHkE0|+gFUm(x`(e^db zzu@#Q(0l{Qv;7x1|Nnab=UfD(j9ft4^vR>!e-7&zpQQ#54-c`TQyw&BVDdc4TOY~W zEGRp<>^HUCdEs7zkx=vbQuEmn_;@MsJf;{h?V779V=cBa&K#$t+c+9KtP4Xef`i{w z-EUN`6a>bh<=$U{gkTk^<@BjQqa7V8GONU49UvnMddk*O)@HO<7^{oBvpXl0)4j60 z;1LLOt2BK{k21}M+A{yw-pS9A&-^}mEjzFCgFMZ*)1~~8?`ig(oDFC^GxJ13P;Gaz zNNPgr+E@7W6!#!phnjsq@O-;Y(zf0X#lXMYg>bLRD=b_W&hG^LSe@dsMX2f`8}rHW zS`!#AX>B&OV0r0^8*Ri>Ce97GmpYQyy5<9I(4fVAKE(z0;rR7|mNM@Nh88d_#gWn_P-@0&j}=LAO$1X+ds?$NHTu??{EKxlI1(g2|P~xwKSronPz!295Iv3#(U)ZH>%}Z53Y6R z!~q1U)ELrmSaNz8%?ku9H*Yx|DSX*b8_k~_nGjE0E37OXa7>J#WMZKcwf5ruZ~a(# z3Y1<)NZwx8k;LyOWndTAsM|=)pYffCM2K%gc|I z7y0EGlFt?Lj>>|c%#mX0;pApEk&$H{sjr$vX!S0l(NGp*IP0YF_F5bB=u^8DX-YiCKf;`N;|hq#4S;&<4O_CQT1w?xtyB>gIfh zxmtUJh7l^Fo^9Jsk2k_pRTl%{~uWbr%f(yVm(8 zkLWu>5i307UB5R3z9@eF{l7!@YU4=Y5pTu|h8E<1@4D>T`^EeH`**dbWS7&b7J&mA zMepT~t)_;ChUVs_PLVib2Rl13F2AQya>t9~0bU;oH)}$q)pV>-X&AL8+$eI$68a=J zUf^uEE|6V~H(HB!%jffDptM=CeKn2mZ$>*53{Ebh+5%^{AHvDe1;*K)(&rJA~h$mZ6xcD%m@m77GLPLLW{o0fr3JmuwV&X3{5vAx@-g7@{KKXnYek^fvLKg4gR8cMju3XWSpyOJh~p_xbyd-0nIr`Necf4u2`h0!+lcdIP{zbyFknXf+CN?zrWsl^! z>}OG=dQ^MOedu4wh+XWX_UK*uF z@2J__B;3XNvb}v?L({^HABtrc`0qEj)&vxChePuFx=rYUD=f|uC^w*03YU}=3AJ)4 zYRI?52p6ZN_dLb6zX|6#i)}Z31ZKGK()fg-Vh#G}AtKCuaIzLAGNP>Jqu{bC#k9x; z88%AA*fct)_bF1C;W)R{%7pgl=M;7VdH#17z5-VtuOtWQhRu675cDmfgjE6Wpgbz5 zOvCvc6MUvxHVots0)_Ov|J8Z_N;uG0@d?_jXFjI4pLuKi&uzCKnp^l^S7!tQKi-&; zK-)QrhlApjMZ=H@3zBf*(=ezo?0G+T>;Z8pK$7>jVASry^-94i2;2km>Mcm zT{$5L1gPl99XG1v`J!ucvP_A9uMuvu#g?e4yC{p(OLS{Q@)@9u5A5QBTxsULG7j zJ<<&S4gCX7*$JZIQ@`O;xS`jDYu;;fOV@b@sP+VL6vPJohq1r7Rd>yuUs(LN$Ac=b zecg{|!S{^3H=yJDdt5H}buZq-L_bCTuyCE)rE+8e?qnyD=+8@lN~VxeR!tt!{#VN( zBhNgVm2A10)T|^b1JLO|4G02Lb}CB>Np*es0jvqQ6nx*B;^kzioGxtk@rx7Sx`wh$ z88`{<#@B0TulIP`VXG0mi7}?Blv`5!Y9s$eaqhh8Pcs$K(?!qYSU9&>&d*N*s$qgU2JOQmwGvkGKvGT6lhrmjc-h1u$Wl-GONO4wGjIKsk2C`q9q5dd#oeelu*aK z+@L38b+$}Tc|Ii{RIw9?wS4=JAYJ__UH2}X!P_p*=f=#t-m*K2=m2wi2ITDY^z=Ch z;{{p)H~b$rLG+f_$4k(ioS^$jGMmOnCP;bDyWVtq>pBg>AbigPA$3el_j-fH-+NQ@MdyPQI_TRh0~hA91Of&|Ru@9HTFEUuqE{ zYBxyEkTD-9P;F0NR&*a7b1#uIK#_TZ+3F$_x^muVzw^4->LdaO9;c@(Kr)LgdeFn; zw(GXJFJZI*U79559tScx43NmkGT%P>%PZ{2amu7W48R;C>D5qk!3RO2o6Mn z%Dlp?!Yp+ZTjXRRx{OeoSs9C3s0?tnAfuxS&sK2C$*%k4tjF`7z;t&axfr!p9L zU0aqDF_R7ga0sSPGUyWBdpf~n#V$H;r+cnBKZgJ9e1@-0hPsA^j*4wu6OuB2gF&pe z{RBx6$%-eUbVTsu8pLjS1@ZEhmzOOYR{t)Pf*yQb)I4X_aC=?tES}l8Jg?dgP{-%z~bUil!(sC9eus4{^57g$I?;SO#w!40|E!gr;fnt7X{*DwyZ_aCM z?zrG|fGP+xtGUie7*Mg=riX5V2d))f*NQaBYY{{&P{W{y$w8~e?FCkD5;5|Du03hy z>)U!6?E88#+Wq{;xctu&;JB8)xmRi*oMHgUTWDG%N?pA>pVt>8B-#Z1+P7=dQwRbi z=$Ycy!#5ueT#YymM-uTcrJa(G)jj6Q=2eyualD*Y7Zir0=0QbTwRcphD? zira`q#8C*`9{}-gQr}Ob!(AT`jIqv^^zZkD8~&R;9Ja zC&qXyLAo5e{M<^$TyCPO0J=+gb= zY5YoDkGa!A<%$MRh1r+no=&@MjRBjO6u6F5?0f;%2>9F`XKlY7ibkL`oqyYYp7z{w z8bAhZcwHGeAcmnkh{kq!co=PPM-JOm^S)N|e(3n|5BN6qZ`Tvwk9G9hTWzrHd5Z4A z1&(wcbFz|6(ND#&wPX*FE8)f#)qBmLjkW&~!Gty=7kEPzIKMfNeftl0 z#0zq{XZ1X1{e$j-@EKo=?|!5D9}``Ajr=2x34+KZu9D~KH9nxdZOO6g15|Z_xL2H6 zQvuH)u7Km`dCxlt`&R3nfb%L5pUPv(T0*_1DbANWTP^eT&M#xLiHjX+-9`<_xAS`n z@iE&wKHr?TKDSY8nlPGf@y0g*UK~7wwXcM43tD+|0IRnjielKjLS0|KHcHQQrqcnd zwtX$Rf{Mpw`)i!tC-;`;!u1HzR;ziN5hm;5=q;p^R|T4{m_4(b{|Qob1PJS6O7a;r zDgZP_9qB3H+Y`_3Q}m2!m`Ld)$MoLM^(ARLG60L)xNeKU=3W21@5$qJfy&8#8>E`% zb3y>)xti@XFkA~eos&*E9-xMrtxPgAmj zsTED2nh-5`On?sx?6IT3BUz7H9Nv&Rm&u;@NQ~7Qfb@jfW z$Ucs`tcNE#-#LUN%aN3^Mlu_lX{hE3ZkB1OXld&&Z0LXgsNytp3O+AV5$9j%=2a0a zB5~tXpGg{V^;Kux`{&&rwpC#i(+fOAc8nqe&2!pu$ch*}*gm5}alpzlX)r7so?Y6` zzAq{I?dD2ed^~-MfDVB1uYNvLr7-r)cG00JQX|MlG9;LVSq z15TQdD9tL3U;+89Do1mZp7)5mgKi=`N1R5*Eu%e$W3o|8S(X}FLk*asQO8*&)bYES z2#M3l##mmSL0>)T5N&g~-F>QgzQVNDrY5G`58$vPw$@$WTFJ`M#P?flGE8rMYwpqi zxND@k>*BaiS4MmC<@qBPlIP~)8wJ*1ADZuaD<4I6(=9ltTlbNk-=w*DC6~994# zyUH85xj*uT!>_FtWTs^53QE@Q`Nd!ESDBIWwHdMM_9WO-?T*9>vGtVCdB}hUsRA{TwuHN=iUsLjxk;eol0Bp3R8iQ>8 z1;35eM}0O6@rhY#Vh-_NlxhF0@-c2nrD{J}6MalL{5!fd1##`vVeb7eyNziK8m9GX z1**Ib(m9Yqqxbk1u2dHXSe5AAQ+b-IBiv+1OU_>RZzlBzR*4b!$nUi?v@abr*b3a` z2J6raWzl_pj?>o3OEhGw#?c^Q)ttQ&<3%0@d4IzQWg4A>bEs>WxYL0wxj zFo5L?I@b?5YDqZiIs)rzNHtVh7>V7VW?e5T?F$Zh)QEc*UodNfB7eJd1U=D7K|# zQ!vP~42G{ih0EwIMp{+|+xN)11Ak{ZX?6H_{Z-Y-(|K;xR|0xfk2UHVZ%`4BFG_<` zHV-mtIz!j$5TnJ5Eg9n-Z-TmI@GaP8xZ_m7DoF(1+aqh*OXW5U%6u@dGN&uLnpZz@ zPtHZ={=(|-<1C($XizXvD(WX%*#XdpCkg=@Q2>1T?58P)KK^b;krUlAhFu!r<8|(} z_}MZ&N3cO7{54;ACJ2r5D-(mu-`ELV5F(tP91#CPcX$E%~wkgW7 zPNQH$8f4-%NiW;hxr$6y)dkZ0Dhnnb|fJdFxbZ51yQ;Z@ZtY9x|)G=3)VqVPQkT|`5D<5SYmvovl zN$zhSm*lXkM!RcrabwIa*bFki2IUi#@ zzeHerx)boyN{x;uiY4J0(Nf;=CZ>_!tc^G~goX?O{w%72&czY%a4WPL?Li%*=DWlN zOZMwn{2M6>R(dQY5=j*jFbwi;NDJm^vMamK9bgl*e&a<#V%0K>4l39oDG7|uN|H5B zQQG?mLF|~71dPKr`in(2T3r)HQ8=!CK9}nwJtItwk;p)grQs}zGUOuZ>>%vxDUK;p zaYCgWC$lcdHdC#5WM<5A2>`~CuuPcrK`}H@7ip200S~04bcABdeTDy_?*+@n=qpPU zhcQBVkj&3o`bcHuC_Mp0EzPwrB~$fngwp^-nDp8usVul`C`t=uGxl~rarua)T)I0S z)dw5xJbVqLvM;~BXV*tQjMLIngNfQxb&=z=jIp;ww*~v+76Y}GZ8n%wWx+LcEuq(7 zR9LlR3VW=9)BR@VQS@}gyM^m|T1~%+bDXUm(>8ZN6yHBXJvPh1-+OJePs{P4IhcM! zBI)GgX@Jv7dB$j$48>!y(@9i45;WSqDCgEj`!_^AR*`9zzcVPQBeK`zoUO5QVQ1nM zNx*OFELy=^9;QRr7+ja5PJ(S)w(+E_tWJ+~Cf|oBOKmA#?N1%$F zSiY@6uUu@!3V*Hs^LeSqE0F1#J!y?IRoTa#h7a$^Ea_DX?jLpJi z7L1B&_L{leVM4FS0w7yMSayW;0neq>{xe7AO%Bor7Sd7{o zsHzf)rNVR_Ee@BGIQxzZ?>$DnXe+HRTvqb9!>Cb1hSaQ6 zmg&uH7=~gkav%3xA`V%ChRrM}R~z-pDVIPW?uww^hw2+a`I66eg&S69#D&9=g67;& z0rTDQ1Y>V|8EUI67W1_V(?^oTSBsjYr@vkvaUU`y^)i8g-svr>R!dZ;x{>JY99dtF zZhuGgP_+qWgT_}YxnJXj43(KFB`ujepUTt(wV0&l(3GJROMl9q`8cyI~V%j=pj}d3h_wiuogl*Rr`6# zWa@MX?-UTPs9kI}pZTnc|2`p~QPAu0n%WmPmeWUS(4aole|@2`rwc5u{-6aTmcTG& zldwi!7uE0{gCuq`yMHkK5{sSa7Vk1J5(J)_?=6?XDhyNqyEPoxhr|u}gD)THi!fU9 z;^Ng7Vvv}VBJ*vdCAAh3q&Ao(IfB-4a4xMGNjSiSa!3}8HG`SO1()JY3|Oz`A(2^z z6U#ZFNqrQc4vAew?EynyZ_Ipo21CRT;oe&@+QhuyUeAuyYoyG?P5`sw5@KFFoLmx= z@(8BUFwN|}!7I$P3uAC1>AzMJGh^;QQ)t+O3@4+S#joIh_r-h~;21-N}&wZE=-2wQyP*n`7;hKTOJTqcUlmEQ&Lb zEmi^P47Tv5uqDRsV;H6taxvxltd%ssyXn%ce3iyd0&#j80Ut1O8b~Qs+Buh6@2)la zobM~qYwm@vK)pl{+`1?YsE0(GICSU1V(?QHtK$3KvnHfs7X_qwZ6t8@st=i|Z?I7~ zQ;5lM(X$j*z=#__n$F_NfNwE^5#~^34^M>oD7?%*N(r?rt`hbruTjKqYTBz!xrW{2 z_6myiMqiBc_E*+HNFF@a{P2KpqEXt?@RD&CynZpM+Di%!GlH4%ohH~;72xNEL=|x4DNmVmF5YYBJ>+n=crdv{sA(M{g*#0Hc(SZ>l(h-)WTEb4UYH_6chz_mmgGEPO(dW|$H1kq&3S688&Ft zS#1I0brRHsyaidGld#-F=`sZCPg|DHM{1GPMnKOa$Q45@u%qyZFpZ>?vmD?vi&lB= z&6JG2Gy*0VN1SHj0N35{bDA2?6<L?-?nu{BMb8?$VsR9YHK~U5ZJ9hWo1(1 zi&1!&2{!|$Fs2=90%MAKTT;X;4$KkC+g_FmHr4$kHtCP3J*G^(mg;lf7FG9I2{oCF z&}vQ0mB&@4)RH1#Y~?*J&r%rH63kqa#wXqeS}d8fIQui!G^%!w9V!vht}07j8*OpC zS-2ogRO&bLN*@yBuPUD_t?Naz0Y<=n8}U7N2=(v6F@IYcGh$Els13-8P@A)o z)Z=FI@xa(cVatSz@y*d4V@xeDCh<8~hpnFV6X;gxQWYMz4IlW!a!^dZ>BLDvY*n*V zlnx8W^ao$zqgDOBOyLI2QkS&aGfe$d6P<61tXneu){ngalO`hR)?j(k3h3`KscL%- zXUd&|B;PNF_h$~lDy_%eXszUAu#ZgR1`UHO&nupVuB zI#roJG&HV9&43kaO#w7tEB)^lZN-~3*3;uJpk`GRjw4D>*60>*)8|_Sbrz=Rf|wTtkVse6-^t#RYil9sJi(Vvs>s`W%8#^^ zq8L&otFyMRywK(cG`U(I#3-;Tq*TzUi;+RBD_F zHLLO*FwvQe(xK6)#|pPt=#w*Ebpt2ZID<%=v#E90thW|&s?b>p*UrY3NVm(*L=Yh2 z|JJPH-~|o+^#yBa{q4pMhrh5#D@H{-TkRZBLYI!v>+T}U^z+A0a~+uiiM2-a$U=$f zB1+ie6EcN`l2WY0M+glzYRy_F*0^F8Cop;$hwm%sh3P_c?BacY@>j|M=D3jD+Jn@! zj3-S#s)S6vJHU@5A#|lzk(L~e#oVtj40S5(fGRmsV=b^B^+Kx>7fSd>&JbE3w(I7< zzZw~XF&x8STLq)swjtfZwwxQ+L0RK$?2{+0r5kvd_YNB*<$8H3Grb|;g0AQUYFT|f z+#glK9jr=NnIK~GRFt&_L!Y%a4Rx?tZJ(WxTd=N182-b~qBwHp_phF9zJSBQp>!LF z1YQWa-pY6DfIo>0GwO8Tt%ry{0eaiJh70QRQ5ZsZ{+T6Wzldwr(K%9^CmQM_H}{hS zgepKz$|Xoq4e&}d>vO8##G{+J^HHJ%Q=(8Ru>-?mL?i?q&zB`8&e zWrT3vJ7$IbbEw_Jl_A_d*IrB?NLp-^1RC8R5?pne^OI$IJ4UOGwEFe9+C%3-rEJ-n zGJw!gjct{Q==-VxIBdPv^oZl?O5j8&&RKvkEE1WG`y@J;`XN5aLD}X>2do#K9L8Bg zIk)CkzNCwcc0~ntU8HOo8IgK}NrkauI7^E0D)_{tuVUkC_W6&Bl*XrWb)b>0ds>K( z^{v--k3YLB{8YDejW^CX>dPm6arg+40oVcu4hyW80nBbK@`Hy-8U0?gkmnu5CW*$jTXFlQ{o4l_@3R|^wg>m;4L^Zw{qfv`F*qw2p5`c!$LG*R-k<=_L1?c*g^jg`!|m<=T(7BiUw^P?QgAjw{2HLUMfK{3Y}uUO zM%wxPj@orP7~!g{103%_nXvwGMe;bRu!eUva(z;coK|LlRD?eY{bP)~NhXapXon?> zA4~T{_%`sovPQ1->I9k|Zaiox+_)~Ii4ITP8k$F_0Z|-SZ=+FGKrO?nz>R883f8#eO7?mWZq>4m>HRLfFnZ4kLm&>8 zU;H9Z{O-`{n{{6`JU&QKF56VAQ{G-@q;FbZ!ANT3EOXAf1exuIm$Wt?QJLQ`(Vxl6 zbH3CIR(}=E8^gj<_v1>;9v5OZ=1VYwRzi|UR2?Lb6)IW*=Xo#GIT^o-py6rtX6s?b z=E6}HfvqP=zPu-!N26fNk}0x9OD>O7rND>cug~k%&bEfOjn!2eZ&INtYFX?il^maz z3W;8P`QJd>(OZO+NsS-=udhvb>_?kSs?ZgEK$jwW2wnA!oqQ>B+CO?3d!R9b&|#)$ zXHt*G%GA}WZlbLPP|KuoSp^?Ru{53qn5J|p9%&$wtip+1o7;cC=xUH>ppQtluxawd zpa$-Q%sEqa)*x z;c5HwQfiQP{M7t8<|%j1vu(X7$il5=M`v-z6N5b@u?k>BRGmN+%^(Pz%lpx1DSem8 zft7IA=&u;C0jcP{e!b0~_^Xq&hqPg~gI7+m3P=zcJj_e%#fbU1`Bo?Bz4P8ijr3D? z#8wyY?O^T8xQ2c|j5Trr7QNQm*^BCXT|;zne5KfHF79>i`|YRw<8>G72g=B-briL+nw-VMiSKQlG%HEi4_E_>k0`SqYBqSn8{< zBa%dWkEnvXrXA0A76p(CU?C9+OwD!gv1v-eg0MwUp(|2<7tRamS`*hlKUsIBL9AR< z%pzVKo_yXnK<23bfa)K`rgFtB#HFkgfs+RSdpLuAT(zeyPMLTfI-kSe*|PYl_zRaa zGFkGyT(bQXE7|)d2cdrKS=Mx1%>MCJ$ocMNqd+HV3KvzCQnQ-!r0wVfz}9Hk$~aZU zMMHqoB>J&^Wdxc<_ z9Fe!Q=$~WTD0h6HFdYO$!C_Ti4muR&Y!;b-tJnt{gC$FRX2sUA&fC-VY)Ed$-+wh) zTKPRIrgpNaOyeS^!9ZW->W0(iAdlG|9b$VgmqoP#e5k5AqdE1^7<8b_lcyyf7b_(R zu-2CjR>jPpR~C6eGr8ZhN|npeP@KhV5?$@%nccj^TOqLXKi`Q)?b*4a`Xvk}KXU0G zBZ*7rys3~u5)&zEsm$CV*m3=K&+EW@^ThGDiTzKRA!87YZ5PA9AbsZ6BS2@+31vcJ zez7O>eu2w)qtxKf-CF(9or%f3KIp240f4XTwy$UurWQH7r(gKo@DBqne&dEq1mh->31h4Vn-mv5<&b4e_5O;Cuv{kG5HJx{48Hw& zzVG}fK+Xu^G_Q%poMm4{!b5keS4t!EyM8!*>g~{Cn(w7amF5;Lf{Gg^07kNUktx!n zGP`%Q8_eBw~k(E8u32eTQKWx%7P9+Ge^xaQPoplAOggPc^4l4M)RZ^9`h z?!BYFZ0@H`@ZDN&;jq1Dme9<`-K|`=p9MfMSJ4w1wG`A8PfD#lVPIxiHR-EW=7 zayP?DI_1{kUHa8g{?Xp59$U~#Y^9ZV7@k~?(44ar8K&xRQS8|SnmO}PFB47`;H zBBwP#BQj-QEW^RNF(4h3Q5l&%9{H}WZ0!>!A!~ELy0Q@2ZCEL#yyG5|gm&2`v@dRtR}3|F z*`qBuL=OBEKu*sL2lA1Sa8Jh7@~HTw6`~ZQxi~eFPa@MLSkWgLMaunvIvt%}2_`Dm z)ivbZAj##g7mS_{e_^0XERvsIvLa~`q+o;-6ti%+COkv=32R%{hy+&hqaWYs`>o+# z>sp1mT<-+tsPqy>VumE`raE9b7KqK&X9JXN0C(s03qH`iYK;PqRx)ZEti9VI6<&b% z-bqtLEY>}hRT;soC^?J(hEOcI38HZtN=vTWn`t{~eOrNK%a7aIuT6hX%$k7|Uc}7s z0L6!W{F;|~Hr2}mVlzUuZM)`IbRaCIZXl3$-MNbk5XkOehCXx|oGMBX4ZjJbhwMs( z+y^agEwGYpRywn{hXL3-Q9oa*9cY+6;aTd=9>{5gGI57!U4l(gt#VkvrDrXhzWyD> z*^534!^GvNkJMTpRD6;GR0t9+Gtg&a*&@R58WEiO_vEB4mJyhigth43@Pz1&bKt~Z^&@SJnlvIqhV)x?! zhsl8sVPKTM;VH|1V`u?i+w>9dW_Avvz7GR|U?b_0rl4+7m89MgRw1>V$jsAC zfgU<-z2(X`*;RIlv9rA=e0qzdG50XA7qRM|F|lXX(Q+t1)UqryeYwJ~(cmdrgtec` zR=Pb~m^TFtn<(9_IFp>e3g0%EP%fP>#OCZuHhV<1T&u-mQ{pyH?vwA}CY2qHS`{n{ z+@+r`)wFrqHYE3J_zz=JLv47JVnLl)h1c2`&()|hh|-9zp2L{jty4Ast#%fNT)c3` zf=tcYfv#v8ekAU-A?27Rca5{{)PS>;)v$nCJ4>rFfcgVkEp;uQP(PHHdxI;Xl)X2 zi9pF`5^z8lDTjC^S8?z%mgt-U7H%CvW|sLqpmzR>nPzsj+1Tw++cWRSi#-fZ!XWnd zGtf4*kWre=6P0c)wLc8Sh}gbKX;7m9%kTB`B`Za#1foK?HAL7Wa%8MQRczbbPyfHA zwkKD{Vwyd@y&8U2r@EN7(q^!jU+&`X6s9%jjWeUmE(%Bg>OBz0)J2mEfRZk3A%wCe zLklXh$!Qit0;q6igC*e-8(GALY4p;Ms-+s?n~UvXw-8e#1LUS+y-t(hBFuZR!Pk8G z!dWxPLzy*WIr~dV^N=lO@mdXtdPk7duK#@%x+=ffwnikF0$iPfM^9&uxO2She7AOG z|EdHE;d{g@>ILsg8st&F^)B@#L^+Klhjz_lya%X3>)*4vyoO!zC!uhz2;gy6>q6|K zUvoq{;r*_?sf_`2EHGFAhgVDU9ALft_?NxP4W)98m9Z*{!sHji7i5{p6k`_?Yrw}T zsZH`6Q?as<$rn3*P7S#f|KgTRtL z&@?B};hd*%fckb-fGSZH5TrEZG{wV2>Dtq)dGa*w`Yoqj+?H%#GgM^$E}S5kNT@3I zM(+d+(Dd+Xj5zwx1f@*cbgFj*umo3?q9>-`Z@T=Nh4H(SmRGUOa5Qz|_dsksB4K6Ed zXg1ZiTtnvf;tS5owmS>y4jl&b(}^R_S%r91^ek1S9IDK1%1cUVSa>5C>VYCdsrrVh zf0%d}VeSCB@v#7xN24|-Yt7io>0^_qH>ZLBbxd&#cKwV?KctBdY zR+ru>(d6(mC;Ei?U~lH@gxbKXs-zXLzW{cIPi7^UUx_~nMk|CmECY)8x2z1AbbI9? z<8Ss~*8L8gh_V@&WB#Jzn(>{Z1eITrFp)i5y?R`QM{2ResmEz_5ai+F7lL$}Lolp@{$%63B^nC6Esy{D3Yd{MIc*^R|1X;n;&-U_EI4?k$I!f%@aL%TbvE8 z7T$GOME=1E_(QP$B%y9^b-xpe8t_k8 z1Zn{O;Lf|{{wMz3b98R_e`o1Gsjt_3Qtln7d+mxdV2@L(qQbwTlZMVjTq#UDeh8sz zmNg-=zYM+H4E`@AV&#`0bs$EX>&<9S44qtjdu=FHaBb+_POkV%el-|#Fn>|^kfusR zwJ89OM|e9mEW=4+di1$2Gzy|+O)MmI?;|9kQPwf@J<{SmDq15 z81`dM@I~^{?}#_><0vq|)O2s7&9%mBh)yAw?|B@QF9f-%w{Q8kT|t6O$Ik~xLtS0h z#(!d8p!?=OPb|nO6#CCO^!U$D*Hq)r00!F;?U&)G%EY7Y+t$R6#Y{`Gm}T7xHq{`^ zv7+gCFSepVni!*j)%CH^s3qJH^W~B%B)ybs-y`2s#&T9c1p-fXMU_&_g%|M)42eR` z!~S8)4^h~kc(G&Iy&}4QM=`be8Ti|WK1hYYF+lkqu9PnwlvCd_w6ZRkp~KX&`ZVl* z@RI^j_DVyowB8$XBC&!BKg)ng0d2jA0gzmpmJZFyVRyxQ)rl>#{9uh1;- z_5q;h7V=o;mIkKJGK6V3MqU4Wx)n7q6<;NP-TC*lwR!Kwa(=w`d_ML(`u04w&G=vR zJmGxqc3t{kg5Lc6K0X#J3&YMPQJxAr{D|4KELp>Lp7hH-`T80SS|ZA32-@wxRC8-zqu^MtPZITh~W(!-BS3H1o zOcVrbPmUa;nMy`BHE5JmwCY5iclL67G;5duKbw{&>$T~=tRMJ(@4tPNjY`OMm16ju zV&Snn2oLu8V)%IqvOzO>&qW&~tLPXSe&$|2=N`B`cl5k=fPv^;S4*Hk?LRNvKaDOp z7f8?d&!M{o3JCnW{=vDV1M7^ztahWf(a-|x8AS>oNq&a_kzJ7-6{8J(PhzTk?S&39S+%s6X1hnES@XoFV7#Z#c9}V z1$m0BG);NLW*&Ejsr<8X&UDhnu#dJP9QehJ2^f)XPb{V{mN;|BAr+%?FkIWszG&$y zUXhKG3i!~Gv4IL2%xT@Q=LmVsj@yDNS;l8TGt& z-jA5xR^RS?wTQI@-Hu1s{QUjxH%Hc9UO=y4f7qp)1U8c0rOnN@4(}6FU8)P;r-TTP zZ~6wVp9_R(Y2gRSNef36FE1bs+-SmAMgJ4kw21@IfIc>X8uzCykq53;Mg$(7uJ`^m zvFgY?4^jy@-|UYa@f~r4B#AV|>yAC|ARi^jK#dcWtio2$m)NRBpZzRDGxc(B2V)bQ zNQ|=p*DVw)Z-18Q1XqQQ%iz7dW9BU%+pu-20l^PIJbMkI-s7$*izXei#UhPOp7C zO;r*}VDGj!j->xmfbr-@ zW06zW!t$xJF~c#?{rs}S0 z&JGU`i=y%;y9&6UEV{Jux$H~%o`Alg2oxe7@0)L6BV3<;5hAFR2B0}uoa{TZ)zPb> z{P04Vci}YS05eG|$WfDI0yAj~PaPN>s?$?p6-R>lg)0Iu5Ndh3?q}8pI`dyE_7iFW z{iqayZ=yF)h$X;G!hTCpYu|c7u?5J?T*1ZT&tic zL>i4Up@zi%aX{IOnk(f!+c3e#i&|r@2i6=6aR%26%`1jR&r8ok4}Z=wNvq8Xdni=# z9NN$>pnGt~Yz%3i;!PYxk>88H0{&y^hn?02tX+;^V1Vrr=!5DpzH4_p;bksopWgdK ztb+O2kr;#=%~(lb7oB{gY;nVrhT?HP7@&jzG&|g-*o_)A{luL%o`~9fKl0ozeVm@N zq(@A>U*4B)7@e8a${kvQtjuc1hdUOHCrmSh_)ga1x77b4i`o+U&mqVEb~OM(cWz(4 zO<%svGriA)k}hs>kMiM~DE6TIk~T;=r{^Z^KVl6Zk*O4NrSw}O(5?B7o^sBcWyQ?PVK|fFkLJqUwA+ULUz71y-*5W> z2QQ(V?|YhW`wu2`bG*pyJ0U7#+RDAu7aKu~;}qUi%G8b?Dftk2M{`x$npF#5>elN8O{qKnmcBm&yZ!RnZT~2#55MOE1-ShDxP+~3YkU3|H2K%_edND&)O8ik z1X>zwZ7aDwK{D@^p1_`;pdfkz=xpD5#=+5%DQyDO58kBcA-{CJHv;On?|B(w3b+P^ z{{qgZdLBkD-;%c94z_uG{~$rbTw>&N@QZ{ZfQLj}>#>sioJe#_PeLeU^}79e@wSFY zi?mU1C$JUFpj>z`{xTk(<8s>6^05^W_!_)GWkDm&f_MDQdpwb~OfI}!Di7XNvxtr; zR+_^4q>(BtmFLtr@_5k4sN_k|+_i@e*N;p@dE1aA6cBp)^SsD-hVDhO0vu(RJ>}GG?{7t{>oBDgMuFgEqnRA|V-#5w2KUizBW;oE2K?sKlA&(;P+Bvc$pCriCf5KNWTwa!^hodSW|6ZnJO z{ACgU-MPHtUX|4P3H|`1lA8BghC-)74<)EhZThcFs79EAQehZNk_Ssn`1xWyN9H9@uhrC?;**H9mV>#@v85kPk%n{ei*E|)rEg1i#{j6UUgmHiGJS6@3<~~ z4dc?*?#H9!bDHCS^lzX#=WNa$XyHZ$pxBMbtUPn>$eFRUn#;RfCpHjl&75P5Ue%W# zwPR}W3(-hnEAB*T8o#QFnrC_n>mMd8&C}OegKRrKPq#Ja z&hR(Jvc`#_;nY>R4QVvGNM*7lx!a4MvsT}hl00W9PMxUiU6bO8HUdnK)#dJehVOn z2yTHuh=_icsX~+lUd9BIo!@#0N`(M9ftGkA-ill?L9%+!_wr!0`jMhQhMb}K3JWZI zW}xWOUtfLwh+?g3l^V81=b(Y;EF39Lc2;=_Ecin|@{~V+UL{_j>y^snWAKt1bx@Pj z&83035}dn=S_C5qAovx#pv9Tm7TzZeg2oJH&AZ(IS5A=LcXu)kH>1jn-I>|A`&UX? zs4PY*5Q4SUEK#d+fwA#Wl$Wv^02F}CRBNZ6hEOFat2)vs%2%f!iOvF!vy6EU@uW3q zlHpS&3VP}0Uj_^&j^zvb!BiHE%fXC%H|LHhs?7}Al=B!q4Z=rYrk!=NzB!H&74rE2 zr-y{oPvd|q)P~X<>Y9OjnvWe}>ddNuEjBWps*pM3X@7EF8eQtNA6r-X^h0uP=~uhk zLnKe8(tfxNE6QhpJ>VctM>Ki%JO*7%Q+;n!Q-_P}7Q4NEpJ(6RtB*xLpDn)%w-;Zl z&bhbgxwox=S4VjgKBv9>_vQfi_lLEvg?r@PzsUJt5-Jc(czf)BbqvC9^KVni--ZJI zp@P%|7r)+0d*c&G{BRR3UEBwSjOLp?W-#BBxD>FtB+06}lo;F~*g0!j*&mKf82o9& zT-B~?D+d6WjS$d5=5lrWKhauzn4xi4!9$j*OxQk~5z)iybwv|HN-OK8pOmH{M3s^m zq--FSrTjJ%v*1hRSD>D+aCK*S6lDs|YtE;|u`MmjpnC9ve9Vlq3NV810YFGRWgn>T z!S#yk=1d=J(=(nvQhR)-f};vH3$_N3n02&+Ff8|O&qQ$fn|ZThuAyhnyPKoUKZK6c zE)87t;V?^=<)Uzh8qYAii}*@bOz`&MYprU7HV{;%KTqDmB2?}Da?*~+Lm%iktzkv` ztE|ByqPZH{jZI=Nss6~U#>*iVtGLAI<3MH;%nO@%e@9LaYCuJtnqbNd`mS(=&GW@+ zHocL4?gzYC1w2}ToFsr1&_;m}$VlLSrkTHK{P)ZMH5c%4cMT$=pM5{P@}Im^eKwai zH9>ndZ(q71(3n|()=+C7@2}rp7Snf}r_Rg!mm{h=@zvdzhnF)cw>n)KEB3|+*$CL!a}{Xww`h4UD4uRS!J zB=!uo6*nuhSl!&jvXVu#)v~gR%p#!WG8KbaLDcY{*KY{JU5}a47q0r1mC-f6*^oc4 zr?|+WAKFZsEEIa$n0>;E8LeEWU)@+4&ah?Pk`-t;w~ZZ&j*%nk`fMK8eJA-G<8?A} zDyVfs8EV@z7F;ljxf7pbY<(>Q4V&-&9_8l?dUO`+Mzh&Nz@>WnVfo{Vf{sKV+G7B_ zC;}gr#^gdxlAhSWSqrLI&lK*A%GYFv+5sEwj80#$+P=K1cM_(mJ=Z*YbIRgZO+Foj zUv}kTpmT14j3{3lESG-!#Yo_SB`6a>shXm(D@KZ|y1bf80 zVhXfIw|+`6163gmCaNcPSSGecmpKJY!TC=`?PWD19L6$;Cv-h<2+L8nlB{(jWaH>f zMQEQx#LAikY3}Ilzfk=@%yN4ytxGWlT3WUoe9g+w$8PZQ zGELKLX2G7l3JTzc_xp{1q{KSEY1B$k5SeEXaA2Kg<-XpqY;A7P`i+_}5p#f0SC8}MW_e8ct$qanPaZ`xJD|gYh1gx_$f=Ahf=CB&)GDBawQ^$k63xJkX z-M@A}aQ0l@t>{M*tzVXRte(;;JH|Z*Fw7m^7n7uUcmD7#aqOMmSZJhRA##F_4`Jp` z6t&2NyD~ffr1n^=@4sVGK*1SRZ1YlSS*lRZrwm0h#)L>Bhf?fM!;*tXWjB=gww&Xy zys)qiawMn;IqYUCFeLI)LSsR4VW$=m0jQ!Pbqndl3Y*PC5n>AHqIFs51Q?s^5;EL6 zuC;2hw79XgO4V18S{w&62#+6r{;~?ir{crSPvd_h%P%jRg=xwyV8^mT;AFp{@Z>Sm zYY19duL2~;Jz*mAC%G!x&BWiUZhua1g&%8V;@A?6&(0`dO4d$)hd?i@*rAkQWrv}H zWePeu!Jv^BYH!#1Jh`Xz@bH4yZ!%On!UJ=i$5#mcr$w>C<(j<(W@BG)el30ZSjeor zH0Vi#L?JU*pHMXrNVu4XL+ZKQ*s_(D_Z!I_js0{&MI`&}4Il3Z3Kx|J_T}q+e$T%( z@uL%ud3>eXc2P}!3do*L7NM|p7cWe57H@4bEtG040pReD!9Wc)jFNsdj{!3jTXmuK z<>%8t=^&&59zl~13jM5>QW@$N3LOJ9X_a4Va%IGTir^$&Dr^FBi3xwz)fDciML-gj z8ij(KGu)ZM1O***m^MdvPDC#&*-NjhAAK3qNDWr4aaN_Y4>V`>*kXX51?Wf|1$ZG| z`!YHBpzGTv?bSCC6iL`9B4WyDn{*zLj%Od#EqNTQ3>S=(cCBJ}|7k`6 zoM%lH=+1arDcj=@(Ezb)5|kbN z$O#SsRumd^ss87pS7XXjQ^Q?8{(kp_Uyt;vloH6B%!rz8%G#WOq_r`_%BHHDD0o#Gj{(Q}j@BMLO^#N~xe;TNWy!v{tA5EP_DJ(bDcX;(q znQf}{6lVagFoG<|lv0ZBYCk~Q<=m4@0H9XN9YX1sevwx8T$FG9(b?|t8d8)tdrjWF z7`5CCRixy)Z-)&b##712c&oZt$Uou%{xyP4r#xf6ybMO5VNW15SrDh(kAq+A!5)b> zw-%+)!8uVi8-Mw+jC)EGhyK$_6T?F&po2CWFhKk3?mD5&EX_!^&qrw-TLp%Xl_4QS zrHup);NWNy?xNJab;_qW-F-GKEv8HbBuXSPk%$x^DVdp31XD3MNH!&F4~WH$aBo=R z)A{KnVS#H*(x;Z}xNS$8{kczxl0_~pO4+I*s;+}VqQ|w^m~pxr*b;n{eWk6NDr_mf zzKXELeIBIh;^!L}XssLIL@lSyNXoeu^gVud_Qs?o;rkSu-7@G8%w2PJQk_e3#QhuvS`4lVPjkTp~`4X$VTJ8(LuvFZ-sR8v!OsXxSIu^ zu|FOrefWEH%6}M140CQHO;!7tBOELbu zrGgPaXDXGzlPyM>7m6!s1mjW32fMS$(+rj<$xCCIBuUXRt4Afh3EH7qGRJJ#6_|*S zS~d?P#F(!nRf;WWq%c&CSk>U0jXam8iCSqVSWRU=?)n!H^^psAsd9F)r8Dso^8vR^ zuEdt{{DoD`-j7<`KQhvV`+oNq5+1wnkO=+!+#k6(F+11&4E=HL69;`RNT(mz64x?T zYW1`wi!xW&7o|!NPGQ9x+W-Jl?W<`ANT*{YieqE0F`%Pist#i;na{`sMLyh#kP5r} zIS`y&Eh-16CdXxj!90MNE|74YN69LfoG*u$;Qmvh`JZ$J_t5+xoc+5b)nDn*EQXG} zVTdFKpF<44Z%`LtQw9_Js(`hYxGI{r{!Zpx&a4%$rXiH{4Dz0wE-n_B zyxn3JM^RC4`vA^FG=|2HGJuKJnb$F;fD6tbLP0Xwaq$%a|Ksta|4K`o1|&E5h?J0b zhWpc8yTljb2o{;_+Mm+dpFjpq7wP0RLrHFG+_ye}x{?%$Paaqv z-68g~fQwkNR7WMOO%v*3vwd$%s0j${K!lQ^w(NZ{+D1`!++sK}DYs=CI>_$w}gI zR_a~Gw4{9|S1T%vayTN3IgGC>1&=qy!79EnV3yhT;}kRB>|1xhx=wVJ*xW{vpusl2 z+B#;alt6)thFHVVJtQ@nTD8F?pXvNjr4~UVvd#Vd-#llP*WT}`l@XdmZRPC8K#HK? z76NSKk^KW$0dVD2w7CRJJH7SPp26h@+xL`l`PamPGsgOXvoM8=Wo-UBvwjL2;FQI{ zW8ph2>aM4zF$;a^`s`^kYF^J@69|D6y)z_>s%}NC1Zk_WZNCLiCj<$2?s=`9$W4l< zLTiH`xG-OL8f*b0ril_j(X#+2H@{|MB zC@N_yIjX(D!}z*Ju&Odkd<_MBjY+VVI#+s+O0d#~{^;nes_3lBsLZU$%+6YLb45KA z#Dg(nzq1>}Il@UC!RQFs&5ercoat2~p1>8I7sSv|IS6UNog&U+q;p z1I|H_p>Hnt>}yQvi0GOIB5!+;<*G#Ioj=`PhKFcHR*SC%`i5Yy(O961+rAw-Qm&Wh z(XJBYde14fwF+rp(i@2=YJ)3wtK{O=xOBvC86q&2L95Y(R8=yh0@dhNmJo`q;b&4Z zmB=upN5ahMsVS)Cl4j?zqch;T;(O$Z5|xk~GG)>Zyb{u+V>VPo3CS{M(wZIUEXbOz z$(!`t;fV_Y%tb0a*%VDMfO=uyp^x0`{CPirkH>;SI9r@(gIqG;c64P)V{Mz{@*>;T z_uL~2xk0KHrU~nqYc|XCPLjla>vXpfsJdA=UUIgeoI=+H2 z^{CWuZ)m9R+yYkG$~KK;P;%s{G=UoWy9R{&fk_Y!NmBX+YZ|Hgab1e{S-<4xS1N3h z^wB+_m{hl6Lv=2O`!t?jSw(LXP)WOwD)T*FgE-eRP`qr#vr;AY{vq>j-)9(P{GAsL z5V^>?Qfi&ey)ZnskZjT>>vqBF+gB+%Dz69MF5@?|(_14_(< zF(ph)q15zA3K-msmNXL@tA8pN$gO~Pi)dHc9(On8zwY-GBbpUcOLZY57g|jcf`W|g z8-f5n|5?1h&Ho4S?LRrlp(^-&&*tOOn?IIqBeGe7@c`mol=xCGWVX~0gI3L$Hv>cX zE{~pGw@$YvnfURGaOSacy_wF+03AZ#HC;Me{{m48{VDFcAZ6{*sO_^}tIh9y#`s@{ zdXvh$Iy!ROTB*skdRN2Ax)tPY+ySk>M7E;UgW0z4~_2)zzUjm*#%OA6dV(khV4L7!EdYkz?a*5Q){0 zVF7Qe8L?#g>UjijH2F+-_a%MhwnPm({(nAYBMWjte~Kupll{vw|GfF})3MKn-~D3! zh_YN|+wXWbGr83;66zKGXQ1i=Lqt-PkqLKQNpOkUTrL`xht(N2Hm)Q15H(eJ0_c&4 zLR?j1B-7Cd;|%>1(#oDN;Dk7vIYuMuIq$D_q+K66G!*$d{D zj+Iuqd0uo4gXY(F(UtQGPNxupt#}rjnyIfI`4SIp2@e_`pWPwem7KsM4=sJCn$>wW zTj#X)U~O$q=PZ88hhiuiGm=%O-(c?_Vw7so;798+{g9Q|f2y{RPJiHxn*+Ph$Kck} zcFNTf2~gqB6ILo@w&@E-j~Pr&kZWYZRf91qxW%#<$Ijp}kgi!doI9~Hun7g>5-~KQ z|AbJWRW4BAi}E8)d^F>%rt(7l&GI&)nt^;kh@D!FMh@#|s;xEpT(^zicDkj!7Jm5s z6veBn_4BoYKDt2W91Q9@uUiCkMgd#iB$XtNHS>iVV;LI(bXpfM467`eLXHwxD3Op?GLLp&kzkb{ViT)yNYB8IOyzJ*0zWsG zqkqz1N=3SqTET6WY9SzBqNAp)8k#X+HQ|V%MbEW4S)|R+;{mThCof|zu02v0><`tI zm*9>X6{n0Pw;_$Im@34OUr_qbpLSlCSQ1fQray*MmGIla6|Y4+6#<%5e}Ni0qZU6? zUVgm16`!p{io#&F^aJ73l7UtN9Xh6aaXuMD&)qo$MrF)p()>e^nIA6q3lybrU$#dB zU7(M}*Nwl%7_Tx+Eh`MV$dZNaOdhAXFuRtxChFGCBvMPba&>w zKYtLfF>-w&Fn3t8WIAcKth1Ie5H=L1(QpviPgO-K7@y}C7;>cvZVlbQrt};s) zb05DeABKFYDHsHKCp)_s zrK+5atII(wdTi6CVzfQSy6@6sne^xW6lyh&KQZpE4pLl(t*6ks68XqT0sw5%|2# ze2@koC`8z68?QB8&56d;^g1~4h_q9F{iSpSi%pY4q#L+6rqaXsoyF8|0+eCo3c&`F za|-llV>}QG)}9H}d(>*Y{mRlY#K|bHTFoI=3{8)@95#Gkp|)MtT8m&$6>udkfrX+c zf1rs91_HSUcYdUS1Jerb=Ja)S)*C>euqM|cMeLEK>B<@ei3_DB@3nL{UF%9ZMn!5W zZSmRm_Z}mDO+-XW7LBnq)?yvL9fFxD=+&P@U`#mpK&U2mFAH36cY?PxRfxpG!cjRU zMyQHeFkbvaDXhJODr^g-qBOElQy?_XwHrLKYCou-`?8M7`pp5^TAs#rt->qp(quRd zh8{{EF70~{<4>vIS$IO?wH8kfc6j!<)$i7>9HsmQ4x81{_n2{#5OUWDCE&T_pNPLD)|PhP557bT)CCJ!)ay zj#|37{TNa%)~B?K=91S`zLL`yeFujTCekHMf-BR7=ic`Shu(*`9@2CwV;9YHWI>h} z9^L$EM$J5m?!Z$NEl-YY2yNeHVD2Cn>&BjYILvCM*AsZZk%Sl&-Mq$ecX&)OK}y0B z`KFx+q>!HFBnRbuw|0}+R+ER49)<3JvsFYYi%n7(0%ftVR>k>Ir7@T6a#<$`|eW4*%m20nsfdkGR z@0WT@!^6PChZO}}o4Nhqn}rBybzs)&6KVIyQS;NU?HJix9j2>o@XTms?l8Ni9huw= znD!oXY8+U47u88IRE;<$d*8y)kA9@OI1Vw4Vl8|VXeDqoB{a@c(^x0oB|OzZtp8~G zLL(r$zHfWNiE?qij3`BP~m74pJ0kz&l`u3H% zvCi2tRH4A$%ElC*w}B{fT&9#ZB6)IQHR>P?b-2Nj_FiqfU^zE(1Z&iVo zlgQ5sWWg;$3Lz1vg}g@TjEx4Cm(nV+ppHDpw*%t!5yw@ZGE6Z#(s2(jA)~F{?Y^JW zJUJQu(0b>0_N7(7G>kv^NB5ug5KyfZLU39_C6(YnYjrp4VUw;(>t~j07Ru{5*qVO- zo?T8gl3dhia?2ICiNX8oQ9)EQf-XvJ*-zkc6$a!H49W@YY^;&^L>{>U&LX&?%@H-u zSahQ$#QAXNsA^zgMAbs|8WS75#R<1nn z*l{3X#oOY87`eNiZuQji3Mav;WA{V2?GMp^@t-NGmugf36JAvpq1Ao=7Kfu&nt^P` zCy_@O`WM=Ehzlr4Y2q2w4S+EQNUo{8MaxK%P;lxh8ScVLd}=ZD3A%WWh4Mk`384fn z8_EzDW*%_oQN_)xmV9uV-#;N=QAq`#eYsi9uhWzSFDOYa^*5viOb40tpcza@j@Wjp z3=1~|kQD8JT&=2HQib=H%KC1Z?}(C^*vl)E3g{d*h32y<6U9WzFMBvRM%IXg^WbXk z&=WE2)iD7ZnUF#`|NZdGRny1j3QLO|Rxl}@H!cmGh1OH{Tp`5Vp!Bk}XLrv7wP<38 z-*FsF{j^t|Mv!9!9jZ;X*btYpJi++%*z-}n#<#W_Te5U=0uxtdYb&`;`<{^&fYLQZ zggVN2lEq^(Op?r&-@_$Bq=Rr|5@A9TxoVG;8fA(ztt^I?&ojKyncbim*i02HWm14= z?Ufacy6@ikx|?VOB*=e*4arYgEW;FKd}piR5LaICTM%>J;Fs~We^?8vT>cyThGYCT zF3ZgbynoeJXRWE-zTaZ7Z0Zb+ROxEDK|xM(P5Y6<-@;dV;#+Sq9fG7nti@D@qMM+f zvWW`_S4@F%3_eA)J;SjzH&KGFP^_8;B=gCIu>nM;fbQfPzoh?^w>a5WWghA5w0nai zf|(L4MEiF_2YL~e6Y$PR+me`-IvK{=%zW3NkcGd`f>>uDTskMbHqOL~)q7}EE8ewu zTRpR9XNsJ>#skm5E4I!PKS@1e2A5aHE|W730u)1(;;aNqMMvQ%|8cfctg&G{G8X~& z{C=uYf)zxb&XNj=i?OzAhQvy(da~O7iM>TQaywnk#LB4NE`HzyCIJsy zU2md_&A6LX*Nsh)(;&83q}SW4LRqoG@+t8n1XwQTAEs5x%CLK9agezl;KG+Fju=A*I@?R7#?;g5If8 zOEVe)($=|CvoS5m#Chzft<-tjQ`ku3Hr>;)(FvSZo~CI1GCBu2j+t@ONY&A}>bXwB zNd4L%Ey^iCOrC;Z!isVFglX5{*Y2mkG);wA*QS>uq*Gvqv_5jt!YVjhj-cBICMij) zN6It;G)FCeApUqbggNW13f3J=$oGZ)U%nFxY4l>1KXtj=%a&JM+d{@GkJNt7unoQj zW(`Q4rbK1xQzYR>TS#(fW<_Jejd+WT_t*_Lxfo^)w*ih~9v!Gpd%STBusp#5I~nXZa&&i}m>Y6g6eM{hl+vHwY=T;7v5V`7^^ zXV5{Z4q7fXlmN6&)8MYOE6_R#!QpY+GxTSonFX7bW>9sSE|XISVMme=82-~V;aUh9 zK{S_F$f7gO;vJv{1nO%fTU@2{PKidjJ-h>!VqDJTeNKYN>CMN9^>Mpn^VQ9^FuUX7u?zit+qym8_*yW zMyxBDOeE#@{2oBf=|b$Flskv!6mOC%zQ?L;w-aMz3T0u(%Va0yE0+tm%wV?xOCyk+ zS0iG;q(I*+CA)&xNI)A;?at(+RhLM&rJlEibkkZo8n%l#IC3JQz%E^w->`Club)Og zqlpR#l@!tCQV)-s9GzeI+#R2Dpn}$;hfX54GOiB3P-ygjH&9nh5`|XhpQj zvsa--X=S=t??QlveNceje3qY@p-Y6iSnYQ+lnga8MXp+AtOPi{I+`vVJEqn|NZR5M z-@%5OWk(8n36^v&4rlF0;pTL(%vysJgnD*>-@>=8ZaY~Py|~jT+6gFST$WPLOoI9> z+CV%2W#BPPbL>m!*~#cow93v%Etmdbnst%_EWLqEV>6|&CEKEw#wuaAgflSFtXOao zvQlvx9O;5XunB!N71BbQ3WG5h@wxHP-qaqLE#M`4x%aNUERNi!f;K{N| zT((i(9ALU)-%T;5g{({Tn_eh|K6xajFM`ZfH_Jx6N*D9@;3{ho`&GQ2DT5NNg^OUL znT(M+AHj++32&1h0l4{$AM4$7c;=Dpkp{-l_%te)qY)sHpR=ectyGm}{q@w& zy-D;L{6`Dl=^7}e%uwans$V_Abf&No8sl7X%i4TKP_$^4ymZBtMoD;m+nyRRlfixv7GLdf%=l^d{8qYLu^z>-B|(yrPc!x8=vg2!8*Po$_P-){RNgXC ztx`QHp>yiNiDKm@8lC#rm~T7j@9kOOF`9_gDtYQq8`IVBvkCJfr<%vt?-|XKGx$W2 z;B@_9NGrlbXU+OLw{^O|Nun8KGL%xA^|nbu6MVve(9~`x7XCxO4IBkL3CYjB|IKfV zxfu|yrm7qdanrI8y?ZWhNRaS%xUD7NZa5nsiOf)`Cq}!cq|niKe2DkY8o&@*ryDofyAvbpk&Zx4a)`m!LjXdi5pG4LD)X z=S!apxE)yHykOiM3Kb}h;fd94#L7@#KMg7 z$ColEMO)df!Nwh)vN1{Zt3Sv7CsW_~j=!i)0Ic%NrO_6iT9-hRWf_`}yTxX-48O(aY&nk87|WlwN8GDWnI8_=Tzr$_#0)mcFk#4^xy#h7t1 zK`t^xIgo9a$oS-|HCs6|%8Y#!PpNo%itLL5h69vSW;0TNSQ+%>zu~{95A7nvH^*|t`*JAe0N5A!%_VXV*E*;Dd1CBs%VePASU2ihkEI&-u`Euu1mJ32z? zCXv>vLCb+E%IFoM^uv3f8&zH(`@h z+UIyXnqu`^Q&{M-%;rfdNONbwIuDm|1Tna!`K?I0J_6IjxCvfYx)N5ZZzyongMQ|k zsdhd;Ze1!Ky!GCW7g%C3Z&Luz@WnHt)nhUg(!@P)(fY?q4C;j+Q@VKkUk8V_fQ#8` zQe^Uii^&ec2g~4G=YbCVPUAg6Q>G#*dMw%qTDhYV>KT=tJ{8b1Z4J}I1sXj&FotmB z4xRDzu3KmL@C%X#y!| zJ-cGL~be=f8IpVIfXvmF|sl z2)E$=xo?Ub!TwkI0uq};KU2>Ch<2w0?vKdhghd%oHub%I-NaJ;qyK6il4%>G4OPyM zg!vwoR8<0oGYft=A2ih5YBDOQ$2T|lU)0qP?7S8!lWft2iR~s;O9XdNCj5vSqHT;I6jbKn_N{4&?9pfM9v{ zV$@vE#lSA~@-6D(zj8Le?0bYFaK}^v1*;xzqaMUWIH3{bzCY))=YAlJf<8k$^vODH zN_D|m%+VWmo+mrW*PiDTwm5Wp5Bb`B>Lyyd4P2@TJ{8p`wjx)M)fm5)jJ5~<3RKt} zgp_mYwl;|zH_mmry^eT##0>fA2%EgBnkHqM3q6A?QxE5`*Soupvf;RsAQ}L2> zE)P!;D54F`DTKh;3ruy+to$!=Eux7BYYDwUDQ2Jo$gKMEi(l|2!^fffGm2Rz&?$)U z57gT1-&n|eTOVYDFb@C#mDo>hT-%2k%)ZgltEa4*fR6Soth z+jdX>A$xuulCbDPY!@Zi+D5yhs8Xg|bjZ~?`&z{Z>P=9mb5Lc^T4>QQ@l0(*qzyUW zC6o3!{rLc=ODQx*g+u8VL%f6-!X#o_h;JR=V==Q07WJ=1ke$W|2iwpY9K40sV7)0l zO|JJ@b=y)Mq)>;6{VPC#REYl9jlG&fs+j=?yK^1mc=gA4aveV?qXv7G{~*jqDVUYu z;)LV%DFE3u(uCxNoRHhy%43JL0e~;Ag6vw0t|R^iUR62UELU#EoG#cukB zj$b-!QJQ$KP;Q6b_F$9sUopX?=Toa6s^ibu$Jp&{}r&E8_@JD z+tjnOktK5zRgw8y(4zG5aFu?{DD1`U8Zrqg3`z}ZB-6Vf>0B$9M_wElr(!?Z7NmwO z4ZH2C6&_#+2990>`M%yv%8?Doa`Y z-|MaN(D_ug1^3Ahbg0-r@n-aA&({mtmcu(- zp6fmjSOGP_A{d`rOHPx{tigX278QFdhJ!{$k32L_kKWnbRN|;$i6IN@XFzg?k&-gX zwF^<>ymeIDuu^C3kE<2c`TzrDK751kF!iqTNeY)Zuc(gO-k)#NX4#eJNWyzfFdp#9 z8?hJZdJ!DF`_8(gxB9bc76tKx%M0VuYUK6-dx@7LiCuZ^51|`JH4qL{;*tA%*WWK~mTaNL+|AJID)_g@D`v zzC3s!U6>QPiu)%C&3q7M9FuH+Qs7WxmIv!vX|CbmdoX}yM-^1uB@2UGZ z!v7><=Vi66EXDZaHofmRvZLo8%>0TfO{r`Y`E7}G)ZOO+PKy(x0=zV?rX}3LSgs75 znAID~wceK#GHfDkX%++M8l!OR^W}TmH#3(U3N-75%{)kxP5rdFj^BzurY@figBP=@ zxU4DITD95`oCbP_Sike~T60MRUvY0_J+;FSHvjI%_I#{azRvd|U|wKtMv-*fOIQo% znDhFB3JfVyv-ckV`^!tv$MSAYpeZ$Kbibjimut%CHg605NMU=r0 zS4ipsZe-IMvBE*?S*1t~Y~$b_J=@&b*^90xRg}+HXYX3`K}21EoHKuB)!>P>h4HA` z(0!A3Pko*u;(4{!c?ivt3im>R4D<|X;&Ro=HYZJN3%G4y$2U9@@vwa??&TKqn|rD( zF_?H6{5=LV&FgA|J7hISe1A^jj|iHhLr##LWOHZ7{~1&y{pwiD{vhcAQCtCgu>O1X zpAUT>k8OSLo#%C+1RrMN|60nPqnxd+ti_w(DS z77lQ|i>Gb*JGA6Y66_N~9jqi>C0%V&Q8QKEU#uR;w}~>v^nK!%9SopWYW6SIM<1-x zv#nT}H2-9TtTwrjiS&R~c|G5p=x9xp|NFrf(lpDjVW5LY2GFe*B=Pw*Q`5o_8`|rC^OUWz$#P=vooxdZyln z9#aj*fRM6^1$x-fLJH-XdFI}WoER)@OjK;NJxh0OxT&5wY$d*-P_XP)ey zQ)Nd1kdp(%6tfD0#1hbdHANpZzq}p(uWbRZUnp!TSd179&rEBOkZE*^HWJT&V2BM+ zX-Ll!o?!=Igm^Ssy1F&pT4Bu#-Bn8{nnMWtTF3>M(?U$N8R&kBC=@O%Z9AU(1Bd7i zdY9WBXD~d;eSUFqZ!FpjhmCY_NoFz@ncw)FU;ifg90m9X_|L&u0?jk@NvLxY-xHYA zcVZ>~`)$3#pQ$MNYmMMM=`|Xhc6IKTvuOZn|)fg3M3p_7+fK+z-yLj`n+1- z9%!D%2yGDvFkx2%=d`4eo(!zSDyfMIhrnsTLzLf?GV>s#xpKP{TYwAmAN)R;Vx__Ee+WpUP+(;XATe&czQ+>( z=0CIR^x_Vu@g@Mfl(f_8q=Hl*5!3NbVCii5;xPrBbrzrd(Qt1#vMEjf>$QOWk81~E zujYyb#=x+f^^DMsO^n|)3O2!L}D-_ z>PNzo<5m+eN4Jq6S#wXoYZWLj2FaO^ebB>MAQNtg@aLn#sykV~rN< zq_gf^b5}Elam+$_-Gfs;SYdOq~*6{@`LZp30THnH0BUQ;-TiIkIhqJdT|2xFp26XPgd7F!>>A-XlrM`lNd}I7VW{nnpoA zMj!EJUoA`{xoh~~7S30hSOXQT^84AwLk+dlw9q#}1O?9#ytr9W2+ulkjpZVKw8Vel zxonBC%oI-NRV2)2&Ie^{1l7dX>5^t`NkC8PuL$cezpl&HEfDc30+#>Uk^gGj_h`Fj z?86*L=+OQfGy}lqJ^m~Q{ipwz6(j^PqF)MwFS6eIZiZJBWI>1-`7>WA>9<>~Zw_L- zK~98xSY+@N4GjfQe$c1)6LjGiU3;&!fZlV>$fM`+^QABE)}!~X9};!?#lMqK(~Rz4 zh`bUUrbmtP`u6p0YK#%KPn$BPy7I$b%UJLGSOCXykn$RwqD`7zZ8RIJ2utI8Q96xB zeL`3p%Y*drS&Q+v@1u45K_Tz;?|mN2G6vo2w3~U%XwIWh`+1JJzTopHc<09#Mgu#k zW++8N=#5;R~VaQ>Wy5AP{b`j`?q9^q+rUG?pvTdTV$c?_D1qEY4`J5z%!}; zZV&0py6^URTf^3gqu^UpNO`_G4!oHq-AtJ{m7eZ=EjuUh9j$(HcvIo0h&PI?XAJzN zhwb~=>yO_3-%pON5i?L3khc9qa{UAwj*c72dEWmb{150s^AzadQpVx05-CRCoGqg( zjIx(?e1~@T%k=?2-n<@%Ub#9MWiiw{V}Ni?2tv(|)z+{Elu|1kYYF-BUQA`F`= z<*Kbni`QS+ye!rRm6?dw(vhZ`(2@V!I8dJ6BNYfM=Roj;0T#GKFEyxh-sKkq-Uw?1#` z18##NIx{nv2B6jY!3~2I3j)J*wd)%apqCSX($s)xPhp~HsvA)$DFKQg2^s~~`=+a0 z#DBn%+$=48GjEStL`$2y9avE-zg;WWs}Jn2%gI;hTyKt}8Mk{6`hS;Gjg|1Zj{l)f zFNlYpL5CGnn3(=DAN&FNbiRy5eP`9ZXCUnkC>9RF;EBTvuYF{DYHMpDVNq)8>#tv& zXvgJf67Af@?KSP8m}nE3O&AF|lqs#){txm%4ZoD43)nIQqPDDcV}?du`J;PK%OL zzCXQ9S7HmsQZSH1#sJfr!_pR#Lt!2Wq8NwFoTX;IMYOJZxS<`Y=1SOvkDMAFK6(1O zYmTnj45rm}Y4XYGN(hI9n#}7oOM)b7xOWtqh7sg~GDIaTdTT&+C23TYvRddbc9#&9 zvbMdc4_r8P2K|O+HKZC~Q&%4-%#hSrV1PuPRy6l0#y%Rs!%MTa^Xf{40;lN{NyKZY;1hwBOe)t!C}blV)q<;#Vq^UPidK?V2>2 zS7}?k)i{)`sa{w!*1E9QsTl>15WGZEbD6bh#V$Y~-8fTQ`+bR7Qu; zup9nRaf+)>(5^qHjz)8xDz`KFwCMqB@2{T~BvW*8MpzbWk7uE2=Y8U9>@x~uW07~m~-hZxOG2zQDveclP6OslL zMD;BNO9UNd3{r;tgMdUi84wipYNNH8k%Bt9Ym=^t)1MXxGq}c(Wq3&qzyc%vQlW`C zP@+W?{LW=@{=K_2;4v6605T2RTv6ll0<4BCX4ZAxM?UhA?d|QyKK8MF-?yhqDP7n7 z)^GjRgAYD<#~pVZIB)>KOJDlZpa1!v|HLOgarEd>lE3pizjOE9cYoJ+eV2&1tn?z^ z1si}ZaEt8y%j;~>2-b6ed8BW&p@5}eAe5E`gG8IToKVDjpTMM%v-NH_S}dV(zWK(d zbQCd52GPK}p54~|(|y<9aKmlg4i0VHx^e%rWNV+XIFN-NyynM6T+K$qYMco5XX-90 zWSYk3FkLvTEzcY~ac=W8ij)+^6~<^Dj6jB!T7#z;iYFF^c{SF9n~+8vT}8j+Q{MZ~ zC-1oa=0j%=P|ewXsqkKzc!_>7fPh_?G4v>aLy}A;xIybZpgFyiDu@!dzASD4PL=mu zd!&5$&mQ_^*nu8h$r(Y%YZd(FNk~BI;jC@tO-vLl#tg@kL<6HkkS7PFg3i$IfQoKF zzeJzF0dxy1N4T(M$D6zODm8bJ&?sI*?{N!&Ng%}p0-6}S#=B6xP6s_y;;eiW2dkMt ziB;}y3WG|rhd%WGZ|_T^?W(GDzd6_5 z``rHC-1H4;2weh56G16ZD8&v6L@WiHXFVNNKG7k=dX!2bS~i8K#ZaI6$y+JHZEE8dkJCbwHIrp5k*Is+>IluYM zZ$5I#C6{z`bo}*S|Fv`Oj5E$S?zrPlKKbM<%T}#g^|6nA?D*r4Kl$X7?Qh@np7(s~ zTi<&7+u#1lPku5CeARl{%QqM}6U%4$Ico1BG$pzPD4bLVLL1F{8_20a4` zt5^op3>2{H9$VLN+mTSF2d`AvjFdTGlOe4tAgJ@2D$)r+HESTNYnp)a5E7yQi`siHe#SVg(3zP7iC(hDCfI{pd$8y67TviwFMT@Pityz}YAKKp@d+f2_`qsCm6hA+MwIUz~#*`<(38CVDSmA@A zRF-2>PgJl9k*C0J7q;A0=u;_9gK#dXc?d+LjP7YY3A;tf@jXu-Mnx8Be4s>2gH>h; z*{O31OQNx|Ar=C}VjxtYs~|a`5mb)mtjQ28eXeMN<32V>Toeo?pA>mEuH!;hJEtaD zQ?`87sQC;*p-`Yub=vHfU0M~Cj#atB6yvps?17aM(4$X2an!tpt-ghZm|^|cO$sl1 zDilS*0HP*4lgp6MqBsiiv7t#CAwp>qWGgIm1(E{kxNj7;rm@3Y>0u$5M_bw8*=W-) z8X=Vg|%s%s1hqmH98nBbu#o~EQb0v5}#P#ARMe2^G^NOpNny*Q;s)1yD#p=`0AN7#NnrCZN$;fne?3 zL!g&{Saiddjk9`dv*z|>!(BYa9P@*QwWJieRvk zA{wj$RDe9G2NfYCRO=AwAwsH50twU*C&8I=iijj2k>IE%u#ixg*uf;gh$!fb5*dLv z=)HSD9aPLbD+@U(p2M*Avq8`T7$Y}EE~)0=iLJ&&03k6JPieV?wP5%d`W4Rb22!W$ zO5_!sx&x*idf?7e6W<=}jPrqGUV=N?^sopB?S>hIV6e=D3BVclnW(G=29Tsg~ zf54Q-QQxKVFA1cjzPcQN%C)07cl z6D4wa@4B6>KOgSj!ElAC_$z5MUC~UdDG+!}=6NZB5;eTMG{4mbT((XLAyJSZQ6z+9 z98e^6WObwhHmqHP&C-HkZB;#q2P=sN>Yj!@Wg8=j%V>UE^ishPOIbKp@}7*bqs`1` z0I&$2NWBTB2Fx_kV*j*P&tijR`?7$u0`?F_#jp$JVZ}&7G=S?qMrTTpD0vW@5(K87 zLKv>w&CQ0VsmnvSTS6@H|4AE0<7JI7jgW)a5{_v8i8epuw;!9iQ9xPgHu+T*fIyPu zLw;~%WHfVK(##CXWY9f4qao#JHNaKKXp+H-!Baex*ak5AT$Z*c21t}3Lw)_dopYHo zc%{TLdK%4*MiH+`Uqi+%fOQsZE>7tqRoB%5_ zRU;9KJ#>oK)^w(t*J0^wQ2@l6hADUBV{S-cS|vuIFG89ucvvNlBhXwSK;1~1kqyv< zwj)y9jM2(V+(N?OVNnQhoRxWdsmq#<-UG5E#X#zEb>tavkjWmFz_Rl}s{(>(jR~Nj z`sG8ASXzF8ilg?y{Nb&|_ndTi_S&r3(O|mEV?@VP~E0ZE%^7jd&du~d^b49gxQ zgd~Q9NlpnVd5{mipEXb!prsQZ`|yym51Q|+$^;ji%{!1&ICuw2Vv5;89jh}4OPZt) zD49B`Dty$*4>nWa#5$Agf8*I~uuuTwl-0>o*!g8*NG)6t5;Zr#WS|VyVp5K(Pz+%p zAx#vi-3R&T;n!m%O-#3LcNYZFbwbEN#k(k&tllHCi7fnym<=SY3WT%bLlz;hfn!HBr`E_3 ziK)jn6iUX!N(k(Ud*A!xVqmDI7G3Y7CCl2?CLZ z*mR}su3^M{fjYn|Bq%5oL=$~3OSu0HEkF~&U=fGAYls3B02L;>E2J7MmkO(pSI25d zLvvdJEJ;>7WZDbUCwfR2WXZHx@*6Me@Ggjh=fb+Y4F zaV2By6do`~Yh@1-f|;$9?AjAoNCNR&hC8MYwRWq@jAFQl3vn!=%M6q#N+q&}G^s;m zl$ujohD03ftY_CXI?{P}|E~L)+X@nkjwGzZl5mjf$0Fi1Lz&gTxwTORG1Ta3{Hod6}CNSHhTQ=-?HBMsqm;84ajA__sB zXV){LGq)B)Ib5PlL0g#0Ft9uW0oID1*HlcJ5Zg=u#-M20-Z+O?P6)6PGq@m#vVc9Y zSMn6qL`gMlDEr~+0}#}4Y2~!^vm6;=4NfS5IM{WY>AWr zh=uo(Omhquhjuk-E17}UgYP+7) zH6vrA31y;13^ciX5N)@m5{!_Q1LJ@KqX-pt99_c-^j$Gkp~qo(%)v;39f%2zD6zg9 zgp@QXe_WA}BwDogKh!>Rba?0hUr(5=U|8&$2b4%XV0c()V`h*T!jh>fXW1}4uxs1D z*CnGY6@@4p%pN+6m6_3yOrzk4PB>PT-{JGLs2;NC;;T9h2|_V=$nC)xg{rDo|)LENNvcP~~4VV?i6iY1iG} zh9;@K8D`m4^>l|Y<@cu3){G@f|4jj~uwxc3L~>Au09_%5d-k}{kamm5h(enoVaau% z7(`R$olS2mIw2hE^(Y2+&E*4tX3usd5~6|_sMkB(meFi}V=PPD7$8(;Lnp6l^P9{0 z0#GHcsZgE|33`=DMeHVFbi0VVYgq8$VU_8MDXT3MkSxRlkEdtS$*Pkp3MeJ z0nRBas1Z303W&GxhbY##60BKNJnduScy_8%8IgyZ){OBY41yu{to+!Nt@B4!VmlyUd?Y$3Fac!I5yOY_eIJ@@5FyLiWiT#xhYLVvySj?r>0;4 zB2B`giKW6g@op?n2F0~_@_QiYn2M?lN_2^gsTf6CK6$B z*9pTQ3NWgTT+QiO@L@tVk36I5j>GF0}x_~h)FPEs^#5T6k_FPPyxK*FR`;7 zMK>TCvJyyE0*Ui9md;C-^!04qwEankOkvHm%@Hf3LWvIuNE8le0Chls@#tZpio3^( zMT%E@)ee=SRR|(<#L>0TKqBJsMk}HdQe~CIdq&Zi=$*Z`80(lAYH=D*W?YK$Aj zK@mIEN9*VSN{~Efu=c~D01GA75Cy~p69?9Ky#bJz5p$*n6)(#&aa_c=5&%cj|yNfG!HG5fA6ns6&Q_Ns}H7j5`D)N3f+SH${J}8~0$o~#|JdZFIS75Aixu$ws@hGS%I7RXEiJD$#)6EICT3MC7I(SN3 z@nout#%Vq{*T`(ph$jX(s7&|+i0Luqpn9Qd1;DCCtu%kNvb^Epl(RJzbu3N4@l6mc z6va0L@iDEG$f(JGSg)gIxUQwEh3Z`e&DAWOH6VC*8r!r5Sf3CgL5d!hDffY(40dEk zZJ$zxma#Trif_1ojAyyQazZts3}oo5!m6>TydXm`rO+53q4H7_}5$q-=MT3TUUH<*Z4-&te%VOOcxX{Y8zWz@VJJs zro52tug!W2lq6}ij7(e7cGUR%(Se<#6BC7_EL4gBk=kA!CdJsW0ptn=>OdpDiqh4z z$JOvqn=esClcFRYl@QLP(8!7hgjAdet1tkO7Sej)fJ?;fl{63{%8z0awvv?aIA@46 zy>>gn5~{9(pA&oHAUam%Eu^d$tmH*1Co(RoKK&2H^J)wVi{UALPx;Lhy)z2lR=i(T z9n_MdRf1fo_6al1K5Z74mjtco+BSax0Gxo`e(GR7+YMGC)b6PP0tG!uiHUq;2pa(4 zBf4IovPo_KF;s}0(AM$3|7iQ}Q5`3BJT({b#;?t*p9l&Kg||Lj0}Kn*;y(9q06f@- zT38OmYl0Ga5*5;}iA}X%J+bSaaX;#bC%j~o&E)5|6APK+(M%BrI)yex+(00Y+2aRw z%bcy9>sF_~7#+z$q(Pt8M`m>yOITS*J%)r6igBxBo0ZU%A956TZfJxZp_xSQ8Ta^NihCvWpN}qCNrS2U>!Y>j zAVmX!y(du;t4s}_NdQSSRbDIRyxHYGuuuu0sJa-}nj^i*B5nFnX{ZTHeKlXU`8Z5IH!iiD>OU9W#5t%KrJCKV3k(MlQyQCw`%>p5?Dkh40 zpWB>gbtpqUD)-vx;(!Q!9cI4~Oq3$Be;X z#Zb43ULhndLa6{%#Wxi!1}&8x8rX7#Domc?of4BcKVI+5ea1W%ON5O8OTr|?4girj zr(j_SMBsc{@YwtWhZV_Pikh%`hBtnlv!sQH^{6g$7$^z0;lQHJFQ41Z)j}EXRx-5$ zmav2Dm?^}{O@9udhE$t7tNetiXDvEh77ubfOYx^!pX7iUh2Uc3Sh`m+&j`Tu-GhlF zX}D20(z>MM$Q`{~2X+k;G9rzNqc$jBwyr|IYMAkgng3v_%J-MfL20BkgoIE~>0}96 zHL!`=u_rL2AS#F)5fKWaoS;mu<`s2cmy%2y6Kv{J0XLP9Qx98=ERU{a!#sO|^}2@yFW$6f~;*|PCsu1BF!j98e+dV)AA z*m));DqNzR6iz&|B>{74WMc=-shzR2_cuFtJmr(jqbNwcLXlHAEGgtCWnl6t33@#+7)D)fyi|iw1rF1?eQu;~{(*qLilvchN@vdP8i$kHO zX|p1MIIsf}(iCJZRVr^*YHk1sG=paQC*=ODHds)=scQwbgn~hp3W8HQ8i6w0yyL2+ zs4ZzHP)nhMm5KseuzAP4_0!fbMd+6WmT*-|NQqPUTa=-Qy}=AtVn|jFm%sr~5D zGlw?Ns-c}vjTX6gErnNr>#XhR+}?@h<9^h$SE0bqD$Q2uHy{GY;eP^DS*YMSqX%`h z_HOIg^pN}2=*W2RH>0~0isgcx(%lUfN|$Okg9X3^XNqC%Vu($}I3;cnTSK8bF%f$r zW^&F6Q^6#Tw6)gK(=$OCRx&%~W8_s<=j3oi z)BqH&AZ~zB5*BQkn)HQ0AhEMmda-IzW1ysmvsn@DlN90rh9vM=q{^krDUbx{Rb23} zJjG8{hyW?H~=Fup_{6k1Qn=}jTt6SWOrd@h>&B5s%gbQAM*FU z*dO9KcjSWcAQOr&4VF=oLX}zsNh~A`e5BC&i$y$%N;=UwFz=zh;m1cuMwv3<#A`vy z4WEzeNFy2Z4GExd2v)RouPWLE)!V9tz9cS(cin>r)OuRCb!`|P{*6P2Z<4U4M8_Jz ztWbU#Q%}*=3h`{bx`XQw^u*)ifa-XPUHYu#jj3P@2^mZTt+m&N$Bu3c%w#FZg$7o! zkFj-xB+snITw_PfB5FJ}VHF{tHFPv}!*jUjVR=f#SX1PLRe?ZW@(6)4abz1zU9xaX zfyTf-6g$L~h!x^dqlhJlHL#UGOX*ovKP1ptsES@imt5oehOgz2MHL6KZobA2br4hP zaX~RFY}+IlEaPF7D4BR537EzHIG)W0OM}5e60*K3AOZxM#6T*K5u%I5_=XlRDbyq# z!RjT*i7UL9;reLSp4RIE3B6pRpF+Wziefc}_nHc?Ca3HCTU0EeE|_9xzFcKUpCzzC}YmbPP9C-kkE>k0NEW|qu&s(8^G*j!;Pk6ZA;pZ z?4Px@zkdXI(u7iiA(x8HvK$yiRAiEq7_hCTAWs0=DIiViiI}J$6i_B&qMVSB0-O*x zNI@zN>b0$nCZ6gj##@rsMj#+Hi&-EpK)mh%f1dIv@SEyF; z{Ft>;1y{0-T1rWv;$GSQicXU_s0-Fg5>N_q&=i^m5qL>MMUM3!2nI_a49cMCb0Oh= zIh=A$IfW;{fdr-l8C-k-MQ}t^R6}nlh$9wwQdSZPy+{NotaOa)T>P~2mIbpG&e?hp zO9BZ>ZzlW}7(@t=mImfk2o;NPyLY*@$Ly31E%%J({S7zRKQ>SxBSV6m7jV6(cXb@l zIy9^Bq)DU~0YK>Z0%~$XCnpW7-b1uvo~Ms3{)?8^Zpt28UEE39DkyW98WV*8az!2) z9>8t}D~cP0?&%D&1`KM_eb%#qs6jFT79u5bq###VUsR@?DS@_j(7?`vsnMxf;Y(SX zphv@CctDx!F7?Dh$X((%$yp1C7kG$=cwwIwT<_{=IWU|4=*YH)uoG5M(x9P7N}d=H z^O{YV6GjmaPEjO@l7w6v3CbH$0G`U#WdLA8l7kdUu1Nz=qAA6tq6nP5gKpCh8%^(Rl182ctX&S7XFbWD;l0x7;kioZLKdmNwHXAGpm=XjJ zOCotvC4dUmChE@Gni`Ox!pb0F5hhrDvW6gus9yNT($#~seRlWaY)f~eWgLK|_DOmk+>4=q4C{art{k^WyO4&G3!jUVf#7Yc>Fe#I@5m91K4#dK0_YmRI ztw;-3)O_#E@x%N1*QBX%A!6bW0s4k0nwN0Eum}|&RO7!0*@OT{35+mTu8OTYvvL6- zxL2kJ8Vy!F713*(!o9MMX>O52uvTRlXv-i8yzSf+oBA+4i1g} zrswY7g>w&n>NsVo`-UcJf=xl{p;S}?AfSSXA%zoYt9GxM`7>>8?9z?(oD=HS#Cy%X zh>{b6vdfF2v!}PmFXDQeH6f_nlWEdb5g~D*DHlumkYZS*;}~wqS{7snZRvlKC}}3f zf)9YoucgD#d{Bl;@jAA^jZH}2k@uvIOz0IJ#KZ-p0Oc@)#g0HkUK(wBuqN$Ak#jHz zC1hQ>z==GZv1$u2;4C5H5j7t`3KjNAqtn$pN7K=k@gAkbXbp(eTn*$(3;#;GhE|S{ z%rQoc?Soe-TEYqNuqrPFoE@PCOOdK6?zv97K6)n6lowg zs2MK@Q+?M2R{R`lugzc;!MZ&c67G+Km0akj3q%%;i~GcdbfGi_CG8#;w4yvKFn%hMR z5$)pXi`thzIq*26Jqnz2g@*;}X@I7o3NbN^5E~dGAvOfaLyfqfgPhf1n{pfG@+48KS`EjGO<_=0zzyLVNh1-DRD67BG#sr*kowqDGZKr1x*J)PzNTYIRGTN zx&{(hH-Na@W$@P|t%aXv6%~WI*;@^4QhX6IPoXI|1u`ImuYnU#4croOcMAy}tnj-a z0LVS^98`n<9W9CX-SI3pSkx5k4O=L7Aci7HAjdnJg#i-56fq(b8;u}>Q-*B^t~z-) zI)T+K_Yt|#mhrAy@6z_etW4FqO~k;E2U>URD0Z;YkdC~X4qe-}ZlDis(xLF+LP-?f z8mWN1!U+|*D{@K-tDYlPKv_bQ0i!i&3|b7LGJ|B{MzC2GQfXKZfW6jT56zo5ed$v> zHW4{(x&_tJXkUheW~wN>BScG)%Wfc#7G(Ni#DEexSnDcE%v7)x%qbx^NM0K=S`Tdu zPV>2N%2wCQ;1F4nGo)OI0dA0i`e;z984$Btg@HB$vExeD1J(I1|aYrH&%RWbAn=f^me0bD{1>BU_b(NK^z+xPtvSjn%0T zNrGXgveUIPqT_5ZC190(2EDT~+1&|XY3dzt+!_SHhn=DTvnB;d!3CT_chMqJ)Yd}9 z)k6G3bJnSXyGz`a!tk*c$46JoY!j!TtchpAL9>wS_70w+EPnw{Kn?!6Ea84S^qHTX zoJUZvKkr(-o1 zAgzGiCN0X5aT&nJB3{_O$ru-HHd!u>0xL^e@0>Qeps#I5KGq;;^rmeTl~Au#V~(nW zhH_~zQXE6MW_2h<_sR^G32y^Vz|mlN!_Lh{QsrEfgQL&IA(juW76BYG2?k)00aasK$2jv6!6w)Hie{5yYKgd@oYC(q#CtG1KQKPa!XnhDiE_h2n{Ql zyf;fhp0#`nIZ`5KQ3s@?OvI`QyDZ^^zzl1@zy!y{L@dyTk`UFYCd3724X!y(l^m2I z-bA}pp(IKSQtuK^*0hhoWM)cyy!8{Q^|WGbHqC5$Q5E=#rkZVKpEPQ--9aud11;~+_FpyW1He?U+>J<()5J`nHDv}l z(v&#?5mCZKL=Falfg2D73T`P}Tj88afy6;XHCIcAiKyg6>XY0ji8vSN_h1cCnpiWK z;0)UB9+SflodUW~87f@3JX<#L;@-B6_mBV7q2^J=S*lq=vF@E>-U9_=78Tn8qQX=L zh(MGR3CO`Ii9iy-fju-)O$biV+Ft9}el$jV>a_+ZU}0jAk##|&CXvN3a)WbqF(x^3 zNt}=ucoDUA5(#{(KqgmJ_R1m|P^fs2w`xLFLa^&XDyB|NP!?fuXo(9j3kfrcqtgG< zaHnE|hUS(Q$4)drf}}u}BV%|Y>IHZc0tii3O{ONZ!pZ`y9wO{J^93VKR1$CsPQfj3 zEkFx61GRu!fvjn;kOap{09AO8A_27^uRX_f-!F#{mE>ZxP}Vp=LZ9VQUXOqh$|

Uz$K+5@;NK40<6 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 S3z#}e(ooetQJ`!Q^8Ww`gvfdT literal 0 HcmV?d00001 diff --git a/tests/_images/Show_crop_shapes.png b/tests/_images/Show_crop_shapes.png new file mode 100644 index 0000000000000000000000000000000000000000..655f20198c238b11f26b03419cde4cbafb5bb3c2 GIT binary patch literal 21785 zcmdRW`8QO5{C^l442Gr}B0G~kBq7UK5?Qm0>>(7%mdIE`vMX!$eU~L9$(DU5NkT}n zC0p`+&inHpe9!s(@NrI^qh{{hx%c&YJ|EljKGoK|MnlC!b>hScn(L}cx+hMMM8h8e zBq{uh)tFnti4%HXuPZ6&d8MwUdHSB#KR6!f{ru&T4<30bghL|+i3}s94kr)@LM6pG z;UVF$`m8b<9lf7#!m}n%o7vJ=1{A!yOG1vPM3b^N&wR;Cn`Ira^P31_h)wz2(CvNP z%K!Q0qotQ(Vj15357M`psjMTB2vT;&SErm$1jw`1oZ&DE^5O{p*5tiSfx@zde{=Ad zm!xGEx9fdz;bxw=xHwyo$;t{f;R#yGaC8H)g!j8Q2-w%r1b}ooqT)vtC7Ga zJ|c_v4D>Pzs;031I~U3-bgTaUc!}}Nyc<(>_hv^6Z;}PbOESCE=6B9BUUs=9$^3Tr z%cDNK?H^;s*Pfqmw(gAj``0%pTDS1;{!&Inc(_Z`W=AmfS=oc-?4(<6-BB#kR8&-G ze52?3uc_)K+a$BRF-QM{mHgH6mbY)-_-uY_FBl^c#-Bx;LY7hxGIP*x8$9^R9sw4L(%qkf4kXS zxWnu3-X=1$FXeKz0DriZvGL13JJT9_9ZBX6>`77*N#>2+mg6G=wGd87r~}J-#f^)f ze>F<_*E{UC3~S@L%)5%rPVbH9cMsv4*bStY4%yo$kFU5tSn6-*-S&C=?_f2C^V%5< zM*bBaH}~SOy70`~$B)?1^2kboY50n*fhYMB)Y6x#tExiiSpRjh`j1XbSVwxN`|r(# zo1C`(ea{n0ZujX{WEpvveV@K z#RS7GnOUd5F@rN~7X{uMKe?EP`{?+ZBj~SROFY@)_P*wumTsG^eP5XYehk%eeZ!1P zvpHSmgYc{-bK&17m31(P)-{h+cd6<7%C!6EiZ( zM^?~yre}8RUz%GjqVpV<&3?@^*4-IM7fLG5%L}oc`ge2)pPQx`dNJfGW5~+q2i#rM z-jrvQge0Q^QjN zg7{nG`diadgEj;Bd_6wP<7t;hK@63d$CRzy-;K8PtB>IJn(6Ag9j?`x3Y?i#D4!Te zzj|0bAS>;@JeYdr0WGVnjQ>C1V0=tQMn+m%v+w@addu;@cL8K0`C7+o@PWUVNnZZK zC>QGSahT72YmTkE{z7Tpoy=Gov5ulPiWG~(pN_V@?g{4hoK<*gI#YmpU z1F5t@(+^nxoiRhjP};E-cazdu!*cWWrtK&;+kJbR^TkC)95JdcE@d^Q4GS^L;85$azo4eFaD`fuLDfgd&4?o`Pl=IpB#X=jZtkc`w%_!$5gOHSrYTWwB z@45bkh9x{d-RB2fLGuQ;+$pCHjhk1It~o_TjzH4Xvb>q z>|bx($e#*u-*4pIQoCDWQYvCoHnF;yVI~)zWuM&N-*1Pd$ST!7e`3p17B(SNZOv3k z`dA;AH!FE(&AlvPx50X{#!{T(<^PhCpYQ*B=$d(X(!6A;K}t+aOl&N{v^R`Gb8PQU z6AnJ-*5I$FO$cgs1jz*~Dm-{zQUR^^qC50 z$BTK%xbD&HYtP9}(t0(US5FD(%eHFJ8glfPs4M8`&AxqXEysQ#t(!cuhUZgwwTcH} ztjY=b*D!ws+ULWSl@-|TyT4{4&IM#PjBJ-_m8|h$i&gn(LwPwcd13Y$)W6PVq#*p4==C}-GK`^ zaCMhi?Y+Z7)hPjo<&*zHlASTi%Go+zZJa@pQPopUXCm6?H$GBa3LwbN_! z9nWs!FxdI&do4$CTC&D)>x%S?F;wk+muG*vOPTs;eRWi@Qu;Y7`Z9sS6A;+e#S3Q& z9Jq_c=?mL!?!NdelskIssYK4RF4YQ=4uBw>*PBzWnk|y7$k@&VIRL-&|b>(UWexk|}-P?@Nj^(J1RYt&Nbk=TxeA!-Ji-7dN?ibAHFi zA=!X00ou#bc5Y6Nk-(W?!Yxm{F5cy{kZOr_t~O4jBMT>r3cOfWQu5oU`ND+@QfX0n z*Aa2iHeEWfdN!{0^!GSOq`BVpJYn5i*u42iui(}apB0!^0x;+0P^RsV!Mjf3&tFk zb%OGd)}MX}_)s^iZWwo@S?A<(|QeftJCzixVM$4Be6zb{RkmMMwF^Uo!YSK-#3 zSe|&5SN1Vc&{U)Yuq7RW6!sUOSd-GkEL_xli9vCn$oh@RPrCU_B=%Go>$0C#rHc z(?P{-o2xJqz$jl2mF_DASpkpyf)j0+&lM7E>PTkna7`Up+V*LlyN_-EY(`)U!m}sZ zN(%+lCL~pD(<{g1In>8@hXMF`haC|&Gch@UB{qf!pfB_n5*Pl>`#k%?rWe=l zElm3eb@9N`bltt%*IEiBqkw!w-}u1t4tow20!@f(#p&crrnT+;vifgS5$#)W&cKiA zIj6}!Co6`a_5ss=jkE1ZBqt4skH@6+@$k0-F!(Xk=-E?)0;p_e*0=4O!g?Y+3s_ap z;_&K@^PZ15(^cQS`w9vQ(@|es;}a4tqTAS9>jIWr=(10hO7ZS zgAP~qv7elN*Qa^SKaYX%6G6>E3!sx*LeRYn5&2aglfxV_uA7<-ar2zES`0;a~sj7WsGbQT>2@O-yR>gLj> z+sRWe?3J}Rcz43{OM>6StM+X-YJ_3Jeobg*8WFN(-2@483 z+uJ|ccovyde zF@@$iB-%Ec-9R6rFADq5HsyH1%=kLw|y`A|NGn9dn0Jj|KBz%C^#1HPQ<5@acqz-NS0lV zI<2f@S3R}j&SN(0FV19(&9jYGhNYjMbN-q5uv_i5R%|GqeIM0;HVK5{^{YYpSN(jN z=a+`nvPOY3J^g9Y^mqc>!s6o8+8_VF^Q?fG_NHh5)jCayKJTn{Um3nz)?oMbUBJc; zte!q#!=S?emihvC0svHlO?NEl99b`Z2QR#z-_$cOs1@v_$`gWvEyNb7axowgpIz#v zoIE6%hnI9GbBl_?=j*+i11##NR(C!*N$k73QRZJ0B9Qw69mmcm@EexhYG7dhAOcMo z`otG~L$k5!I|EvBNACMui*dYKc6~m}nV~m$PN7oGd^g*H%$rqOwL`}MW(Dtg zH0@mXdVeOx$Ua$!pa1T(J)6deLGjq!{VqrBocNQJ`R)C`esTlb1U8^S(@wRMr$Sr$ z?5YQr9yHFdup7DVE8uzA&bAU7?;rm=s;6{_GbyDIUI8U&Z>vX`-Kb2r@LgO!j_QE8 zv{S?#7;Jcf*zc*i6`ocqd8O!X5S57w=S%nqH^oUJ#B#xZT%>1aX0nGV zI61?!fd5ag!6y2rOWx)!n<30hd-;(dEZCBgk`d~Y8Y7I1j9It?-?#PlXEa8>+JFpW zzKLDEUZq02YxMDjlZCN1NCA)tziL$q z@bBNOl&(=i2Z7q~!soF;D8<^i<7?2+PMd%5FMMf>s4_BKg-F^&UcP(@oZVUCiQUT10noM|KYqxw z4W=gsq!&)FX=-S2H{)L_B8ual@RHb(;|V(s>5hB1Fv`Gh?@Q)g$_+4S3N?zBo3Qq0WN+8U1^ zUyY1U`#lxKA{m%dgizBLOS3W_pWmzycm(AOm*wA~d0Pw@&VXpO7thPj@66ric1Ucu zDl9B?7)Ui=&N=jzRaNHEOmu=TT&Wrb!i&BLRwlukobKGfcJ#Hxl$4a{U`xsfM8nR?F4JVVtAx1b71#x+Os%9!&?1W^HY4W;RpE z%rnJP?s+OV6|QKOG~V(z>gp|yL6uG~=3LciGu>l(4@G~~6z{5xJeln^J zw!-pii8d-UD_7uN9 z%dXYE@s&2L;wMa`p_+nw(bGSy^!<9-LpFAH9{4r+q6-gYFJ02dw11Z%$AD@^WP8Vu!d!er|57dR*69gN%f42XUeG$NERCS?rc{Kh&TP!xNeb> zj`+(P5-BulGM)t&D??R~${aD1nydoXS(7wpuLrzM=vkDS$A_{Y1XM|a?fVU?U+sx@ zx_0YomozFMip@Sq8PL$sRE%3XT@XT2f}mbJ_9;_$tZL+BKSst+W1kv8t#00_)?ijC1eo|4QthB(DAi`Og{I*ao1c+klE%o8_?(0G8nR+aXz zKSf0sC8o(LpxHRtnVu0;0~lErZoCf4DyZ#4M@sW0Q2iBXnVt3NBi%(Kin9f|YDhSY zoab`r`7dyi#A2N!Qh@N-i@UC$dHwUZa`upg2o{MjN?i0#pOAFX8_xv7~51sY80A$&7MrDqCXi(QBRfjk5iXReeTsw_t`!8oLjW0_X2byB*J3s zp#oYmD$ZlMSIQV&3|0VCJvY-EH~4;>C@!v5skY$u1ocHh{S3n=GWwG0SH>Usn4Vch z&W+I&vjYBzF7jGwzb^gw)lI;qsfC)qeqSOR{b*HLe@p0@%E&%NDm?%TKwswOwB?E8 z_Gdb}yCgGD+=XAKEpjHLZMfd4vX(sj+@1FJCOeWa zvT|eei3R^fEJ}NW4rK2k0c3OB>30huzV}4;2Zt;18tNzSiZdnk*ot7KvW!mmx=>RD z4zA2gY9>dkj<}y=;GC!JkQ5Xw4YWgcoQ><|LgHcF+|61?$3o|{As1;-K&+x*4SfCj zZl+|+@usdW&|ZV$1X0RwJA4$}TRzR`q0mS~a-Q`=_5eq6!4oT*ESD8UegSpX!GI=g zQZ3d2j6#)*W5Ca)E*Lp}A%>YBuG!=ya_0vc4;;_&H9_yvwAfn;`Bzlzi00Cu!;HIDpCDjM+YdC>?z+Mj-3+B0J%s8ZI1^IG~e$Evy|cprHY$qGkIz zqM%Ezn(en0!xw}W2#QHeOpJ_pu8Uc`FDYN$k9`sv?60H~?;l!sD32({4s8OTe6r$*Yp6XLV2njK?t378XQgW9D)Q*^rRfMcVV|uLPB` z3F~EQ+t}C?=gr=z*50k8#3x!^ zSE;19PtsA3s$~z!r@V`{HO#uC%wlm@O-*en<(mEVx-$aNWLU%ptfDRX@=tfoS3mUR z4IJO!UeR_Dff|=T(%m|Qxr(PQsAujfO{qjLza<1Gzn>QMF1{@eM60AtD{V8oF#E|eBo9>(Nuyu4Wm%y*m z$yRCANOT`Cztd5{CKYI9hvc!2XlH4h5klgfot=M%R-ozQ6E)&35e?#3Wq66U%D=1`g*8S7WVU<3MWap_ zz5RG+4E!Un@4YWY8ZWJ+%ZK@T{?^GsH@3~)mrA?-$$%xOXOTcTTuDRfu<6lwH6Y~S zg9Q#F5SPtr?1$=I=XG^;qnNL_%|E;R#cTc+oR%vi|mO3A6KENKoQ zY)Ei5xVhUMU#oRqZ6+ChRdgen`e^EFl!$da#~jLv|WVcovF6(Zqx){!o78h3D zym><_TH>sYIZYLe3oj}!Uq^P54Bxf5e!2e2j7yzCv9rb(%7N|IuU}VD4O>U*^XY>K z5_<+2t8+6eZ>BIi-(YrJ-TZJ0&@wV}t}Rq$t5i6(eAJ2wc6?L0~syA zi$QS*>>f3rGj?K5qd>PXYp6gxjZ_w(EKzO*nGl$EreY}ACug53HJO)}Ak@)_?#4*r zug%Ffcye{Sw|x~A+l-t4va4&l?8ilu<8|UER@Yvo)5fPhQ{o7ae`1MMK!b>CT5ThM zF-}Ynw}^Zw#WFgiQ6uQAU`~J)_d^|I&m#~(!L5G0T3Uxc7z4G>@}v%inwokRc7$ZxjdqYEH)rRmQi9>RSOP0ABw6`?sd1CN?%!8)qYetub*1 zLZeh-!P+uQH&kZVGO#U!i4H2G8C8zHe)anO5{qB1zE=gb-@)$0&N-%F@O1^J@J^*C z1p++vubrcaON?TbJO50j*&GrCG8(^62?Ve;m;9IwOrnu>$Z~d|-eM3)&I709{*-Of zX$-~}(iWBGo=)Y@EMI^C+|i+u)I+{C3X%hux$>3T32KWTjp}M@c74gVqA#uPSzRzQ z&(*zvp^BQfIjx+B<70UG;pmQ~ei;bGg%aM={g*vFGH;lm*p=F!NKK01e%uG;Jbj5> z#>c0PYg?*6r&`(IvhTTQ!}Wv7N^6j$TqT)TC(4r&`A9s!LN?-x>o-Knu(`4E{-7cq zd0;CTe}M&kY0`BC1@_=Uqw7qXeO^zj66Ia|at^tojk@pZpMa6fF-I`%y49%GPFj~t ztU^1=acxsF9bJo#2qhmF23Ov5?b9XrIBk6y|=%g<~R5`Redd2w|To?y6&@^x}|02XhghRy~ER$dVx*0 zzJ>rsf=Cf}@$x-UQa2zfH*enL=jVqT&~A0TMrVe)0eL1mA>oqC=Xxl7(0k~3#Hb0{ zMn++16DZ!_`%*xRpRgBCPDwfZ$X|X7Oof8(<1B}RMYtTGP|NV1sYB$?2hz~!`9&B42(a?=6(lWbpAyG z#mz=72-tM>_KIUsX?CXr*nsGD6GoC+hwa6|&#B_0(PZO7z?pv4qxX!g9J252>SEI; zK_Zk8>O3`(^@=RAjWg-V$;s}vNXj5u0y0s+{^cbAKqe;1GcLRi1_%Ozz65b9Wdz+Q zq6huI+eWSCA%f5Z-;>&ke~pR|9T%r)hh#tsvJ(<4EF6UQ&f$N`4D{G=JCZ86MBBT3 zi{bdCl6{ev_oTt1T8$2Zz|4N$;M-G`>@1uVGwq89ilgE3lBbm_7_`KhG_XGxdgEx z=k8CgdGHn%D8*?EIxL>>H`}X6VX+`6(U@tdg51!9=!Ycx%>4^O{w#eA(n3@rA^HV#M;SU z-Zbp^8kAiN5hB7Ty63K)EO360K+*?XeFR?=vJ{E7#tLYI5~GU_!#M;3DX_aoKQGoz z9|4qjcK+(8)txspzs8CUGyMPU!;ex0a)v6=7Os|2;+k3}Kc)9WN;4rtN5>-F!UgXy z_TriuvMkoOZr%(;o7B0?Kn?@4lzk$R2E}GoHk3V80EQHiVCq0x%kJR!3dCfs*cHQxWZwvH?Iy%16=e2r z%P`ZcE_)x-b))uQV5nbk@lRW6#AaF+JV;T;v;z(+i~lglFhvQ9^eLVj1%-uklKnQK z07i1*yMXj6Ga$`Ot7?0KWO&6L;F!z+Xlc~~cVC<2YJl+LBmrl@9wa~ibytDPQe^adKi(usyVRhk;vBUB$v4;92p$E-w|}) z_|oVUhj1&wqiOG3#5pD=u)f|N{h0>J)A;JuiH<|7Q|0oXB%|7}#87W|vnHzTox#c} z1vEBfs>S~p0;~}7EHQu}>OU!12w-`F+4)kSm|L*O+?{vnAaIJgd3M513V%tbqnJS64j*^a7K{Hf}0oEy0bbl0F4SF zlwcx5{tfadLeG0$Q(G-wIhbS*y))x?rU`8m==rhZvywCyo|ltDY?IatJhZ>%Jt)8#Q-d5{t6CbB90SBjl9g zy7i2WpQ1@aA&Hp>K^-x%Qph1xoMGk9V%OKqclsOdq_-PB_hKHACfa-KNx_ShtXZmU(Z+ za~9B6R|qjj33pAX{wryC7C4FU;|JIcB8=~*e*#jN^M0$9A-g=FK4cN8tOHtYuI~Pk z-(K{*g&ZgCr+y7Q0lZ+TFxZLbfNHX?5%Qt>j;q5=u z;B{t@07ib-c&RB|$*boF0J#Dd0%!Y9?~4GmNtI2v|MB50F%y}YnORfgKKDL25U3y| zgz*re_PTV(;R9jN`Ylj}4M>j$3+| zBURP#wd1>FS#51CHSfh5B`9seEq}NArPnJ2sFSlMR*89q?EyJfYjC^HmK#-C^(9{d zckH~fj!O0>qzu$GG|2N;?)e{1Ll%liM*(6BVo`rqC)Ob|0ewnWCRTn~^xd=>8d1og zm?ii_2I%v~u+eMBG2n!tNGa)np92YsU$ZSOHEmV4J&;cN3(0_ju^(XXr9+T(m?y6L zH^fNI;T*0-F@uT-wPB#YKT+#sfP9!V2yP;ut1dJ1H)<+-o!~JRO^2k!Eg>3zzD%I9{n^K$?MN4O`3B);6i+!yr@G zIXoK|$t#T*RYYRka=K%1m<2s@>ssHw`B2(3}Y} z0fYKD3^bn~wbxOAE0o!~Xba=5;cPrLt?VhgYq-!0rjcwPHViCV)*E zdhcRDW(ca}?`U7=Ns@1taFV1!-S*-|V~!aEXQ_grhUlFLwQ8D~n&TiI6$4Da>Pj40DoYrdMtezjXs=@U%6HQ2G*RRU%l3vcZKDRd4jQNJpLth!+1Kbqne# zbD1`7VSE4GoRx9yU1{R`g19)x=kSp71~Gv*9G2+L;SosdOwaHJN)r$2i67goR??2;7kNJ!_y~i?Nuf5;u%fEJMjk7#|)}CM5f=(K_FDy@`|_ZfA6{Ekaz1p z-&K)LCx3){1;e0n*p}%(PnRGW#IHfoICi&Fwk+c=z_d ztt3{zJxEVDh%+VUL3^JkA)^3iIkK|b#!V^>$sUZ?F*LmV=#NvHW}WN2N{A(}r#g#P z!sS_CF-}fJOuLbAq&yp!FnGyV9(;et3W>yX61_H}8tF3L;FN=zmgk^=2909^=<{TG zg#eUr$Tl)Q@7(?~eUI*(1d1KfPQraJF3uO1zfHb;?>zD5^strlGFl4=k`U0k#be6@ zGjCM6NQ<%8$sb!B6G08I)T=(f-(e%NBq3`IR|zO&L{@<|F8Q=!5UbV~s&fF5mCete z2~!nkT9o_+w7MrrSXe-SS==6t2W>mBRRlzb`;tzgFUy*?KAt@9#m3F8oT-f@fU_$N zRJVHSh7P8u>Oa{Hf_#uY1&r~|rvb?xEoO9xGuX1x6*3T2l;vqB<>~%dYoxy5@S>yy zukokrV@@^RoIpNP2d4$?ENBp9#9c_bKu$GC8-^XAc|C>*{)@ivL>V&X+W8B7d_JIK z0aphQ0wU3r6C?-=x;aNy+=*StJ`Bx(2(WwsO3q`DY9KpSGrb1I*0{n#0R(?AK zJdhm%W0z6t2{BFw%{Ike@gG82N94!w} zneia9#Q#YR#l)~*Zu|3VW*VYyVNP9$4N9VB7^2OV*mWqJm2h^gl{G35Me9~b(; zFD$(Vk>H)O)`9iux^m5Y2uYzkT`O7cd8t1UX^nWl;(i`thO0aOadB~`(!#>-o*u|) z6e#AQu00RYdEK;NP;v7L8&skeQ zV236cNVY?4^YQVKOqYO3r7t}dQ)Y9gSzu@*$R3|IyrpAgBkg-f~dg z0}}3G$v$DQ)2Sh(LJF9F`_tWW7HJQZb!uXwgys7nfNwj?LuBmnaNR(+f}_OG*F$ZA zO)GHwt<2S{EN{Yvl2)OFw15zvf8%AAHcqJd_b`NS?Ck7fOLRyx`Po54F`o{kll9u2 z@l-UT;*nG56o9D|nS}`aJ)PpQ_k-!9`plv>U2ybKr!6rZ{{MLsDIm*2QIr+`G?v_W9?b z$TRHbP|w}jWCk8EgZj$gjLeLXM??$;$iKd8^(i+)4;-^)uXRS*$qVQ39f=#2`P zBWhPb26^C#FWr!NelgD>Ip_p{9!1e@#GdJlV{m?VA>blUh^763e-YKokqtNa_LeUuk1lo)*xps>^^^wn zFXI6?F4`53`XDP<&b-pmpwwn@x+~k$p17^-qv{gP9jiozXCQP8f@$J#6ENntyxz z52iIZUYlHnIu5bfY`F-gOtC8(`E)+P%$=$*N(#AO z+of4ypG=JYL97f&gQkw2I8(587je`oApuUV2)I{L5AoZ;s3377Y=g)DSHluqCqEzq z;I4q1cXem<=HZ{U=_*@ld|3QRRb>8dMUJ^;J}eX_NDISMR;Me`BV+OW4AW}QtrqOy z)!8b~0Dq$qiMG&~h{gt39FPvw%pUq@FO!k(+~=iX+3r@H^Rjq%IeA2P4eQ z?8^P-4p2(>IAxJvawA+>wB%BZ!ivTN-FMqN`@U4cSy!9!h3(pLTD)L%B?9> zHmcQ{`#H6UIKb8k8r2)p%E#r}HN5BAsr^Jnq@!uB4&J_91l9$5i*$}`bc?qHb{ zjDZBYp~*=YL$cl5qa=LY@o|om=ifwP0Akuw=YRf_E>9Jb@` z6&Y0JJ+r-g8XA4zpBm}u*+`^-xd9`~AcTQ{kQ4ZnJo59KhpQ0K2fU06-&*-9uk#0b zi!)F%0$VDm=3;(YiaiYCcgSldA>E0gQug!nyNg<7e$`&F|trH!mW1Q23M z#bc1LRd@I$Gw`VS3pjz#RLJCLcU}Gb{sA1Mx^}C<%@&6tCOa9t#(5WEGG(U9He$&B zMh$!4=Dsgc?Z`wKyTV3eM1{Zro!C%_c>b$b7O;S;wq^rB7^XbM!$q7-%FctW3uc2^ zqlaKnnMjAsz`f7)n?Rs5#P0ONA_lEa5J{@6!}JUWNkK7-I(He?x`TK!7*T+W18t38 zn`r2aLaE{B;{!aKuZ^=h!suYU)1Rwk^Cb|INs!IW)=9Jl{Dapz^1siVug3?Gs_WOU z0}!^|G0DRf<>Y)=^MDsshz+T*2cd5@!YYEX<6`yh?IwKYhL;Q!iSE9>gn`_klAjRZ zhHSgi^za!QE+e4bf5D{A^bfuG=kN%m1ru;B;JS)4^+B0>+;?e$C<749A`PewNA7Is z7mz~T(}p<$&=i-z@Q?wZr^>Yjqe83hZ@|jWlpEN}bYO}-ouHOG;{stw$Jfbu4liZ= zEUtsM>mIcDASsaBr&$(8u0jOC#Q-g!1Z7Rsfx9+z2^Mg@!Ab~i6w31Cd_Fk#>7;5ZGLO~^`^(APS~Ud8B3?EQ&L*WB4&331|x`b9-v1i_kD+= z9JJ(({oqUy=?@;^BM9ye`!Aj_s&W|NDW8bAC|kHmNg}Z6(+uM1mBiZ-P@3-o!Zp$i zQHXd9Gs`fXKUDjdQlzA^ax+5s?K?NeN&~#*mG&<=qjw@*MX;%&wjVVv&xqe07g(Nx zi9MLKaGtCP$XhY4wwv)gT#N2J5ixU=(3>-HSTj)Y%9VR9JG_p8i|GNDwaqG4aK^;#Sht0763Q61C)f%zF zDI`@HN3_>E@?ytPg*Df!6*GS8N{E%@P7xCv4}FrKQX}$nBDEPMelfQ8Va4Lj^ zK80Tt`Y*>0VKsoXx^GUo6e+v@oCIYWraOH8`~-gb>E83-hq4*vd3hb{yAfIT)l*f~ z)$9zA^MZb*sHn)r5Rm4O+}}m~iT)HcUk}R`@=!1!1DnVzx9R=*wd^6-hv1?n+A@ZK zwFz88*W*0Cptkl8DA!py5De{XZ8PQM0)Xy-Z)_nJr>M?u*Y|bMx~bJ`syxQBB?$E6pXJmm?5s5o9ZQD5U)PQ)yN2_GJ0-uKQ1E85p z-Y;mXVT=pv;;fA*1eYU(-q?3Sj98QXoC4b1Z+{U~zfNGn@*iNZme}AXiDTp(K@j&< z$qvYT0-MTP=KM+y41dP~Xh{pOWc7HJ@?WGKV zKaix)xzxkZ{=LZx66?=?eGCXoNFb>v3C&bmUvqF+fdUU47yzd{li$G#Z-^!FxfC$Z zt4tF(s`OfNJ)+U@V@+1~fX z&cjS9=xK24#wI3U^bLL#XdYQW_2!9N3Fj}vK_di`3wPt9$Ir?7CO@uME3_<9;?QW| z2Rdb2j!F8`ZJ!nHpuwA3S78o#A0kdaU;=3{3s)uZ2*5D_@n4PWkg_B`@B^6%D3nu( zr#(i9+o*4{-Zi_=j*L#7L7;Kw-$onV<>^zum*tN4pZD24f(*ddHbC_6-@gZJ9G->z zfxZp-t*b%krX$D>$-qP%C`Kt?U>gSwK9~C!cJT~iF7-kGOWDV7axlBI{w+{aO4t1V zCSPF@=;?<+uFIFtc9?_WA!YII$s|k85+v_;K`MucQli8RTy@YitHh$-krx#g_w@GO zst>IV8u^%wKF4qOv zSJ#k7@ILH3JX8SUs^3mif5wBf0!xYxhw0b@h^B|bK>DN8b?cw}nJZC^OX-hPqL}xg z`JY2k*oQ(%12DHyR9qJ8LHxg7J27`zaE5R2jKG)+|IsL{a?3Tro7pfgxqG35kH4#v{%J3E)ECo0{;>Twi1HNJUO;X_(NeD8l#Gq1xRY*W4cWhH5p(_aL7weC zOtE=&EZ46;1r7OX8dSpP=dYUNj|5D?wuEc}JYeL>b>;dQ z5?k!k130i8R4fRHOj}i|J{^HhLoD);Rvg&gAgu?9^0DkJ$S)D-PcUl-;7Zh%>NADR zfL4kG%p%sn22SH?PZGizMV~Fw<1>x&s1`_xi`#~h4((tIU~3wnko*k4kFLxgTzfu# z{OR$?$45%0;J-m|unu8AXL^l}5gsMGSb=#AgYa^4EoEgw7^=nZ-|;^98ZSqVd4=Iazx_?R*8$H zlUdBknFPLaCTG5pQpA>^yYrn(9oefS?43&>aH(tV$yA7!ZgcSNop!CH{MG$_85(wCc? zTlr?(PNW0Xws-XJ(%o@*^1;7FVSjiONkT`Sh147OX8U9hsWhf%dBh=5Js2DrvWM8B zWgI^9NwG0Fuf>*1jJ9t)af8d?O0WALKZ5%XW2%qANrhs!k$ktz8w9knw+D_<^YAbN zXj^9`_pB%aNj^@zsy{=TgZlw6+8aRgSwWKpcPR*ZArwSX`gA=|9Y*k=247hnOy>6h z&HT7u=itFNrt`LRj>#qb;ope3bbXdC4FjSCC~hr(7lpw*gNIH4a5#XvH30PrX8vJd zBxB$jJeex>n!Qx{#5v(&(0o<08=y1HLIsO-g<)Yx6^Pmovb_iK++cvr zye|m>`Z=g^pov2y1;WLF3W2TYB;!Q_TO{@(X^4Sv)5d$~rwEx6sJ?QLQG^qKd^}Ny zko&j!9Q0XGAKu&&Dxc_aP3^XcHP3~ivN6Y&Sz(Q9cb{9n>W8NM2dquGqu)0b(C@hR zG%^PAbqlRRT^U1wR7YnDnrU=XV5Od~JCFOliLg*`Q37sb=}M)52DC`D#er@$?SD@J zPK7wDXrh9$f9ZMlETA2~_S1$a7OCH0JtpPFemH+tAYi^$=FNiShaoPn+KE!r-FIYk zpW!@-6sFTvB4rJfUqubNVW4IgJMKaE1>MnJ^ySyus7vQAYsfxN(tmYrK=$ybBHh)6 z9iI%ZZ%;u#g@;ug61lNB{%5~n<8kFNc}#e=v$)3kY>ON-E&P296S#Z=0>p<+fy1=W z9hb}beQ9ZW?GLcc19;w26FexZwc)OV$E^~=?-gi;Z+FH`iP>dhSoS8_|7+peqoGd2 zaJss*NV6KZI!+~aXG1$KtC8(ulVKQYBFoNX<_4W>#(dZ zr0}S!yS6NV+#Fe+ksF*`cjU_`G5Wyuc(;3Sr&dVJ9n$l$a%uvwZ4$oNY<=FDBQ;gX zJmOXd{)vxE!^)qy`CPB|{?OWHiy-w2El&Zw$r=X$6Fs|#VWxQ{C2^CXrm%icO<2>$ zN5uuvVHzml?1p)<$lulw5+J(Uwf5@I)1{s0#cAp3HlU$#R8Tk+X;zNPdV#iJIkt8| z#m@rgy~{IiDt;8#?Wzg&>?$P&YOH-hmD`8*J%C9O(Pl?BBed^u_ZSKm z__)W3AtTYUxy9XM82A}W8xt@V2;4VkCrX5cW?r`!Ylvnv_KRi-+%2f7J9BV5VVg#4 zj!+AQH4#=eVB6g@_{Jr}&WfVGr>CMz5f;zKX-=*a2g;TnAA}1>EM8O8u@+g_1Rfb* zZhL|D5{f?8LjAZTg9PO!aR0Q-!Bzs+ZRhy&GEB}>m>C-;D@vNo=#&p8bXUv^Y)bzK z>>W!S+2Fk#U0cfW?gDotp4a;1>4iq51uWWtjZ+mBhT_0eMr%2~zA2<4ubOV~oeMG5 z`aE#fowR@76`+DAbFm>+NIU^GQLPtw2nu^h53ViNr>eEdz2pQ8OhTSXu zzREW*tG2I1V}`jP42~<9z1IwO2P5uR@#;ptGn456b2^SeE&txAxEb|U3{C6S7}ggE z8dNu!u3Q<=dU^e&xR1z7nmtdQxc`aIVzDskJPXze3AqSuv7ZPLSbzjxSJPgj6REe} z3E}BGrb+1Xdn>0nAtA3|#V2X50Jy;Limo69SRM2f`VC~zr*Soh@u)O~)jYN-1q}(7 zRKen9_AwF25TYY%Y=4Jwy-TvY11sxP&9g22rG|_Hp?Ffkr{(r!}MM+v%_nc&F82cbiO1CW%Ffn_#bCTt6NQbg{Sl&KT| zd0}hS&+M~El0%2_e{pZWyGi@tn+h0?u&OKbIpbzwnsA<5pESjQOlJ6#ybCzJu#G_7 zd5jk=rAP}rxX#Y%IXLM`?HWOO@%iIu)C=ywtlh z35aJK7?)rJ4V0RLlmD4tOM*SISVZ~(@o2c%aWG~u#AP0O=iM-TRA9oUR80>V2y6C{ z#{iNnGj^Ou-31!^wzAv0FB_5_u+3SK=%dtN??HSGM#qn%#WIM4CP@SE-{FV@^yfhH zC2BQbB@DU%kaWJYJ`oqMR1Dz%nnv@+(gxV|4AM)C8g>xdFOVy4S_uIU#Q0~UzV!s` z5xCEfH7jC3&5*kgeT|spFyOqN!aJW@=CIDj<~`A*@QZ+{Ud6hos^>N47KKX{IFIn} zz>Jl6?8wPqVqFV|WO-WQfdAP4k@sjwuY1cBx;Y-vAklu_p?f?I0}k==5w%Uy;aBWM zn^el8%3qZFCxtUWrQ2ojQK7GUaX&ts`UpOaeEZSr*KkTPopYnX!RsZEAUzp@31glm z|Kr6yt8o*_S&TJj#4ec(@4T(JfHPQuxaFJ`Z%5j(I04AO8dD1_*AMDCG{(8i}0xjK*+)buYAHXz?TPa77Rl}3WeUn z`B>qH=f1J0>g}WCtEKRNp|4;!mqMv5@-EKJD0uSd4q5YtsSa^hOZ}9xvNAj?VW3vw zcCgQw!V#~O2VDe;0~f$sTml`wzOd>`3`xP`h(pLPs$2QfS>-eYcrHi?I2%GFSZVaT zqUqe}v3N_r(oi0r^$)tq)m$n)s1>Wbj022nd4-6deS zt^|a(Pw8854@2lxUJSt6`lE8dE_1#kWi$cz59*K^KY_gcmG+Vrcz&f?RBF% zf5i$d$4ri~9@WHX;O5D{@7?|!eq51yt;$b)uZ88PNQC zvC0=7V;!ordmAD>hK>itmf2>tS&jHUUVc@HaXMD0zGk-yR-Vq<;>g-mxPg1*Uz6W3 A@c;k- literal 0 HcmV?d00001 From b0e44f6472c9851cb02d3ade9d43615d91dfd123 Mon Sep 17 00:00:00 2001 From: anon Date: Wed, 12 Aug 2026 18:37:00 +0200 Subject: [PATCH 8/8] refactor(show): make crop_coord internals more maintainable Behavior-preserving cleanup of the crop_coord feature, plus one correctness fix in the datashader window path. - BBox NamedTuple (render_params): one (x0, y0, x1, y1) ordering travels through every crop helper instead of three names/orders (crop_coord at the API, crop_box in show(), crop downstream); show() converts the public (xmin, xmax, ymin, ymax) once at the boundary. Removes the per-helper order-restating comments. - Thread crop via FigParams.crop instead of a kwarg on _render_panel and all four render fns; drops the kwargs['crop'] special-case. - Dedup the axis-limit block (compute limits, set once). - Extract _pin_norm_to_full_range (shared by _render_points/_render_shapes) and _crop_color_is_stable (labels windowing predicate). - Harden _datashader_window_image: base and the datashader aggregate now cover the same integer pixel window (mapped back to world via the forward affine), fixing a sub-pixel misalignment and an edge-clamp case where the fractional canvas range overran the sliced source; materialize base before overwriting; drop the dead 2D branch (images always carry a c dim). Tests: BBox is a tuple subclass so existing helper tests are unchanged; add datashader window placement/clamp/empty-window tests. Full non-visual pl suite: 550 passed. --- src/spatialdata_plot/pl/basic.py | 35 +++++----- src/spatialdata_plot/pl/render.py | 77 ++++++++++++---------- src/spatialdata_plot/pl/render_params.py | 17 ++++- src/spatialdata_plot/pl/utils.py | 84 +++++++++++++----------- tests/pl/test_show.py | 3 +- tests/pl/test_utils.py | 49 ++++++++++++++ 6 files changed, 173 insertions(+), 92 deletions(-) diff --git a/src/spatialdata_plot/pl/basic.py b/src/spatialdata_plot/pl/basic.py index 7977cddf..8701d88e 100644 --- a/src/spatialdata_plot/pl/basic.py +++ b/src/spatialdata_plot/pl/basic.py @@ -56,6 +56,7 @@ _split_colorbar_params, ) from spatialdata_plot.pl.render_params import ( + BBox, CBAR_DEFAULT_FRACTION, CBAR_DEFAULT_LOCATION, CBAR_DEFAULT_PAD, @@ -1511,17 +1512,17 @@ def show( ) # `crop_coord` is one box in one coordinate system's units; applying the same numbers across - # coordinate systems with different scales/units would be incoherent. - crop_box: tuple[float, float, float, float] | None = None + # coordinate systems with different scales/units would be incoherent. Convert the public + # (xmin, xmax, ymin, ymax) order into the internal BBox once, here at the boundary. + crop_box: BBox | None = None if crop_coord is not None: if len(coordinate_systems) > 1: raise ValueError( f"`crop_coord` requires a single coordinate system, but {len(coordinate_systems)} would be " f"rendered ({coordinate_systems}). Pass `coordinate_systems=` with exactly one entry." ) - # show()'s `crop_coord` is (xmin, xmax, ymin, ymax); the subset helpers expect (x0, y0, x1, y1). xmin, xmax, ymin, ymax = crop_coord - crop_box = (xmin, ymin, xmax, ymax) + crop_box = BBox(xmin, ymin, xmax, ymax) panels = _plan_panels( coordinate_systems=coordinate_systems, @@ -1555,6 +1556,7 @@ def show( scalebar_units=scalebar_units, scalebar_kwargs=scalebar_params, ) + fig_params.crop = crop_box legend_params_obj = _build_legend_params( legend_params=legend_params, legend_fontsize=legend_fontsize, @@ -1596,7 +1598,6 @@ def show( title=title, dpi=dpi, figsize=figsize, - crop=crop_box, ) if has_shapes and wants["shapes"]: @@ -1611,12 +1612,11 @@ def show( "all geometries are empty. Drop the element or restore at least one non-empty geometry." ) - if crop_coord is not None: - # `crop_coord` pins the view to the exact box: set limits directly (bypassing the - # expand-don't-overwrite merge, which would expand back out to any pre-existing - # axes limits) and ignore `pad_extent`. crop_coord is (xmin, xmax, ymin, ymax). - ax.set_xlim(crop_coord[0], crop_coord[1]) - ax.set_ylim(crop_coord[3], crop_coord[2]) # (0, 0) is top-left + if crop_box is not None: + # `crop_coord` pins the view to the exact box: bypass the expand-don't-overwrite merge + # (which would expand back out to any pre-existing axes limits) and ignore `pad_extent`. + x_min, x_max, y_min, y_max = crop_box.x0, crop_box.x1, crop_box.y0, crop_box.y1 + set_limits = True else: # fast path for axis-aligned transforms; identical result, falls back to get_extent otherwise extent = _get_extent_fast( @@ -1630,15 +1630,17 @@ def show( ) cs_x_min, cs_x_max = extent["x"] cs_y_min, cs_y_max = extent["y"] - - if any([has_images, has_labels, has_points, has_shapes]): + set_limits = any([has_images, has_labels, has_points, has_shapes]) + if set_limits: # If the axis already has limits, only expand them but not overwrite x_min = min(ax_x_min, cs_x_min) - pad_extent x_max = max(ax_x_max, cs_x_max) + pad_extent y_min = min(ax_y_min, cs_y_min) - pad_extent y_max = max(ax_y_max, cs_y_max) + pad_extent - ax.set_xlim(x_min, x_max) - ax.set_ylim(y_max, y_min) # (0, 0) is top-left + + if set_limits: + ax.set_xlim(x_min, x_max) + ax.set_ylim(y_max, y_min) # (0, 0) is top-left if legend_params_obj.colorbar and axis_colorbar_requests: pending_colorbars.append((ax, axis_colorbar_requests)) @@ -2095,7 +2097,6 @@ def _render_panel( title: list[str] | None, dpi: int | None, figsize: tuple[float, float] | None, - crop: tuple[float, float, float, float] | None = None, ) -> tuple[list[str], dict[str, bool]]: """Render every applicable render command into a single panel's axes. @@ -2153,8 +2154,6 @@ def _render_panel( } if cmd == "render_images": kwargs["channel_legend_entries"] = axis_channel_legend_entries - if cmd in {"render_points", "render_shapes", "render_images", "render_labels"}: - kwargs["crop"] = crop if cmd in {"render_images", "render_labels"}: kwargs["rasterize"] = _should_rasterize( cast("ImageRenderParams | LabelsRenderParams", element_params), dpi, figsize diff --git a/src/spatialdata_plot/pl/render.py b/src/spatialdata_plot/pl/render.py index 7aadc406..b2aa0a51 100644 --- a/src/spatialdata_plot/pl/render.py +++ b/src/spatialdata_plot/pl/render.py @@ -128,6 +128,35 @@ def _full_element_norm_range( return (float(resolved.vmin), float(resolved.vmax)) +def _pin_norm_to_full_range( + norm: Normalize, + full_color_spec: ColorSpec | None, + cmap_params: CmapParams, + transfunc: Callable[..., Any] | None, +) -> None: + """Pin ``norm`` in place to the full (pre-crop) continuous range so a cropped matplotlib zoom keeps + the uncropped plot's colours. No-op when uncropped (``full_color_spec is None``) or categorical. + """ + if full_color_spec is None: + return + full_range = _full_element_norm_range(full_color_spec, cmap_params, transfunc) + if full_range is not None: + norm.vmin, norm.vmax = full_range + + +def _crop_color_is_stable(color_col: pd.Series | None, palette: Any) -> bool: + """Whether windowing a labels raster keeps colours stable (else the caller full-renders + clips). + + Windowing drops off-window instances before colours resolve. That is colour-stable for numeric + (continuous) columns, pandas-Categorical columns (fixed levels), and explicit palettes; a plain-string + column with the default palette would reshuffle colours as whole categories drop out of the window + (their sorted positions shift), so windowing is unsafe there. + """ + if palette is not None or color_col is None: + return True + return pd.api.types.is_numeric_dtype(color_col) or isinstance(color_col.dtype, pd.CategoricalDtype) + + def _get_top_data_array(element: xr.DataArray | DataTree) -> xr.DataArray: if isinstance(element, DataTree): return next(iter(next(iter(element.values())).data_vars.values())) @@ -624,7 +653,6 @@ def _render_shapes( fig_params: FigParams, legend_params: LegendParams, colorbar_requests: list[ColorbarSpec] | None = None, - crop: tuple[float, float, float, float] | None = None, ) -> None: _log_context.set("render_shapes") element = render_params.element @@ -728,8 +756,8 @@ def _render_shapes( # matplotlib backend can pin the uncropped norm; the range itself is resolved lazily below (only on # the matplotlib path — datashader autoscales over the window, so it must not pay the full scan). full_color_spec: ColorSpec | None = None - if crop is not None: - elem_bbox = _bbox_to_element_space(sdata_filt.shapes[element], coordinate_system, crop) + if fig_params.crop is not None: + elem_bbox = _bbox_to_element_space(sdata_filt.shapes[element], coordinate_system, fig_params.crop) if elem_bbox is not None: # None = rotation/shear; render full and let axis limits clip full_color_spec = color_spec # capture before filtering (filter returns a new object) keep_crop = _bbox_mask_shapes(shapes, elem_bbox) @@ -961,10 +989,7 @@ def _draw_centroids(xy: np.ndarray, radius: float | None = None) -> None: # Under crop, pin the norm to the full-element range so the zoom matches the uncropped plot # (datashader, handled above, autoscales over the window instead). Resolved here (not in the crop # block) so the datashader path never pays the full-element scan. - if full_color_spec is not None: - crop_norm_range = _full_element_norm_range(full_color_spec, render_params.cmap_params, render_params.transfunc) - if crop_norm_range is not None: - norm.vmin, norm.vmax = crop_norm_range + _pin_norm_to_full_range(norm, full_color_spec, render_params.cmap_params, render_params.transfunc) # Build the paths once and share them across the fill and outline collections (geometry is # identical; only colours/alpha/linewidth differ), then apply the coordinate-system affine # once to the shared Path objects rather than once per collection. @@ -1361,7 +1386,6 @@ def _render_points( fig_params: FigParams, legend_params: LegendParams, colorbar_requests: list[ColorbarSpec] | None = None, - crop: tuple[float, float, float, float] | None = None, ) -> None: _log_context.set("render_points") element = render_params.element @@ -1504,8 +1528,8 @@ def _render_points( # matplotlib backend can pin the uncropped norm; the range itself is resolved lazily below (only on # the matplotlib path — datashader autoscales over the window, so it must not pay the full scan). full_color_spec: ColorSpec | None = None - if crop is not None: - elem_bbox = _bbox_to_element_space(sdata.points[element], coordinate_system, crop) + if fig_params.crop is not None: + elem_bbox = _bbox_to_element_space(sdata.points[element], coordinate_system, fig_params.crop) if elem_bbox is not None: # None = rotation/shear; render full and let axis limits clip keep_crop = _bbox_mask_points(points["x"].to_numpy(), points["y"].to_numpy(), elem_bbox) if not keep_crop.any(): @@ -1577,11 +1601,7 @@ def _render_points( # Under crop, pin to the full-element range so the zoom matches the uncropped plot. if color_spec.is_continuous: norm = _resolve_continuous_norm(color_spec.color_vector, render_params.cmap_params) - if full_color_spec is not None: - # pin to the full-element range so the cropped zoom matches the uncropped plot - crop_norm_range = _full_element_norm_range(full_color_spec, render_params.cmap_params, render_params.transfunc) - if crop_norm_range is not None: - norm.vmin, norm.vmax = crop_norm_range + _pin_norm_to_full_range(norm, full_color_spec, render_params.cmap_params, render_params.transfunc) else: norm = render_params.cmap_params.fresh_norm() # update axis limits if plot was empty before (necessary if datashader comes after) @@ -1805,7 +1825,6 @@ def _render_images( rasterize: bool, colorbar_requests: list[ColorbarSpec] | None = None, channel_legend_entries: list[ChannelLegendEntry] | None = None, - crop: tuple[float, float, float, float] | None = None, ) -> None: _log_context.set("render_images") sdata_filt = sdata.filter_by_coordinate_system( @@ -1827,7 +1846,7 @@ def _render_images( width=fig_params.fig.get_size_inches()[0], height=fig_params.fig.get_size_inches()[1], scale=scale, - crop=crop, + crop=fig_params.crop, extent=extent, ) # rasterize spatial image if necessary to speed up performance @@ -1847,7 +1866,7 @@ def _render_images( coordinate_system=coordinate_system, extent=extent, downsample_method=downsample_method, - crop=crop, + crop=fig_params.crop, ) elif rasterize: img = _rasterize_if_necessary( @@ -1857,7 +1876,7 @@ def _render_images( height=fig_params.fig.get_size_inches()[1], coordinate_system=coordinate_system, extent=extent, - crop=crop, + crop=fig_params.crop, ) channels = img.coords["c"].values.tolist() if render_params.channel is None else render_params.channel @@ -2227,7 +2246,6 @@ def _render_labels( legend_params: LegendParams, rasterize: bool, colorbar_requests: list[ColorbarSpec] | None = None, - crop: tuple[float, float, float, float] | None = None, ) -> None: _log_context.set("render_labels") element = render_params.element @@ -2258,19 +2276,12 @@ def _render_labels( _guard_2d_only(label, element, "labels") extent = get_extent(label, coordinate_system=coordinate_system) - # Windowing the label raster under `crop` drops off-window instances before colours are resolved. - # That is colour-stable for numeric (continuous) columns, pandas-Categorical columns (fixed levels), - # and when an explicit palette is given; but a plain-string column with the default palette would - # reshuffle colours as whole categories drop out of the window (their sorted positions shift). Fall - # back to full render + axis-clip for that case so cropped colours always match the uncropped plot. - crop_labels = crop - if crop is not None and col_for_color is not None and palette is None and table_name is not None: - _color_col = sdata[table_name].obs.get(col_for_color) - if ( - _color_col is not None - and not pd.api.types.is_numeric_dtype(_color_col) - and not isinstance(_color_col.dtype, pd.CategoricalDtype) - ): + # Only window the label raster when doing so keeps colours stable; otherwise fall back to full + # render + axis-clip so cropped colours always match the uncropped plot (see _crop_color_is_stable). + crop_labels = fig_params.crop + if crop_labels is not None: + color_col = sdata[table_name].obs.get(col_for_color) if col_for_color and table_name else None + if not _crop_color_is_stable(color_col, palette): crop_labels = None # get best scale out of multiscale label diff --git a/src/spatialdata_plot/pl/render_params.py b/src/spatialdata_plot/pl/render_params.py index f2fa8716..ec09b240 100644 --- a/src/spatialdata_plot/pl/render_params.py +++ b/src/spatialdata_plot/pl/render_params.py @@ -3,7 +3,7 @@ from collections.abc import Callable, Mapping, Sequence from copy import copy from dataclasses import dataclass, field -from typing import Any, Literal +from typing import Any, Literal, NamedTuple import numpy as np from matplotlib.axes import Axes @@ -16,6 +16,20 @@ _DsReduction = Literal["sum", "mean", "any", "count", "std", "var", "max", "min"] _ImageDsReduction = Literal["max", "min", "mean", "mode", "first", "last", "var", "std"] + +class BBox(NamedTuple): + """Axis-aligned bounding box in one coordinate space, corners sorted so ``x0 <= x1`` and ``y0 <= y1``. + + On-the-fly cropping uses a single ``(x0, y0, x1, y1)`` ordering everywhere internally, so no crop + helper has to restate which order it received. ``show()`` converts the public + ``crop_coord=(xmin, xmax, ymin, ymax)`` into this once at the boundary. + """ + + x0: float + y0: float + x1: float + y1: float + # Canonical definition for the package; imported by basic.py and utils.py. # replace with # from spatialdata._types import ColorLike @@ -195,6 +209,7 @@ class FigParams: title: str | Sequence[str] | None = None ax_labels: Sequence[str] | None = None frameon: bool | None = None + crop: BBox | None = None @dataclass diff --git a/src/spatialdata_plot/pl/utils.py b/src/spatialdata_plot/pl/utils.py index 62d4d6d2..dc534295 100644 --- a/src/spatialdata_plot/pl/utils.py +++ b/src/spatialdata_plot/pl/utils.py @@ -57,6 +57,7 @@ from spatialdata_plot._logging import logger from spatialdata_plot.pl._scanpy_compat import _add_categorical_legend, default_102 from spatialdata_plot.pl.render_params import ( + BBox, Color, ColorbarSpec, FigParams, @@ -807,12 +808,12 @@ def _get_valid_cs( def _rasterize_to_bbox( image: DataArray, - bbox: tuple[float, float, float, float], + bbox: BBox, coordinate_system: str, target_x_dims: float, target_y_dims: float, ) -> DataArray: - """Rasterize ``image`` to the world bbox ``(x0, y0, x1, y1)`` at ~``target_*_dims`` figure pixels. + """Rasterize ``image`` to the world ``bbox`` at ~``target_*_dims`` figure pixels. ``rasterize`` interprets ``target_unit_to_pixels`` in world units (not intrinsic pixels), so dividing the target pixel count by the world span keeps placement correct for any transformation @@ -830,7 +831,7 @@ def _rasterize_if_necessary( height: float, coordinate_system: str, extent: dict[str, tuple[float, float]], - crop: tuple[float, float, float, float] | None = None, + crop: BBox | None = None, ) -> DataArray: """Ensure fast rendering by adapting the resolution if necessary. @@ -870,13 +871,12 @@ def _rasterize_if_necessary( if crop is not None: # Restrict rasterization to the crop window: only its source pixels are read (cost bounded by - # the window, not the full image), and the zoom keeps full figure resolution. ``crop`` is - # (x0, y0, x1, y1) in coordinate-system units. + # the window, not the full image), and the zoom keeps full figure resolution. bbox = crop elif y_dims > target_y_dims + 100 or x_dims > target_x_dims + 100: # Rasterize when the source is substantially larger than the figure DPI × size requires; the # +100 margin avoids rasterizing when the image is only slightly larger than the target. - bbox = (extent["x"][0], extent["y"][0], extent["x"][1], extent["y"][1]) + bbox = BBox(extent["x"][0], extent["y"][0], extent["x"][1], extent["y"][1]) else: return image @@ -891,7 +891,7 @@ def _rasterize_if_necessary( def _datashader_window_image( image: DataArray, - crop: tuple[float, float, float, float], + crop: BBox, coordinate_system: str, target_x_dims: int, target_y_dims: int, @@ -899,36 +899,44 @@ def _datashader_window_image( ) -> DataArray | None: """Datashader-aggregate only the crop window of an image; ``None`` to fall back to the full path. - ``rasterize`` produces the target grid with correct world coords/transform for the ``crop`` box; - the source is sliced to the window in element-pixel space and aggregated with the datashader - reduction in that pixel space, then index-assigned onto the grid. The full image is never read. - Returns ``None`` for rotation/shear (box does not map to a box) or an empty window. + ``base`` and the aggregate are made to cover the *same* integer pixel window (the fractional crop + box, clamped to the image), so the aggregated grid is index-assigned onto ``base`` without a + sub-pixel shift: ``base`` is rasterized over that window mapped back to world (correct coords / + transform) and datashader aggregates the sliced source over its own pixel extent. The full image is + never read. Returns ``None`` for rotation/shear (box does not map to a box) or an empty window. + Images always carry a ``c`` dim (``Image2DModel``) and this path is images-only, so no 2D branch. """ - has_c_dim = len(image.shape) == 3 - y_dims, x_dims = (image.shape[1], image.shape[2]) if has_c_dim else image.shape - elem_bbox = _bbox_to_element_space(image, coordinate_system, crop) - if elem_bbox is None: + y_dims, x_dims = image.shape[1], image.shape[2] + elem = _bbox_to_element_space(image, coordinate_system, crop) + if elem is None: return None - px0, py0, px1, py1 = (int(round(v)) for v in elem_bbox) - px0, py0 = max(px0, 0), max(py0, 0) - px1, py1 = min(px1, x_dims), min(py1, y_dims) + # Integer pixel window: floor/ceil brackets the fractional element box, clamped to the image bounds. + px0, py0 = max(int(np.floor(elem.x0)), 0), max(int(np.floor(elem.y0)), 0) + px1, py1 = min(int(np.ceil(elem.x1)), x_dims), min(int(np.ceil(elem.y1)), y_dims) if px1 <= px0 or py1 <= py0: return None - base = _rasterize_to_bbox(image, crop, coordinate_system, target_x_dims, target_y_dims) - out_y, out_x = (base.shape[1], base.shape[2]) if has_c_dim else base.shape + # World box of that integer window (forward affine on its corners), so ``base`` covers exactly the + # region the aggregate does — not the fractional crop box, which would shift and (when clamped at an + # edge) overrun the sliced source. + matrix = get_transformation(image, get_all=True)[coordinate_system].to_affine_matrix(("x", "y"), ("x", "y")) + corners = np.array([[px0, py0], [px1, py0], [px0, py1], [px1, py1]], dtype=float) + world = corners @ matrix[:2, :2].T + matrix[:2, 2] + world_box = BBox(world[:, 0].min(), world[:, 1].min(), world[:, 0].max(), world[:, 1].max()) + + base = _rasterize_to_bbox(image, world_box, coordinate_system, target_x_dims, target_y_dims) + if hasattr(base.data, "compute"): + base = base.copy(data=base.data.compute()) # materialize before we overwrite .values + out_y, out_x = base.shape[1], base.shape[2] src = image.isel(x=slice(px0, px1), y=slice(py0, py1)) src = src.compute() if hasattr(src.data, "compute") else src - # Canvas is in the sliced source's own (pixel) coordinate space; the aggregated grid is - # index-assigned onto base, which already carries the correct world coords/transform. + # Canvas spans the sliced source's own pixel extent, so datashader places every source pixel; the + # aggregated grid then lines up with ``base`` (same window, same resolution). cvs = ds.Canvas(plot_width=out_x, plot_height=out_y, x_range=(px0, px1), y_range=(py0, py1)) - if has_c_dim: - agg = np.stack( - [np.asarray(cvs.raster(src.isel(c=i), downsample_method=downsample_method).values) for i in range(src.sizes["c"])], - axis=0, - ) - else: - agg = np.asarray(cvs.raster(src, downsample_method=downsample_method).values) + agg = np.stack( + [np.asarray(cvs.raster(src.isel(c=i), downsample_method=downsample_method).values) for i in range(src.sizes["c"])], + axis=0, + ) base.values = agg.astype(base.dtype, copy=False) return base @@ -941,7 +949,7 @@ def _rasterize_if_necessary_datashader( coordinate_system: str, extent: dict[str, tuple[float, float]], downsample_method: str, - crop: tuple[float, float, float, float] | None = None, + crop: BBox | None = None, ) -> DataArray: """Downsample to canvas resolution with a configurable datashader reduction. @@ -1007,7 +1015,7 @@ def _multiscale_to_spatial_image( height: float, scale: str | None = None, is_label: bool = False, - crop: tuple[float, float, float, float] | None = None, + crop: BBox | None = None, extent: dict[str, tuple[float, float]] | None = None, ) -> DataArray: """Extract the DataArray to be rendered from a multiscale image. @@ -1064,7 +1072,7 @@ def _multiscale_to_spatial_image( # portion reaches the target — scale the target up by full/window per axis. full_x = float(extent["x"][1]) - float(extent["x"][0]) full_y = float(extent["y"][1]) - float(extent["y"][0]) - win_x, win_y = crop[2] - crop[0], crop[3] - crop[1] + win_x, win_y = crop.x1 - crop.x0, crop.y1 - crop.y0 if win_x > 0 and win_y > 0: optimal_x *= full_x / win_x optimal_y *= full_y / win_y @@ -1548,10 +1556,8 @@ def _element_extent_fast( # so a sliced image is drawn in the wrong place; they rely on axis-limit clipping instead. -def _bbox_to_element_space( - element: Any, coordinate_system: str, bbox: tuple[float, float, float, float] -) -> tuple[float, float, float, float] | None: - """Map a coordinate-system bbox ``(x0, y0, x1, y1)`` to element-native coords. +def _bbox_to_element_space(element: Any, coordinate_system: str, bbox: BBox) -> BBox | None: + """Map a coordinate-system ``bbox`` to element-native coords. Inverts the axis-aligned affine on the box corners and re-sorts so the result has ``x0 <= x1`` and ``y0 <= y1`` even when the transform flips an axis (a negative scale would otherwise yield a @@ -1565,17 +1571,17 @@ def _bbox_to_element_space( x0, y0, x1, y1 = bbox corners = np.array([[x0, y0], [x1, y0], [x0, y1], [x1, y1]], dtype=float) elem = (corners - matrix[:2, 2]) @ np.linalg.inv(affine).T - return (float(elem[:, 0].min()), float(elem[:, 1].min()), float(elem[:, 0].max()), float(elem[:, 1].max())) + return BBox(float(elem[:, 0].min()), float(elem[:, 1].min()), float(elem[:, 0].max()), float(elem[:, 1].max())) -def _bbox_mask_points(x: ArrayLike, y: ArrayLike, elem_bbox: tuple[float, float, float, float]) -> ArrayLike: +def _bbox_mask_points(x: ArrayLike, y: ArrayLike, elem_bbox: BBox) -> ArrayLike: """Boolean keep-mask for points whose element-native ``(x, y)`` fall inside ``elem_bbox``.""" x0, y0, x1, y1 = elem_bbox x, y = np.asarray(x), np.asarray(y) return (x >= x0) & (x <= x1) & (y >= y0) & (y <= y1) -def _bbox_mask_shapes(shapes: GeoDataFrame, elem_bbox: tuple[float, float, float, float]) -> ArrayLike: +def _bbox_mask_shapes(shapes: GeoDataFrame, elem_bbox: BBox) -> ArrayLike: """Boolean keep-mask for shapes whose bounds intersect ``elem_bbox`` (element-native coords). Bbox-intersect, not clip: a boundary-crossing shape is kept whole (axis-limit clipping trims it diff --git a/tests/pl/test_show.py b/tests/pl/test_show.py index 4accd95a..4ed87c6c 100644 --- a/tests/pl/test_show.py +++ b/tests/pl/test_show.py @@ -266,6 +266,7 @@ def test_crop_multiscale_selects_finer_level(): """A crop must pick a pyramid level fine enough for the WINDOW, not the whole image (Visium HD).""" from spatialdata.models import Image2DModel + from spatialdata_plot.pl.render_params import BBox from spatialdata_plot.pl.utils import _multiscale_to_spatial_image n = 800 @@ -274,7 +275,7 @@ def test_crop_multiscale_selects_finer_level(): extent = {"x": (0.0, float(n)), "y": (0.0, float(n))} coarse = _multiscale_to_spatial_image(tree, dpi=10, width=5, height=5) # target ~50px over the full image fine = _multiscale_to_spatial_image( - tree, dpi=10, width=5, height=5, crop=(0.0, 0.0, 80.0, 80.0), extent=extent # 10% window -> 10x boost + tree, dpi=10, width=5, height=5, crop=BBox(0.0, 0.0, 80.0, 80.0), extent=extent # 10% window -> 10x boost ) assert fine.shape[-1] > coarse.shape[-1] diff --git a/tests/pl/test_utils.py b/tests/pl/test_utils.py index 7b877672..7eeb4bb4 100644 --- a/tests/pl/test_utils.py +++ b/tests/pl/test_utils.py @@ -1433,3 +1433,52 @@ def test_bbox_mask_shapes_polygon_intersect_and_empty(): gdf = ShapesModel.parse(gpd.GeoDataFrame({"geometry": polys}), transformations={"g": Identity()}) np.testing.assert_array_equal(_bbox_mask_shapes(gdf, (1.0, 1.0, 5.0, 5.0)), [True, False]) np.testing.assert_array_equal(_bbox_mask_shapes(gdf, (200.0, 200.0, 210.0, 210.0)), [False, False]) + + +# --- datashader image windowing (crop) ------------------------------------------------------------ + + +def _bright_block_image(n=200): + """A single-channel n×n image (Identity transform) with a bright block at y∈[120,140), x∈[40,60).""" + from spatialdata.models import Image2DModel + + arr = np.zeros((1, n, n), dtype=np.float32) + arr[0, 120:140, 40:60] = 1.0 + return Image2DModel.parse(arr, dims=("c", "y", "x"), transformations={"g": Identity()}) + + +def test_datashader_window_image_places_block_at_correct_relative_position(): + """The windowed aggregate must land the bright block where the crop box puts it (alignment fix).""" + from spatialdata_plot.pl.render_params import BBox + from spatialdata_plot.pl.utils import _datashader_window_image + + img = _bright_block_image() + # window x[20,80] y[100,160]; block centre world (x=50, y=130) -> rel (0.5, 0.5) -> output centre + out = _datashader_window_image(img, BBox(20, 100, 80, 160), "g", 60, 60, "max") + assert out is not None + a = np.asarray(out.values[0]) + ys, xs = np.where(a > 0.5) + assert ys.size > 0 + oy, ox = a.shape + assert 0.3 * oy <= ys.mean() <= 0.7 * oy # near vertical centre, not shifted to an edge + assert 0.3 * ox <= xs.mean() <= 0.7 * ox + + +def test_datashader_window_image_clamps_at_image_edge(): + """A window straddling the image edge still returns a raster (source is clamped, not dropped).""" + from spatialdata_plot.pl.render_params import BBox + from spatialdata_plot.pl.utils import _datashader_window_image + + img = _bright_block_image() + out = _datashader_window_image(img, BBox(-50, 100, 50, 160), "g", 60, 60, "max") # left half outside + assert out is not None + assert np.asarray(out.values[0]).max() > 0.5 # the in-bounds part of the block survives + + +def test_datashader_window_image_none_when_fully_outside(): + """A window with no source pixels falls back (returns None) instead of building an empty canvas.""" + from spatialdata_plot.pl.render_params import BBox + from spatialdata_plot.pl.utils import _datashader_window_image + + img = _bright_block_image() + assert _datashader_window_image(img, BBox(500, 500, 600, 600), "g", 60, 60, "max") is None