Skip to content

Instantly share code, notes, and snippets.

@ivirshup
Last active October 9, 2023 10:42
Show Gist options
  • Save ivirshup/3fbe634b648304978ea77469b5d88961 to your computer and use it in GitHub Desktop.
Save ivirshup/3fbe634b648304978ea77469b5d88961 to your computer and use it in GitHub Desktop.
Using sparse dask chunks inside of anndata
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"id": "734d0a4f-79fd-4672-b028-afe1cf3282de",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"'0.10.1'"
]
},
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%load_ext memory_profiler\n",
"\n",
"import anndata as ad, scanpy as sc, numpy as np, dask.array as da, pandas as pd\n",
"import zarr\n",
"from dask import delayed\n",
"from scipy import sparse\n",
"\n",
"ad.__version__"
]
},
{
"cell_type": "markdown",
"id": "2c0b1594",
"metadata": {},
"source": [
"## Download a couple example datasets"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "065c5f51-d95a-4c7f-8941-318b0bdf6d34",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/mnt/workspace/mambaforge/envs/anndata-dev/lib/python3.11/site-packages/anndata/_core/anndata.py:1900: UserWarning: Variable names are not unique. To make them unique, call `.var_names_make_unique`.\n",
" utils.warn_names_duplicates(\"var\")\n",
"/mnt/workspace/mambaforge/envs/anndata-dev/lib/python3.11/site-packages/anndata/_core/anndata.py:1900: UserWarning: Variable names are not unique. To make them unique, call `.var_names_make_unique`.\n",
" utils.warn_names_duplicates(\"var\")\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 213 ms, sys: 40.2 ms, total: 253 ms\n",
"Wall time: 256 ms\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/mnt/workspace/mambaforge/envs/anndata-dev/lib/python3.11/site-packages/anndata/_core/anndata.py:1900: UserWarning: Variable names are not unique. To make them unique, call `.var_names_make_unique`.\n",
" utils.warn_names_duplicates(\"var\")\n",
"/mnt/workspace/mambaforge/envs/anndata-dev/lib/python3.11/site-packages/anndata/_core/anndata.py:1900: UserWarning: Variable names are not unique. To make them unique, call `.var_names_make_unique`.\n",
" utils.warn_names_duplicates(\"var\")\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 171 ms, sys: 47.1 ms, total: 218 ms\n",
"Wall time: 218 ms\n"
]
}
],
"source": [
"import pooch\n",
"\n",
"EXAMPLE_DATA = pooch.create(\n",
" path=pooch.os_cache(\"scverse_tutorials\"),\n",
" base_url=\"doi:10.6084/m9.figshare.22716739.v1/\",\n",
")\n",
"EXAMPLE_DATA.load_registry_from_doi()\n",
"\n",
"samples = {\n",
" \"s1d1\": \"s1d1_filtered_feature_bc_matrix.h5\",\n",
" \"s1d3\": \"s1d3_filtered_feature_bc_matrix.h5\",\n",
"}\n",
"adatas = {}\n",
"\n",
"for sample_id, filename in samples.items():\n",
" path = EXAMPLE_DATA.fetch(filename)\n",
" sample_adata = sc.read_10x_h5(path)\n",
" sample_adata.var_names_make_unique()\n",
" %time sample_adata.write_zarr(f\"{sample_id}.zarr\")"
]
},
{
"cell_type": "markdown",
"id": "fcb4c6f4",
"metadata": {},
"source": [
"## Functions for IO"
]
},
{
"cell_type": "markdown",
"id": "79f766de",
"metadata": {},
"source": [
"Unfortunatley, dask doesn't have the best support for sparse arrays. So we need to do a little leg work to get these things working.\n",
"\n",
"Here we define a helper function and class that lets us create dask arrays with the appropriate \"meta array\" from a `dask.delayed` task."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "a3574cc4-b557-4ef5-9227-6e86d548e837",
"metadata": {},
"outputs": [],
"source": [
"def csr_callable(shape: tuple[int, int], dtype) -> sparse.csr_matrix:\n",
" if len(shape) == 0:\n",
" shape = (0, 0)\n",
" if len(shape) == 1:\n",
" shape = (shape[0], 0)\n",
" elif len(shape) == 2:\n",
" pass\n",
" else:\n",
" raise ValueError(shape)\n",
"\n",
" return sparse.csr_matrix(shape, dtype=dtype)\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "48333808-de8e-4ab7-955c-92948ecb91f4",
"metadata": {},
"outputs": [],
"source": [
"class CSRCallable:\n",
" \"\"\"Dummy class to bypass dask checks\"\"\"\n",
" def __new__(cls, shape, dtype):\n",
" return csr_callable(shape, dtype)"
]
},
{
"cell_type": "markdown",
"id": "94cac178",
"metadata": {},
"source": [
"Here we create dask chunks from a `CSRDataset`:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "79db8e22",
"metadata": {},
"outputs": [],
"source": [
"def make_dask_chunk(\n",
" x: ad.experimental.CSRDataset,\n",
" start: int,\n",
" end: int\n",
") -> da.Array:\n",
" def take_slice(x, idx):\n",
" return x[idx]\n",
"\n",
" return da.from_delayed(\n",
" delayed(take_slice)(x, slice(start, end)),\n",
" dtype=x.dtype,\n",
" shape=(end - start, x.shape[1]),\n",
" meta=CSRCallable,\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "60fe5b0e-f563-45e3-83a8-357a8b78c95c",
"metadata": {},
"outputs": [],
"source": [
"def sparse_dataset_as_dask(x, stride: int):\n",
" n_chunks, rem = divmod(x.shape[0], stride)\n",
"\n",
" chunks = []\n",
" cur_pos = 0\n",
" for i in range(n_chunks):\n",
" chunks.append(make_dask_chunk(x, cur_pos, cur_pos + stride))\n",
" cur_pos += stride\n",
" if rem:\n",
" chunks.append(make_dask_chunk(x, cur_pos, x.shape[0]))\n",
"\n",
" return da.concatenate(chunks, axis=0)"
]
},
{
"cell_type": "markdown",
"id": "07e2dd9c-c2dd-4019-a1ac-c5c966a427cc",
"metadata": {},
"source": [
"## Demo"
]
},
{
"cell_type": "markdown",
"id": "b3406ef7",
"metadata": {},
"source": [
"First showing the above works:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "622fd838-0c91-4ac3-a9dd-cae9de5ec5c9",
"metadata": {},
"outputs": [],
"source": [
"z = zarr.open(\"s1d1.zarr\")\n",
"x = ad.experimental.sparse_dataset(z[\"X\"])"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "18b92237-0716-40e8-9359-211a9c58de67",
"metadata": {},
"outputs": [],
"source": [
"# showing that they are equal\n",
"assert not (x.to_memory() != sparse_dataset_as_dask(x, 1000).compute()).nnz"
]
},
{
"cell_type": "markdown",
"id": "67ff3ea5",
"metadata": {},
"source": [
"Now a real usecase:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "ae06d1d3-0e5a-4da2-a16e-20ddf7ffc3e3",
"metadata": {},
"outputs": [],
"source": [
"def read_w_sparse_dask(path: str, obs_chunk: int = 1000) -> ad.AnnData:\n",
" z = zarr.open(path)\n",
" return ad.AnnData(\n",
" X=sparse_dataset_as_dask(ad.experimental.sparse_dataset(z[\"X\"]), obs_chunk),\n",
" obs=ad.experimental.read_elem(z[\"obs\"]),\n",
" var=ad.experimental.read_elem(z[\"var\"]),\n",
" )"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "8659881f-c539-43a2-94c0-38e7eed4b724",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 30.5 ms, sys: 7.18 ms, total: 37.7 ms\n",
"Wall time: 35.7 ms\n"
]
}
],
"source": [
"%%time\n",
"adatas = {s: read_w_sparse_dask(f\"{s}.zarr\", 4000) for s in samples}"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "61261b51-2c7d-42ed-978c-bb840272f2b2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 19.7 ms, sys: 3.83 ms, total: 23.6 ms\n",
"Wall time: 22.9 ms\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"/mnt/workspace/mambaforge/envs/anndata-dev/lib/python3.11/site-packages/anndata/_core/merge.py:1242: FutureWarning: The default value of 'ignore' for the `na_action` parameter in pandas.Categorical.map is deprecated and will be changed to 'None' in a future version. Please set na_action to the desired value to avoid seeing this warning\n",
" concat_indices = concat_indices.str.cat(label_col.map(str), sep=index_unique)\n"
]
}
],
"source": [
"%%time\n",
"combined = ad.concat(adatas, index_unique=\"-\")"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "003d068d-0bd4-4696-93dd-6a1e2e50e456",
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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3NnZqe985zvKysrSa6+9Ftfa9DISaTC9/NFHH8nn88nv9+v222/Xq6++qkWLFsX9HmF6GYkyUB//93//tw4dOqTf/OY3CV+bPkYiDeaafP78eR07dkzBYFCnTp3S6tWr9fWvf11r166Na216OTZDahhx6tQpSdKoUaMijhlj+n1etGODZfX8t9xyi6TPawei9XGy0cdIpFh6ubOzU48++qg++ugjVVRUKDc3N6616WUkkpXrcldXl3bt2qUDBw7EtTa9jESJ1scnTpzQyy+/rH/913/V7bffnvC16WMk0kDX5Iceekjr16/XqVOndPHiRe3Zs0dPPPGEgsGgFixYoEuXLllem16OzZAaRly4cEHS1U9p/6KsrCxJUmtra8Sxtra2Po+xwur5v/SlL0n6vHYgWh8nG32MRBpsL7e1tWnOnDnavXu3NmzYoPz8/LjXppeRSIPp5a985Ssyxqinp0cnTpzQ//7v/+rYsWMqKChQc3Oz5bXpZSRKtD7+4Q9/qLy8PP3t3/5tUtamj5FIA12T161bp29/+9saM2aMRo4cqb/8y79UeXm5vvGNb6itrU3vvfee5bXp5dgMqWFEdna2JF33K7SufeXLwYMHI45du2vR31ccDYbV8197GU9OTo7lteEt0fo42ehjJNJgevnUqVOaNWuWGhoatHHjRs2aNSsha9PLSKRYrst+v1+33XabFixYoFdffVWXL1+O660a9DISpb8+bm1tVUVFhXbu3Km0tDT5fL7ebf/+/ZKu/qfP5/Opp6fH0tr0MRLJSlb2+Xx68MEHJUmnT5+2vDa9HJshNYwYO3asJOncuXMRx67daSstLY04VlJS0ucxVlg9/7Var9UOROvjZKOPkUgD9fKxY8c0Y8YMffzxx9q0aZNmzpyZsLXpZSSS1evylStXJMU3XKaXkSj99XE4HE762vQxEsnKNdkYox07dkiSxowZY3ltejk2Q2oY8dWvflUjRozQH/7wh4hjBQUFGjdunLZt26Yf/ehHOnfunNrb2/WLX/xCa9eu1ahRo/TYY49ZXtvq+a/Veu0TVoFofZxs9DESKVovHzx4UA8++KDa2tpUU1OjBx54IKFr08tIpGi9/C//8i/6yU9+orq6Op0/f15dXV1qbm7Wr371K/3zP/+zJMU1aKOXkSj99fGoUaNkjLnudu0DAi9duiRjjNLT0y2tTR8jkaJdk5cuXaof//jH2rNnj86fP6+Ojg7t3btX8+fP13vvvaesrCzNnj3b8tr0coyMS2VlZZmioqKYn1dYWGiGDRtmurq6Io5t3LjR+P1+I6nP5vP5zOrVqyMeP2PGDCPJ7Nu3b1Brx3p+Y4x58cUXjSTT0tIS09/T6s8H9qqurjaSTGtra0zPi9bHzzzzTESP/em2Zs2aPo9P5T62+vOB/RYsWGAKCgpifl5/vfz9738/ah9fr2dTuZet/nxgv0Tnix/96EdR+/iZZ56JOFcq9zL5wh2SkS+uZ+rUqUaSuXTpUsSxVO5j8oV7JDpf/OQnP+n3epyenu66//O5PF/sGVKvjJCk7373u+rq6tKGDRsijhUWFmrr1q166KGHNHLkSGVmZmrmzJmqqqrSU089FfH4ay9bG+wUONbzh0IhrVu3Tvn5+Ro/fnyMf1N4WbQ+jhV9DCfRy/CK/nr5n/7pn/Rf//VfmjVrlm699VYFAgGNHj1a3/zmN1VWVqbi4uKIc9HLcArXZHhFf73805/+VL/+9a81c+ZMjRo1SoFAQOPGjdOzzz6rPXv28H8+uzk9DrHK6mT+ypUr5pZbbjHz5s2La/1QKGSys7PNpEmTTDgcjutc/dm0aZORZMrKymJ+Lncu3MHqZH6o9DF3LtzD6mR+qPSyy+9cDCnki+jIF+5AvoiOfOEe5IvoXJ4vht4rIzIyMvTyyy+rsrJSjY2Nls9z8OBBXbhwQUuWLJHP50tghZ9btmyZJk+erCeffDIp54d70cfwCnoZXkEvwwvoY3gFvewOQ24YIUmLFi3ShAkT9POf/9zyOXbs2KHx48fr6aefTmBln9u5c6dqamq0bNky+f3+pKwBd6OP4RX0MryCXoYX0MfwCno59Vn7yFuXCwQCOnLkSFznWLRokRYtWpSgiiLNmDFDxpiknR/uRx/DK+hleAW9DC+gj+EV9HLqG5KvjAAAAAAAAM5hGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYimEEAAAAAACwVbrTBcSjvr5e5eXlTpchSQqFQvL7/U6X0SsYDDpdAmJQUVGhzMxMp8uQlFq93NDQ4HQJiMGZM2dS5pospVYvNzc3y+fzOV0GBol80T/yhbuQL66PfOEu5Iv+uT1fuHoYsXz5ci1fvtzpMoC4Pf/8806XAMStoaFB8+fPd7qMlFVQUOB0CRgk8gW8gnwBLyBfROfmfOEzxhini3A7Y4wmTpyopUuX6oknnnC6HMCy+vp6zZ49W6dPn06ZOymAFUuWLFFzc7NWr17tdCmAZeQLeAX5Al5BvkioOj4zIgF2796tpqYmlZSUOF0KEJeVK1eqo6ND69evd7oUwDJjjIqLi1VRUaGLFy86XQ5gGfkCXkG+gBeQLxKPYUQCrFq1SpK0YcMGtbe3O1wNYE04HO4NvARfuNnOnTt18uRJBYNBVVZWOl0OYBn5Al5AvoBXkC8Sj2FEnEKhkEpLSyVdvdiuXbvW4YoAa2pra/Xpp59KkqqqqnT+/HmHKwKsWblypTIyMpSWlkbwhWuRL+AV5At4Bfki8RhGxGnLli19LqrFxcUOVgNYt3LlSgUCgd4/E3zhRj09PVq1apW6u7sVCoW0efPm3hAMuAn5Al5BvoAXkC+Sg2FEnK5NyKSrdzFqa2t1+vRph6sCYhMMBlVeXt77lW3GGK1YscLhqoDY1dTUqK2trffPPp9Pv/3tbx2sCLCGfAEvIF/AK8gXycEwIg5dXV16++231d3d3bsvLS0tpb4HFxiMjRs39vkgnnA4rJ07d+rEiRMOVgXE7ot34MLhMMEXrkO+gFeQL+AV5IvkYBgRhw0bNqizs7PPvlAoRGPCdUpLS/tcYCUpPT2dry2Cq3R1dWnt2rW9d+Ckq2Hhgw8+UEtLi3OFATEiX8AryBfwAvJF8jCMiENpaan8fn+ffcYY1dfX6+jRow5VBcSms7NTlZWVfS6w0tX3xr311lsOVQXErrKyUpcvX47Yn56ezh1luAr5Al5AvoBXkC+Sh2GERZcuXdI777yjnp6eiGOBQIDGhGusW7dOV65cidhvjNGBAwd05MgRB6oCYldSUhLxHzjp6nuWCb5wC/IFvIJ8Aa8gXyQPwwiL1q5de92gIF1tzDfeeMPmigBr+rvASlJGRkbv99wDqezixYuqqqrq97p8+PBhHTp0yOaqgNiRL+AV5At4AfkiuRhGWFRcXCyfz9fv8aNHj6qhocHGioDYtbW1qaampt8LbHd3NxNfuMKaNWsUDof7PR4IBHiPMlyBfAEvIF/AK8gXycUwwoKzZ89q69atCoVC/T4mEAiorKzMxqqA2JWXl8sYE/UxTU1N2rdvn00VAdYUFxdHPR4MBvXmm28O2O+Ak8gX8AryBbyCfJFcDCMsKC8vjxoUpM/fQ0RjIpWVlJREnfZKV79HmeCLVHb69Glt3759wOvyJ598orq6OpuqAmJHvoBXkC/gBeSL5Et3ugA3Onz4sPLy8voEgQ8//FBjxoxRTk5O77709HQdOXJEX/7yl50oE4iqvb1dly9f1qRJk3r3dXR0qKWlRXfffXef93k2NjY6USIwKLt27VJeXl6fsHDy5El1d3crNze3d19aWprq6up03333OVAlMDDyBbyAfAGvIF8kn88wWk+InJwcLV26VAsXLnS6FMCympoazZ07V62trX2CL+A2CxcuVEtLi6qrq50uBYgL+QJeQL6AV5AvEqqOt2kAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYimEEAAAAAACwFcMIAAAAAABgK4YRAAAAAADAVgwjAAAAAACArRhGAAAAAAAAWzGMAAAAAAAAtmIYAQAAAAAAbMUwAgAAAAAA2IphBAAAAAAAsBXDCAAAAAAAYCuGEQAAAAAAwFYMIwAAAAAAgK0YRgAAAAAAAFsxjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYimEEAAAAAACwFcMIAAAAAABgq3SnC7CqoqJC3d3dTpfRKxAIaP/+/SovL3e6lF733nuvJkyY4HQZiOLMmTOqra11uoxehw8fVmZmpioqKpSZmel0Ob3mzZunQCDgdBmIYu/evWpqanK6jF4nTpxQe3t7Sl2Tx4wZo/z8fKfLwADIFwMjX6Q+8sXgkC9SH/liYG7OFz5jjHG6CCuys7PV3t7udBkpraioSAsXLnS6DERRU1OjuXPnOl1GymttbVVOTo7TZSCKF154Qa+//rrTZaS0goIC1dTUOF0GBkC+GBj5IvWRLwaHfJH6yBcDc3G+qHP12zSKiopkjGG7zpaVleX0rwcxaG1tdbxnUnGrrq52+leDGBQUFDjeM6m6LViwwOlfD2JAvuh/I1+4C/ni+hv5wl3IF/1vbs8Xrh5GAAAAAAAA92EYAQAAAAAAbMUwAgAAAAAA2IphBAAAAAAAsBXDCAAAAAAAYCuGEQAAAAAAwFYMIwAAAAAAgK0YRgAAAAAAAFsxjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICthuQwIhgM6q677tJzzz0XcWzHjh2aM2eOsrKyNHLkSM2aNUvV1dUJW3uw59+xY4d8Pp82bdqUsLXhLf318ccff6xf//rXevjhh3XDDTfI5/OpqqoqoWvTx0ik6/VyZ2enSktL9cgjjyg3N1c33HCDbrvtNs2fP1/79u1L2Nr0MhKJfAEvIF/AK8gXLmBcKisryxQVFVl67i9/+UuTnp5uGhsb++yvqqoyfr/fSOqz+Xw+U15eHnfNsZ5/zpw5Ji8vz4RCoZjXiufnA/tUV1cbSaa1tTXm5/bXx6NHj47osY0bNyaqZFv7OJ6fD+y1YMECU1BQYOm51+vll19+OaLHrm2BQCAhPW1nL8fz84G9yBfRkS/cgXwRHfnCPcgX0bk8X+wZcq+M6O7u1quvvqrHHntMEydO7LP/Bz/4gUKhkF566SWdPXtWbW1teuWVV2SM0aJFi9TR0RHXurGe/8c//rEaGhq0Zs0ay+vCm/rrY0nKzc3V4sWLVVVVpRdeeCHh69LHSKT+ennkyJF69tlntX79ejU1Nemzzz7Tvn37NGfOHAWDQS1evDjudellJBL5Al5AvoBXkC9cwrlBSHysTubLysqMJFNZWdln/7vvvmskmfz8/IjnPP7440aSKSkpsVyvlfP39PSYsWPHmtmzZ8e8Hncu3MHqZL6/Pv6ixYsXJ/TOhd19zJ0L97A6mR9sL1/T2dlpcnJyjCRz7ty5mNe7xu5edvmdiyGFfBEd+cIdyBfRkS/cg3wRncvzxdB7ZcSKFSs0fPhwFRYW9tm/bds2SdIzzzwT8Zxnn31WklRbW2t5XSvn9/v9evTRR7V161YdP37c8trwnv76ONnoYyRarL184403aty4cUpPT1dmZqbldellJBr5Al5AvoBXkC/cYUgNI3p6erR9+3bdc889CgQCfY4dPXpUkjR58uSI502ZMqXPY6ywev77779fkrRlyxbLa8NbovVxstHHSCQrvfzHP/5RDQ0NeuSRRzRs2DDLa9PLSCTyBbyAfAGvIF+4x5AaRhw+fFgdHR2aOnVqxLGLFy9Kkm666aaIY9f2tbe3W17b6vmnTZsmSdq1a5flteEt0fo42ehjJFKsvdzZ2anvfOc7ysrK0muvvRbX2vQyEol8AS8gX8AryBfuke50AXY6deqUJGnUqFERx4wx/T4v2rHBsnr+W265RdLntQPR+jjZ6GMkUiy93NnZqUcffVQfffSRNm7cqNzc3LjWppeRSOQLeAH5Al5BvnCPITWMuHDhgqSrn6L6RVlZWZKk1tbWiGNtbW19HmOF1fN/6UtfkvR57UC0Pk42+hiJNNhebmtr07e+9S0dOHBAGzZsUH5+ftxr08tIJPIFvIB8Aa8gX7jHkHqbRnZ2tqTPXz7zp6595cvBgwcjjh04cKDPY6ywev5rL+PJycmxvDa8JVofJxt9jEQaTC+fOnVKs2bNUkNDgzZu3KhZs2YlZG16GYlEvoAXkC/gFeQL9xhSw4ixY8dKks6dOxdx7NokrLS0NOJYSUlJn8dYYfX812q9VjsQrY+TjT5GIg3Uy8eOHdOMGTP08ccfa9OmTZo5c2bC1qaXkUjkC3gB+QJeQb5wjyE1jPjqV7+qESNG6A9/+EPEsYKCAo0bN07btm3Tj370I507d07t7e36xS9+obVr12rUqFF67LHHLK9t9fzXar32CatAtD5ONvoYiRStlw8ePKgHH3xQbW1tqqmp0QMPPJDQtellJBL5Al5AvoBXkC9cxLhUVlaWKSoqivl5hYWFZtiwYaarqyvi2MaNG43f7zeS+mw+n8+sXr064vEzZswwksy+ffsGtXas5zfGmBdffNFIMi0tLTH9Pa3+fGCv6upqI8m0trbG9LxoffzMM89E9NifbmvWrOnz+FTuY6s/H9hvwYIFpqCgIObn9dfL3//+96P28fV6NpV72erPB/YjX0RHvnAH8kV05Av3IF9E5/J8sWdIvTJCkr773e+qq6tLGzZsiDhWWFiorVu36qGHHtLIkSOVmZmpmTNnqqqqSk899VTE48PhsCQpPX1wnwMa6/lDoZDWrVun/Px8jR8/Psa/KbwsWh/Hij6Gk+hleAX5Al7ANRleQS+7hNPjEKusTuavXLlibrnlFjNv3ry41g+FQiY7O9tMmjTJhMPhuM7Vn02bNhlJpqysLObncufCHaxO5odKH3Pnwj2sTuaHSi+7/M7FkEK+iI584Q7ki+jIF+5BvojO5fli6L0yIiMjQy+//LIqKyvV2Nho+TwHDx7UhQsXtGTJEvl8vgRW+Llly5Zp8uTJevLJJ5NyfrgXfQyvoJfhFfQyvIA+hlfQy+4w5IYRkrRo0SJNmDBBP//5zy2fY8eOHRo/fryefvrpBFb2uZ07d6qmpkbLli2T3+9PyhpwN/oYXkEvwyvoZXgBfQyvoJdT3+De+OIxgUBAR44ciescixYt0qJFixJUUaQZM2bIGJO088P96GN4Bb0Mr6CX4QX0MbyCXk59Q/KVEQAAAAAAwDkMIwAAAAAAgK0YRgAAAAAAAFsxjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2Sne6gHjU19ervLzc6TIkSaFQSH6/3+kyegWDQadLQAwqKiqUmZnpdBmSUquXGxoanC4BMThz5kzKXJOl1Orl5uZm+Xw+p8vAIJEv+ke+cBfyxfWRL9yFfNE/t+cLVw8jli9fruXLlztdBhC3559/3ukSgLg1NDRo/vz5TpeRsgoKCpwuAYNEvoBXkC/gBeSL6NycL3zGGON0EW5njNHEiRO1dOlSPfHEE06XA1hWX1+v2bNn6/Tp0ylzJwWwYsmSJWpubtbq1audLgWwjHwBryBfwCvIFwlVx2dGJMDu3bvV1NSkkpISp0sB4rJy5Up1dHRo/fr1TpcCWGaMUXFxsSoqKnTx4kWnywEsI1/AK8gX8ALyReIxjEiAVatWSZI2bNig9vZ2h6sBrAmHw72Bl+ALN9u5c6dOnjypYDCoyspKp8sBLCNfwAvIF/AK8kXiMYyIUygUUmlpqaSrF9u1a9c6XBFgTW1trT799FNJUlVVlc6fP+9wRYA1K1euVEZGhtLS0gi+cC3yBbyCfAGvIF8kHsOIOG3ZsqXPRbW4uNjBagDrVq5cqUAg0Ptngi/cqKenR6tWrVJ3d7dCoZA2b97cG4IBNyFfwCvIF/AC8kVyMIyI07UJmXT1LkZtba1Onz7tcFVAbILBoMrLy3u/ss0YoxUrVjhcFRC7mpoatbW19f7Z5/Ppt7/9rYMVAdaQL+AF5At4BfkiORhGxKGrq0tvv/22uru7e/elpaWl1PfgAoOxcePGPh/EEw6HtXPnTp04ccLBqoDYffEOXDgcJvjCdcgX8AryBbyCfJEcDCPisGHDBnV2dvbZFwqFaEy4TmlpaZ8LrCSlp6fztUVwla6uLq1du7b3Dpx0NSx88MEHamlpca4wIEbkC3gF+QJeQL5IHoYRcSgtLZXf7++zzxij+vp6HT161KGqgNh0dnaqsrKyzwVWuvreuLfeesuhqoDYVVZW6vLlyxH709PTuaMMVyFfwHCRZpMAACAASURBVAvIF/AK8kXyMIyw6NKlS3rnnXfU09MTcSwQCNCYcI1169bpypUrEfuNMTpw4ICOHDniQFVA7EpKSiL+Ayddfc8ywRduQb6AV5Av4BXki+RhGGHR2rVrrxsUpKuN+cYbb9hcEWBNfxdYScrIyOj9nnsglV28eFFVVVX9XpcPHz6sQ4cO2VwVEDvyBbyCfAEvIF8kF8MIi4qLi+Xz+fo9fvToUTU0NNhYERC7trY21dTU9HuB7e7uZuILV1izZo3C4XC/xwOBAO9RhiuQL+AF5At4BfkiuRhGWHD27Flt3bpVoVCo38cEAgGVlZXZWBUQu/Lychljoj6mqalJ+/bts6kiwJri4uKox4PBoN58880B+x1wEvkCXkG+gFeQL5KLYYQF5eXlUYOC9Pl7iGhMpLKSkpKo017p6vcoE3yRyk6fPq3t27cPeF3+5JNPVFdXZ1NVQOzIF/AK8gW8gHyRfOlOF+BGhw8fVl5eXp8g8OGHH2rMmDHKycnp3Zeenq4jR47oy1/+shNlAlG1t7fr8uXLmjRpUu++jo4OtbS06O677+7zPs/GxkYnSgQGZdeuXcrLy+sTFk6ePKnu7m7l5ub27ktLS1NdXZ3uu+8+B6oEBka+gBeQL+AV5Ivk8xlG6wmRk5OjpUuXauHChU6XAlhWU1OjuXPnqrW1tU/wBdxm4cKFamlpUXV1tdOlAHEhX8ALyBfwCvJFQtXxNg0AAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYimEEAAAAAACwFcMIAAAAAABgK4YRAAAAAADAVgwjAAAAAACArRhGAAAAAAAAWzGMAAAAAAAAtmIYAQAAAAAAbMUwAgAAAAAA2IphBAAAAAAAsBXDCAAAAAAAYCuGEQAAAAAAwFYMIwAAAAAAgK0YRgAAAAAAAFsxjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsle50AVZVVFSou7vb6TJ6BQIB7d+/X+Xl5U6X0uvee+/VhAkTnC4DUZw5c0a1tbVOl9Hr8OHDyszMVEVFhTIzM50up9e8efMUCAScLgNR7N27V01NTU6X0evEiRNqb29PqWvymDFjlJ+f73QZGAD5YmDki9RHvhgc8kXqI18MzM35wmeMMU4XYUV2drba29udLiOlFRUVaeHChU6XgShqamo0d+5cp8tIea2trcrJyXG6DETxwgsv6PXXX3e6jJRWUFCgmpoap8vAAMgXAyNfpD7yxeCQL1If+WJgLs4Xda5+m0ZRUZGMMWzX2bKyspz+9SAGra2tjvdMKm7V1dVO/2oQg4KCAsd7JlW3BQsWOP3rQQzIF/1v5At3IV9cfyNfuAv5ov/N7fnC1cMIAAAAAADgPgwjAAAAAACArRhGAAAAAAAAWzGMAAAAAAAAtmIYAQAAAAAAbMUwAgAAAAAA2IphBAAAAAAAsBXDCAAAAAAAYCuGEQAAAAAAwFYMIwAAAAAAgK0YRgAAAAAAAFsxjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALDVkBxGBINB3XXXXXruueciju3YsUNz5sxRVlaWRo4cqVmzZqm6ujphaw/2/Dt27JDP59OmTZsStja8hT6GV9DL8Ap6GV5AH8Mr6GUXMC6VlZVlioqKLD33l7/8pUlPTzeNjY199ldVVRm/328k9dl8Pp8pLy+Pu+ZYzz9nzhyTl5dnQqFQzGvF8/OBfaqrq40k09raGvNzh0Ifx/Pzgb0WLFhgCgoKLD13KPRyPD8f2It8ER35wh3IF9GRL9yDfBGdy/PFniE3jLhy5Yq59dZbzRNPPBGxf/z48UaSeemll8zZs2dNW1ubeeWVV4wkM2rUKHPp0iXL9Vo5/6ZNm4wks2rVqpjXIyy4g9V/DIdKHxMW3MPqP4ZDpZddHhaGFPJFdOQLdyBfREe+cA/yRXQuzxdDbxhRVlZmJJnKyso++999910jyeTn50c85/HHHzeSTElJieV6rZy/p6fHjB071syePTvm9QgL7mD1H8Oh0seEBfew+o/hUOlll4eFIYV8ER35wh3IF9GRL9yDfBGdy/PFniH3mRErVqzQ8OHDVVhY2Gf/tm3bJEnPPPNMxHOeffZZSVJtba3lda2c3+/369FHH9XWrVt1/Phxy2vDe+hjeAW9DK+gl+EF9DG8gl52hyE1jOjp6dH27dt1zz33KBAI9Dl29OhRSdLkyZMjnjdlypQ+j7HC6vnvv/9+SdKWLVssrw1voY/hFfQyvIJehhfQx/AKetk9htQw4vDhw+ro6NDUqVMjjl28eFGSdNNNN0Ucu7avvb3d8tpWzz9t2jRJ0q5duyyvDW+hj+EV9DK8gl6GF9DH8Ap62T2G1DDi1KlTkqRRo0ZFHDPG9Pu8aMcGy+r5b7nlFkmf1w7Qx/AKehleQS/DC+hjeAW97B5Dahhx4cIFSdLIkSMjjmVlZUmSWltbI461tbX1eYwVVs//pS99SdLntQP0MbyCXoZX0MvwAvoYXkEvu8eQGkZkZ2dL+vzlM39q4sSJkqSDBw9GHDtw4ECfx1hh9fzXXsaTk5NjeW14C30Mr6CX4RX0MryAPoZX0MvuMaSGEWPHjpUknTt3LuJYfn6+JKm0tDTiWElJSZ/HWGH1/NdqvVY7QB/DK+hleAW9DC+gj+EV9LKL2Pc1ooll5Xuug8GgGTFihJk+fXrEsStXrphx48YZSeall14yZ8+eNRcuXDCvvPKKkWRGjRplLl26ZLleq+d/8803jSTzxhtvxLQe3wPuDla+53oo9THfA+4eVr7neij1ssu/B3xIIV9ER75wB/JFdOQL9yBfROfyfLFnSA0jjDGmsLDQDBs2zHR1dUUc27hxo/H7/UZSn83n85nVq1dHPH7GjBlGktm3b9+g1o71/MYY8+KLLxpJpqWlJaa/J2HBHaz+YzhU+piw4B5W/zEcKr3s8rAwpJAvoiNfuAP5IjryhXuQL6Jzeb7YM6TepiFJ3/3ud9XV1aUNGzZEHCssLNTWrVv10EMPaeTIkcrMzNTMmTNVVVWlp556KuLx4XBYkpSenj6otWM9fygU0rp165Sfn6/x48fH+DeFl9HH8Ap6GV5BL8ML6GN4Bb3sEk6PQ6yyOpm/cuWKueWWW8y8efPiWj8UCpns7GwzadIkEw6H4zpXfzZt2mQkmbKyspify50Ld7A6mR8qfcydC/ewOpkfKr3s8jsXQwr5IjryhTuQL6IjX7gH+SI6l+eLoffKiIyMDL388suqrKxUY2Oj5fMcPHhQFy5c0JIlS+Tz+RJY4eeWLVumyZMn68knn0zK+eFe9DG8gl6GV9DL8AL6GF5BL7vDkBtGSNKiRYs0YcIE/fznP7d8jh07dmj8+PF6+umnE1jZ53bu3KmamhotW7ZMfr8/KWvA3ehjeAW9DK+gl+EF9DG8gl5OfYN744vHBAIBHTlyJK5zLFq0SIsWLUpQRZFmzJghY0zSzg/3o4/hFfQyvIJehhfQx/AKejn1DclXRgAAAAAAAOcwjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYKt3pAuJRX1+v8vJyp8uQJIVCIfn9fqfL6BUMBp0uATGoqKhQZmam02VISq1ebmhocLoExODMmTMpc02WUquXm5ub5fP5nC4Dg0S+6B/5wl3IF9dHvnAX8kX/3J4vXD2MWL58uZYvX+50GUDcnn/+eadLAOLW0NCg+fPnO11GyiooKHC6BAwS+QJeQb6AF5AvonNzvvAZY4zTRbidMUYTJ07U0qVL9cQTTzhdDmBZfX29Zs+erdOnT6fMnRTAiiVLlqi5uVmrV692uhTAMvIFvIJ8Aa8gXyRUHZ8ZkQC7d+9WU1OTSkpKnC4FiMvKlSvV0dGh9evXO10KYJkxRsXFxaqoqNDFixedLgewjHwBryBfwAvIF4nHMCIBVq1aJUnasGGD2tvbHa4GsCYcDvcGXoIv3Gznzp06efKkgsGgKisrnS4HsIx8AS8gX8AryBeJxzAiTqFQSKWlpZKuXmzXrl3rcEWANbW1tfr0008lSVVVVTp//rzDFQHWrFy5UhkZGUpLSyP4wrXIF/AK8gW8gnyReAwj4rRly5Y+F9Xi4mIHqwGsW7lypQKBQO+fCb5wo56eHq1atUrd3d0KhULavHlzbwgG3IR8Aa8gX8ALyBfJwTAiTtcmZNLVuxi1tbU6ffq0w1UBsQkGgyovL+/9yjZjjFasWOFwVUDsampq1NbW1vtnn8+n3/72tw5WBFhDvoAXkC/gFeSL5GAYEYeuri69/fbb6u7u7t2XlpaWUt+DCwzGxo0b+3wQTzgc1s6dO3XixAkHqwJi98U7cOFwmOAL1yFfwCvIF/AK8kVyMIyIw4YNG9TZ2dlnXygUojHhOqWlpX0usJKUnp7O1xbBVbq6urR27dreO3DS1bDwwQcfqKWlxbnCgBiRL+AV5At4AfkieRhGxKG0tFR+v7/PPmOM6uvrdfToUYeqAmLT2dmpysrKPhdY6ep749566y2HqgJiV1lZqcuXL0fsT09P544yXIV8AS8gX8AryBfJwzDCokuXLumdd95RT09PxLFAIEBjwjXWrVunK1euROw3xujAgQM6cuSIA1UBsSspKYn4D5x09T3LBF+4BfkCXkG+gFeQL5KHYYRFa9euvW5QkK425htvvGFzRYA1/V1gJSkjI6P3e+6BVHbx4kVVVVX1e10+fPiwDh06ZHNVQOzIF/AK8gW8gHyRXAwjLCouLpbP5+v3+NGjR9XQ0GBjRUDs2traVFNT0+8Ftru7m4kvXGHNmjUKh8P9Hg8EArxHGa5AvoAXkC/gFeSL5GIYYcHZs2e1detWhUKhfh8TCARUVlZmY1VA7MrLy2WMifqYpqYm7du3z6aKAGuKi4ujHg8Gg3rzzTcH7HfASeQLeAX5Al5BvkguhhEWlJeXRw0K0ufvIaIxkcpKSkqiTnulq9+jTPBFKjt9+rS2b98+4HX5k08+UV1dnU1VAbEjX8AryBfwAvJF8qU7XYAbHT58WHl5eX2CwIcffqgxY8YoJyend196erqOHDmiL3/5y06UCUTV3t6uy5cva9KkSb37Ojo61NLSorvvvrvP+zwbGxudKBEYlF27dikvL69PWDh58qS6u7uVm5vbuy8tLU11dXW67777HKgSGBj5Al5AvoBXkC+Sz2cYrSdETk6Oli5dqoULFzpdCmBZTU2N5s6dq9bW1j7BF3CbhQsXqqWlRdXV1U6XAsSFfAEvIF/AK8gXCVXH2zQAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYimEEAAAAAACwFcMIAAAAAABgK4YRAAAAAADAVgwjAAAAAACArRhGAAAAAAAAWzGMAAAAAAAAtmIYAQAAAAAAbMUwAgAAAAAA2IphBAAAAAAAsBXDCAAAAAAAYCuGEQAAAAAAwFYMIwAAAAAAgK0YRgAAAAAAAFsxjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYimEEAAAAAACwVbrTBVhVUVGh7u5up8voFQgEtH//fpWXlztdSq97771XEyZMcLoMRHHmzBnV1tY6XUavw4cPKzMzUxUVFcrMzHS6nF7z5s1TIBBwugxEsXfvXjU1NTldRq8TJ06ovb09pa7JY8aMUX5+vtNlYADki4GRL1If+WJwyBepj3wxMDfnC58xxjhdhBXZ2dlqb293uoyUVlRUpIULFzpdBqKoqanR3LlznS4j5bW2tionJ8fpMhDFCy+8oNdff93pMlJaQUGBampqnC4DAyBfDIx8kfrIF4NDvkh95IuBuThf1Ln6bRpFRUUyxrBdZ8vKynL614MYtLa2Ot4zqbhVV1c7/atBDAoKChzvmVTdFixY4PSvBzEgX/S/kS/chXxx/Y184S7ki/43t+cLVw8jAAAAAACA+zCMAAAAAAAAtmIYAQAAAAAAbMUwAgAAAAAA2IphBAAAAAAAsBXDCAAAAAAAYCuGEQAAAAAAwFYMIwAAAAAAgK0YRgAAAAAAAFsxjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYimEEAAAAAACwFcMIAAAAAABgK4YRAAAAAADAVgwjAAAAAACArRhGAAAAAAAAWzGMAAAAAAAAtmIYAQAAAAAAbMUwAgAAAAAA2IphBAAAAAAAsBXDCAAAAAAAYCuGEQAAAAAAwFYMIwAAAAAAgK0YRgAAAAAAAFsxjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYimEEAAAAAACwVbrTBcSjvr5e5eXlTpeRkoLBoNMlIAYVFRXKzMx0uoyU09DQ4HQJiMGZM2e4JvejublZPp/P6TIwSOSL/pEv3IV8cX3kC3chX/TP7fnC1cOI5cuXa/ny5U6XAcTt+eefd7oEIG4NDQ2aP3++02WkrIKCAqdLwCCRL+AV5At4AfkiOjfnC58xxjhdhBfcf//9+rd/+zfl5+c7XQpg2fHjxzV9+nQdP35cfr/f6XIAy5YtW6bjx4/rV7/6ldOlAHEhX8ALyBfwCvJFQtXxmREJcOzYMe3Zs0dlZWVOlwLEpaysTCdPntTWrVudLgWIS3FxsUpLS9XT0+N0KYBl5At4BfkCXkG+SCyGEQlQVlYmY4xWrlyp7u5up8sBLHvrrbckieALVzt69KgOHDig1tZWbdmyxelyAMvIF/AK8gW8gHyReAwjEmDFihWSpIsXL6qmpsbhagBrDh8+rA8//FCSVF5eritXrjhcEWBNaWmpAoGAAoGASktLnS4HsIx8AS8gX8AryBeJxzAiTvv371djY6Mk0ZhwtZUrVyoQCEiSOjo6VFVV5XBFgDVvvfWWgsGggsGg3n77bV2+fNnpkoCYkS/gFeQLeAX5IvEYRsSprKys9wIbDAb1u9/9Tp2dnQ5XBcSupKSk9yvb/H4/wReuVF9fr+bm5t4/X758WRs2bHCwIsAa8gW8gnwBLyBfJAfDiDgYY1RcXNznO7evXLmid955x8GqgNh98MEH+vjjj3v/3NPTo8rKSnV0dDhYFRC7srIyZWRk9P7Z7/erpKTEwYqA2JEv4BXkC3gF+SI5GEbEYefOnTp58mSffWlpaTQmXOeLF1jp6p24devWOVQRELtwOKySkpI+H/TX09Ojd999V+3t7Q5WBsSGfAGvIF/AC8gXycMwIg5/+hLKa0KhkKqqqnT+/HmHqgJiEw6HVVpaGvFJ7T6fT8XFxQ5VBcRu27ZtOnPmTMT+cDis3/3udw5UBFhDvoAXkC/gFeSL5GEYYVFPT4/Kysr6vITyGmMMjQnX2LJli86dOxexPxQKafPmzfr0008dqAqI3fXuwF1D8IVbkC/gFeQLeAX5InkYRlhUU1Ojtra26x4zxvR+HReQ6lauXNnvBdbn82nt2rU2VwTELhgMatWqVRF34KSrwXfr1q3XvasBpBryBbyCfAEvIF8kF8MIi/70a4q+KBwOa8eOHTpx4oTNVQGxuXLlitasWXPdC6x0tZcJvnCDqqoqXbx4sd/jaWlpWrNmjY0VAdaQL+AF5At4BfkiuRhGWNDV1aXf/e53130J5TV+v1/l5eU2VgXEbsOGDVG/Ki4cDmv37t19PgkbSEWlpaX9/gdOunr3guCLVEe+gFeQL+AV5IvkYhhhwfr16wf8ru+enh699dZbNlUEWLNy5UqlpQ18GSD4IpV1dnZq3bp1Uf8DZ4zR3r17+3xHOJBqyBfwCvIFvIB8kXwMIyxYtWrVoB63f/9+HT16NMnVANZcunRJ7777rkKhUNTHGWMG3fOAE9avX6+urq4BH0cvI9WRL+AF5At4Bfki+XzGGON0EW7T3t6ucDjcZ98dd9yhn/3sZ/re977XZ39mZma/H94DOCkUCkW8B27r1q16/PHH1dTUpOzs7D7HcnJy7CwPGLTLly9HhIW/+7u/0/HjxyM+IC0jI0OZmZl2lgcMGvkCXkC+gFeQL5KuLt3pCtwoKysrYp/P59ONN97IBRWu4ff7I/p1xIgRkqTs7Gx6Ga4xfPhwDR8+vM++G264QYFAgD6Gq5Av4AXkC3gF+SL5eJsGAAAAAACwFcMIAAAAAABgK4YRAAAAAADAVgwjAAAAAACArRhGAAAAAAAAWzGMAAAAAAAAtmIYAQAAAAAAbMUwAgAAAAAA2IphBAAAAAAAsBXDCAAAAAAAYCuGEQAAAAAAwFYMIwAAAAAAgK0YRgAAAAAAAFsxjAAAAAAAALZiGAEAAAAAAGzFMAIAAAAAANiKYQQAAAAAALAVwwgAAAAAAGArhhEAAAAAAMBWDCMAAAAAAICtGEYAAAAAAABbMYwAAAAAAAC2YhgBAAAAAABsxTACAAAAAADYimEEAAAAAACwFcMIAAAAAABgK4YRAAAAAADAVgwjAAAAAACArRhGAAAAAAAAW6U7XYDbtLa26vz58zp//rw6OjokSR0dHQoGg6qvr9emTZvk9/uVnp6um2++uXe74YYbHK4c+FwwGOzt4/Pnz6u7u1uStG3bNknS+vXrddttt0mSbrzxxt4+vummm5SWxgwTqaOzs7NPL0tSd3e3mpqadPbsWb3zzjsaNmyYJCk7O1ujRo3SzTffrJEjRzpZNhCBfAEvIF/AK8gX9vAZY4zTRaSSrq4uHTp0SPv379fRo0fV0tLSu505c0bhcNjSeUeMGKFx48YpNzdXd9xxh3Jzc5WXl6e8vLzeizKQSOfOndP+/ft16NAhHTt2TM3NzWppadEnn3yiCxcuWD7v6NGje3s5NzdXEydO1JQpUzR58mSNGDEigX8DQAqHw2pqatL+/fv10Ucf9fZxS0uLTpw4oa6uLkvnzcjI0NixY3v7+I477tDdd9+tvLw83XnnnUpPZ1aPxCJfwCvIF/AC8kVKqBvSw4hwOKxDhw5p586dev/991VXV6fGxkaFQiENHz5cd955Z59/3MeMGaNRo0b1Tr6uXRgzMzOVkZEhSWpvb1c4HFZPT0/vJO3cuXM6d+6cjh8/rubmZjU3N+vYsWM6deqUJOnmm2/WX/zFX2j69Ol64IEHNH36dGVlZTn2c4H7dHZ2qq6uTjt27NCuXbu0b9++3v4aNWpUn14eN26cbr311t4+vvnmm3v7NycnR5IUCoV08eJFSdJnn33W28tnz57VmTNnei/Wzc3NOnr0qC5duiSfz6cJEyboa1/7mh544AHNmDFD06ZN46KLmJw8eVLvv/++du7cqd27d+vgwYPq6OhQWlqacnNzNWHChN5/4P/8z/+8zx3im2++WT6fTxkZGcrMzJQkXb58uTdQXLhwQWfPnu3t5xMnTvT2cXNzs5qamtTT06Nhw4Zp0qRJ+vrXv97by7m5uQ7+VOA25At4BfkCXkG+SElDbxjxySefqKqqSlVVVfq///s/tbe3a+TIkZo+fbruu+8+TZkyRVOmTNHEiRPl9/uTWktra6v279+vhoYG/f73v9f777+vxsZGpaWladq0aSosLFRhYaGmT5/OBRd9hMNh1dfXq6qqShs3blRdXZ16eno0btw4zZgxQ/fcc4+mTp2qvLw8jRkzJqm1GGPU3NysAwcOqKGhQXv27NH777+v1tZWZWZmKj8/X9/85jdVWFioO++8M6m1wH06Ozu1ZcsWbdy4UZs2bVJTU5PS09M1ZcoUTZ8+XdOmTdOUKVM0adKk3gCQLFeuXNGhQ4fU0NCg/fv3a/fu3aqvr1d3d7f+7M/+TA8//LAKCws1Z84cZWdnJ7UWuA/5Al5AvoBXkC9cYWgMI/74xz+qvLxca9asUUNDgzIzM/WNb3xDDz/8sGbOnKnJkycnPRgM1qeffqr3339fmzdvVlVVlY4dO6bs7Gx9+9vf1lNPPaW5c+fy/tAhKhQK6b333lN5ebkqKip09uxZ3X777SosLFRBQYFmzJih22+/3ekyJV0NEB999JF27Nih6upq1dTUqL29XRMnTtQTTzyh+fPna9q0aU6XCYe0tbWpoqJC5eXleu+99xQMBnXPPfeosLBQs2fP1te//vWUeUnu5cuXtXfvXtXW1qqqqkq7d++Wz+fTgw8+qCeffFJ/9Vd/pdGjRztdJhxCvoAXkC/gFeQL16mT8agzZ86Y//f//p+ZOnWqkWTGjh1rfvjDH5rq6mrT1dXldHmDduTIEfOf//mf5sEHHzRpaWkmOzvb/M3f/I3Zvn2706XBJr///e/N4sWLza233mokma997WvmX//1X82BAwecLm3QgsGg2bZtm/mHf/gHk5ubaySZu+66y/zsZz8zx48fd7o82KC7u9u8/fbb5tvf/rbJyMgww4YNM48++qhZsWKFOXPmjNPlDVpra6spLy83f/3Xf21GjBhh/H6/eeihh8yKFSvMZ5995nR5sAH5Al5BvoAXkC9cbY+nhhHhcNjU1NSYp556ymRk9ENpLgAAIABJREFUZJjs7Gzz4osvmvfee8+EQiGny4vbJ598Yv7jP/7D3HPPPUaSufvuu82///u/m/PnzztdGhLs0qVLpqioyNx7771GkvnKV75iXn31VdPY2Oh0aXELh8Nm9+7d5u///u/N6NGjjd/vN9/61rdMRUWF6enpcbo8JNixY8fMT37yEzN69GiTlpZmvvnNb5oVK1aY9vZ2p0uL22effWbWrFljHn/88d5/c/5/e3ceVlW5vg/8XnuzGRVkUpwQVJRkdB7AISewyCHnyqLjXGlleaxOZWWn/JalVpbmlOWIWmYimJoTOGEOIA4ogkOKCso8s5/fH/7glAoy7LXevdd+Ptflda4rOeu9Nz4ub96191qvvPIKJSQkiI7GDIz7BVML7hdMLbhfqII6NiOKiopo1apV5OfnV7Gzu2TJEsrNzRUdTTanT5+mWbNmkZOTE1lbW9O4cePo7NmzomOxOkpLS6PZs2eTs7MzWVlZ0ciRI2nnzp2k1+tFR5NFaWkp7dy5k0aOHElarZY8PT1p7ty5lJmZKToaq6Njx47RuHHjyMLCgpo0aUKzZs2iS5cuiY4lmzt37tCSJUvI19eXAFBQUBBt3bpVtX93zQX3C+4XasH9gvuFWnC/UFW/MO3NiLy8PPr888/Jzc2NLC0tady4cXTixAnRsRSVk5NDCxcuJE9PT9JoNDRixAiTensduyc5OZlefPFFsrS0JDc3N5ozZw6lp6eLjqWoCxcu0EsvvUS2trbk6OhI7733Ht29e1d0LFZD27dvp27duhEA6tq1K0VERJjVFSm9Xk9RUVHUv39/AkB+fn60YcMGVVw9NyfcL7hfqAX3C+4XasH9QpX9wjQ3IwoLC2nhwoXk5uZGdnZ2NHPmTLp27ZroWEKVlpbShg0bKCAggDQaDY0ZM4avZJiAK1eu0KRJk0in01Hr1q1p+fLlJvWZYzmkp6fTRx99RE5OTuTo6Ehz5syh7Oxs0bHYI+zevZt69OhBACgsLIw/d05EJ06coLFjx5JGoyF/f3/asmWLWq5kqBb3iwdxvzBN3C8exP3CNHG/eJCK+oVpbUbo9Xpav349ubu7k42NDb3++usmdWMSJej1etq4cSP5+PiQVqulyZMn061bt0THYvfJzs6mWbNmkZWVFXl4eNDy5cuppKREdCyjkpmZSbNnzyYHBwdydXWlxYsXm9UOuKlITEykgQMHEgAaMGAAHT58WHQko3P69GkaMWIESZJE3bp14++REeJ+8WjcL0wD94tH435hGrhfPJoK+oXpbEYcO3as4o7P4eHhZn+l4lHKysrohx9+oCZNmlCDBg3oyy+/pOLiYtGxzF5ZWRktX76c3NzcyNHRkRYsWEBFRUWiYxm1jIwMev3110mn01FAQAD98ccfoiMxuvfn8sorr5CFhQW1b9+e9uzZIzqS0Tt+/Dj16dOHJEmicePG8b9jRoL7Rc1wvzBO3C9qjvuFceJ+UXMm3C+MfzMiLy+PZs2aRVqtlrp06UIHDx4UHcmk5OXl0ezZs8nGxoZ8fX3p0KFDoiOZraSkJOrTpw9pNBoaN24cX3WroaSkJBo5ciQBoJEjR/IVOYEiIiLI1dWVnJ2dacGCBXxFqYa2bt1KLVu2JFtbW5o7dy5//wThflE33C+MB/eLuuF+YTy4X9SNCfYL496MiIqKohYtWpCTkxOtXLnSVD8LYxSSk5Opf//+pNFoaPr06ZSTkyM6ktkoKiqiDz/8kKysrKhz58508uRJ0ZFM2q+//kpNmzYlV1dXWrNmjeg4ZuXy5cv0xBNPkCRJNGXKFL4reR0UFBTQO++8Qzqdjnr06EGJiYmiI5kV7heGw/1CHO4XhsX9QhzuF4ZjYv3CODcj8vPzafr06SRJEoWFhZnSW02MXkREBLm4uJCHhwffAEYBZ8+epQ4dOpCNjY2p7FCahKysLJo+fTppNBoaNmyY2d0ZXISIiAhydHSkVq1a0e7du0XHUY34+Hjq2rUrWVlZ0dy5c039rthGj/uFfLhfKIv7hTy4XyiP+4U8TKRfGN9mRFxcHLVt25acnZ1p06ZNouOo0o0bNyg0NJQsLCzoww8/5H/AZKDX62nRokVkY2ND3bp1o4sXL4qOpEp//PEHNW/enJo2bUo7d+4UHUeV7t69S2PGjCFJkui1116jgoIC0ZFUp7S0lD7++GPS6XQ0cOBAun79uuhIqsT9Qn7cL+TH/UIZ3C/kx/1CfibQL4xrM2LBggWk0+moX79+fLVCZnq9nhYuXEjW1tbUq1cvunHjhuhIqpGZmUlDhgwhrVZL7733Ht/FWmZ37tyhkSNHkkajof/85z9cfg3o2LFj1KJFC2rcuDFFR0eLjqN6R44codatW5OrqyuXXwPjfqEc7hfy4X6hLO4X8uF+oSwj7hfGsRmRm5tLzzzzDGm1Wvrvf/9rrG8jUaVTp06Rl5cXNWnShGJjY0XHMXmnT5+mNm3aUOPGjWn//v2i45iV77//nqysrCgkJITfVmkAy5cvJ2traxowYADfzEtBOTk5NGbMGNJqtfTpp5/yvQzqiPuFONwvDIv7hTjcLwyL+4UYRtovxG9GpKSkkL+/Pzk7O9OOHTtExzFLmZmZ9NRTT5GlpSUtXrxYdByTtWnTJqpXrx4FBQUZ49ugzMLRo0fJ3d2dPDw8KD4+XnQck1RSUkJTpkwhSZLorbfe4itBgnz55ZdkYWFBTz/9NOXm5oqOY5K4X4jH/cIwuF+Ix/2i7rhfGAcj6xdiNyOOHj1Kbm5uFBAQQCkpKSKjmD29Xk8ffPABSZJEb775Jl89qqHPP/+cNBoNTZ06lZ+3Ltjt27epT58+ZG9vzz+A1FBWVhYNHDiQ7OzsaPPmzaLjmL29e/eSi4sLderUid/qXkPcL4wH94u64X5hPLhf1B73C+NiRP1C3GbEli1byNbWlkJDQyk7O1tUDHafNWvWkJWVFY0YMYLy8/NFxzF6paWlNHXqVNJoNPTFF1+IjsP+v6KiIho3bhxZWFjQ0qVLRccxCVeuXCF/f39q3LgxxcXFiY7D/r8LFy6Ql5cXeXh4GPvjuYwG9wvjxP2iZrhfGCfuFzXH/cI4GUm/ELMZ8cMPP5BWq6XJkyfzzXeM0L59+8jJyYl69+7NRa4KRUVFNGLECLK1taWff/5ZdBx2H71eT++//z5JkkSffvqp6DhG7cKFC+Tu7k6+vr6UmpoqOg67T3p6OgUHB5OTkxMdPXpUdByjxv3CuHG/qB7uF8aN+0X1cb8wbkbQL5TfjFi8eDFpNBqaNWuW0kuzGjhz5gw1adKEOnbsyDfreYjCwkIaOnQo2dnZ8TORjdx3333H55wqnD17lpo2bcp/141cYWEhDRkyhM85VeB+YRq4X1SN+4Xp4H5RNe4XpkFwv1B2M2L+/PkkSRL997//VXJZVkvnz5+n5s2bU0BAAJ9E/iY/P5/69+9Pjo6OdOTIEdFxWDWsXLmStFotvf7666KjGJWTJ0+Sq6sr9ezZk7KyskTHYY9QVFREw4cPJ1tbW2N7NJdw3C9MC/eLh+N+YXq4Xzwc9wvTIrBfKLcZ8e2335IkSfTll18qtSQzgJSUFPLw8KCOHTtSZmam6DjCFRUVUWhoKDk7O9PJkydFx2E1sG7dOtJqtfT222+LjmIUzp49Sw0bNqS+fftSXl6e6DismkpKSmjs2LFkZ2dHBw4cEB3HKHC/ME3cL/6J+4Xp4n7xT9wvTJOgfqHMZsSqVatIo9HwFQsTdfHiRWrSpAl1796dcnJyRMcRprS0lEaNGkX29vb8uW0TVX4u+uSTT0RHEery5cvk7u5u9n+nTdXfz0XmfjMw7hemjfvFPdwvTB/3i3u4X5g2Af1C/s2ILVu2kFarpXfeeUfupZiMEhMTydXVlUJDQ83ypmB6vZ5eeOEFsrOzo5iYGNFxWB0sWrSIJEky22fep6WlkaenJ3Xq1ImvRpqwoqIiCgkJIRcXFzp//rzoOEJwv1AH7hfcL9SC+wX3CzVQuF/Iuxlx9OhRsrW1pcmTJ8u5DFNIXFwc2dnZ0cSJE0VHUdwHH3xAFhYWFBUVJToKM4CPPvqILCwsKDIyUnQUReXl5VHnzp3Jy8uLbt++LToOq6O8vDzq2rUrtW7dmm7duiU6jqK4X6gL9wvuF2rB/YL7hRoo2C/k24xISUkhNzc3CgkJMcudbrXatm0babVas3ob2rp160iSJFq0aJHoKMxA9Ho9hYeHU7169ej48eOi4yiirKyMhg0bRs7OzmZ7JV2Nbt++Ta1bt6bOnTubzWdzuV+oE/cLpgbcL7hfqIVC/UKezYjc3Fzy8/OjgIAAfo60Cn311VckSRJt2bJFdBTZHTp0iCwtLenf//636CjMwIqLi6lv377UvHlzunnzpug4snv77bfJ2tqab3qoQmfOnCFHR0d67rnnREeRHfcLdeN+wdSA+wVTCwX6hTybEc8//zw5OTlRcnKyHIdnRmDChAlUv359OnPmjOgosklLS6NmzZrRgAEDqLS0VHQcJoM7d+5Qq1at6PHHH1f1FdYtW7aQJEm0bNky0VGYTHbu3ElarZa++uor0VFkxf1C/bhfMDXgfsHUQuZ+YfjNiPnz55NGo+HPvqlcYWEhde7cmdq2bavK5weXlJRQ7969ycPDg5+BrnKnTp0iW1tbevPNN0VHkcX58+fJwcGBP1tvBubMmUM6nY727dsnOoosuF+YB+4XTC24XzC1kLFfGHYzIi4ujnQ6HT9iy0xcvnyZXFxcKDw8XHQUg3v33XfJ1taWn/VtJlatWkWSJNG2bdtERzGowsJC8vf3py5dulBhYaHoOExmer2eBg8eTM2aNaOMjAzRcQyK+4V54X7B1IL7BVMDGfvFUYmICAaQl5eHjh07ws3NDX/88Qc0Go0hDsuMXFRUFJ588kmsXbsWY8aMER3HIGJjY9G7d298/fXXmDp1qug4TCHPP/88oqOjER8fDzc3N9FxDGLGjBlYunQpjh8/Di8vL9FxmALu3r2LwMBAdOrUCZs3bxYdxyC4X5gn7hdMLbhfMDWQqV/EGWwzYtKkSdi0aRNOnjwJd3d3QxySmYipU6di/fr1OHXqlMn/2WdlZSEwMBCPPfYYIiMjIUmS6EhMIbm5uejQoQNatmyJqKgok/+z37lzJ0JCQvDDDz/g+eefFx2HKWjfvn3o27cvli1bhhdffFF0nDrjfmG+uF8wNeB+wdRChn5hmM2I6OhoDBo0CJs2bcLw4cMNEYyZkPz8fHTs2BHu7u7YsWOH6Dh1Mn78eERGRiI+Ph4NGzYUHYcp7ODBg+jVqxcWL16MCRMmiI5Ta9nZ2fDx8UGPHj2wYcMG0XGYADNnzsSSJUuQmJiI5s2bi45Ta9wvzBv3C6YW3C+YWhi4X9R9MyIvLw/+/v7o3Lkz1q9fX9dAzEQdOXIEQUFBWLlyJcaNGyc6Tq3s3bsXffv2xcaNG7n0mrE333wTy5YtQ2JiIpo2bSo6Tq1MnToVmzZtQmJiIpdeM1VUVIT27dvD09MTkZGRouPUCvcLBnC/YOrB/YKpgYH7Rd03I1599VWsXr0aZ86cQaNGjeoaiJmwadOmYd26dThz5ozJnaAKCgrg7+8Pb29v/Pbbb6LjMIHy8/Ph7++P9u3bY+PGjaLj1NihQ4cQHByMn376Cc8884zoOEyg/fv3o0+fPli3bh1Gjx4tOk6Ncb9g5bhfMDXgfsHUwoD9om6bEX/++Se6dOmC5cuXIzw8vC5BmArk5OTAx8cHffv2xQ8//CA6To385z//waJFi3DmzBk0adJEdBwm2M6dOzFw4ED89ttvCAsLEx2n2kpKShAYGAgPDw+TvRrODGvy5Mn49ddfkZSUBHt7e9Fxqo37Bfs77hdMLbhfMLUwUL+o22ZEr169UFpaitjYWJO/GQszjI0bN2L06NE4fPgwunTpIjpOtaSkpKBdu3aYO3cuXn31VdFxmJEYNWoUjh8/jsTERFhZWYmOUy0LFy7Ev//9b5w+fZrvbs0A3Lv7dZs2bfDiiy/is88+Ex2n2rhfsPtxv2Bqwf2CqYGB+kXtNyPWr1+PZ599FocPH0bnzp1rG4CpUJ8+fVBUVISDBw+aRIkcPnw4zpw5g/j4eOh0OtFxmJG4evUqvL298dFHH+GNN94QHeeR7ty5gzZt2mDixIn49NNPRcdhRuSbb77BG2+8gYSEBLRp00Z0nEfifsEqw/2CqQH3C6YWBugXtduMKCoqQtu2bdG3b1+sWLGiNgszFTtx4gQ6d+6Mn376CWPHjhUdp0r79+9H7969ERkZiSeeeEJ0HGZk3nvvPXz99de4ePEiXFxcRMep0vTp07Fx40YkJSWhfv36ouMwI1JaWorAwEB4eXnhl19+ER2nStwvWFW4XzC14H7B1MAA/aJ2mxFff/01Zs2ahYsXL/Ln39hDhYeH4+DBgzhz5gwsLCxEx6lUr169YGlpiV27domOwoxQbm4uWrVqhfDwcPzf//2f6DiVunLlCtq0aYOFCxdi8uTJouMwI7R9+3aEhYXhyJEjRv1uA+4X7FG4XzA14H7B1KKO/aLmmxEFBQXw8vLC6NGj8cUXX9R0QWYmUlNT0bZtWyxevBgvvvii6DgPtWPHDoSGhmL//v3o2bOn6DjMSH3xxReYPXs2kpOTjfaO/hMnTsTOnTuRlJQES0tL0XGYkerevTsaNGiAqKgo0VEeivsFqw7uF0wtuF8wtahDv6j5ZsS8efPwwQcf4NKlSyb3eCWmrEmTJmHXrl04d+6cUZ7AunXrBmdnZ74rMKtSQUEBWrVqhdGjR2P+/Pmi4zwgOTkZjz32GJYsWWK0xZwZh127dmHAgAGIiYlBUFCQ6DgP4H7Bqov7BVMD7hdMLerQL2q2GVFUVARPT08899xzJnVXbibG5cuX4eXlhWXLluH5558XHecf/vjjD/Tr1w9Hjx416rcsM+OwcOFCvPPOO7hy5QqcnZ1Fx/mHqVOnYufOnTh37pxRv2WZGYeePXvCwcEB27ZtEx3lH7hfsJrgfsHUgvsFU4ta9os4TU2+eu3atUhPT8f06dNrlo6ZpRYtWmDUqFGYN28e6vAEWVnMmzcPffr04aLAqmXixImwsbHBt99+KzrKP9y5cwc//fQTZsyYwUWBVcvMmTOxfft2nDlzRnSUf+B+wWqC+wVTC+4XTC1q2y9qtBmxcOFCjB07Fs2aNavRIsx8lT+TeOfOnaKjVDh//jx27NhhEo9TYsbB1tYWU6ZMwTfffIOCggLRcSp88803sLKywgsvvCA6CjMRTz31FLy9vY3uLcHcL1hNcb9gasD9gqlFbftFtTcjdu/ejVOnTmHGjBk1DsfMl7+/P/r27YsFCxaIjlJh/vz58PLy4kdtsRp55ZVXkJWVhfXr14uOAgAoKSnBd999hylTpsDOzk50HGYiJEnCa6+9htWrVyM9PV10HADcL1jtcL9gasH9gqlBbftFtTcjlixZguDgYAQEBNQqIDNfL730Enbs2IHLly+LjoLc3FysW7cOU6dOhUZTozcGMTPn5uaGYcOGYenSpaKjAAB+/fVX3Lp1C5MmTRIdhZmYcePGwdraGj/99JPoKAC4X7Da437B1ID7BVOL2vSLap0t09PTsXXrVkycOLHW4Zj5Gjx4MBo1aoSVK1eKjoJ169ahqKgIzz77rOgozARNmDABhw4dQmJiougoWLp0KQYNGoQWLVqIjsJMjI2NDcaMGYPvv/9e+OftuV+wuuB+wdSC+wVTg9r0i2ptRvzwww+wsbHBiBEj6hSQmScLCwuMGzcOK1asQFlZmdAsy5Ytw4gRI+Di4iI0BzNNffv2RatWrYRfvUhJScGuXbv4BzhWaxMmTMC5c+dw8OBBoTm4X7C64H7B1IL7BVOLmvaLam1GrF69GmPGjIGtrW2dwjHz9eKLL+Lq1avYv3+/sAxJSUk4evQo/vWvfwnLwEybJEkIDw/H+vXrhRbftWvXwsXFBU8++aSwDMy0dezYEf7+/li9erXQHNwvWF1xv2BqwP2CqUVN+8UjNyPOnz+PU6dOYcyYMXUOx8yXt7c3AgMDERERISzDhg0b4Obmht69ewvLwEzf2LFjcfPmTezdu1dYhg0bNmDEiBH8uC1WJ6NHj8amTZtQWloqZH3uF8wQuF8wteB+wdSiJv3ikZsR69evh5ubG4KDgw0SjpmvUaNGCS2+ERERGDFiBLRarZD1mTq0atUK7du3F1Z8z58/j4SEBIwaNUrI+kw9xowZg4yMDGHFl/sFMxTuF0wNuF8wtahJv3jkZsTmzZv5BMsMYtSoUUhPT8e+ffsUX/vcuXM4ffo0Ro4cqfjaTH1Gjx6Nn3/+WchbKTdu3IjGjRujZ8+eiq/N1KVly5bo0KEDNm7cKGR97hfMULhfMLXgfsHUoCb9osrNiGvXriEhIQFDhgwxWDhmvlq1agUfHx9s375d8bW3b98OJycnBAUFKb42U5/BgwcjPT0dcXFxiq8dGRmJsLAwfnQcM4jBgwdj+/btij9Vg/sFMyTuF0wtuF8wtahuv6hy2rZv3w47OzveIWMGM2jQIERFRSm+blRUFEJCQvgKHDOIxx57DC1atFB8lu/cuYO4uDiEhoYqui5Tr9DQUFy7dk3xx8lxv2CGxv2CqQH3C6YW1e0XVW5GREdH4/HHH4eVlZVBwzHzFRoairNnzyIlJUWxNfPy8nDgwAE+wTKDCg0NRXR0tKJr7tixA5IkoV+/foquy9SrU6dOaNiwoeLFl/sFMzTuF0wtuF8wNahuv6h0M0Kv1+OPP/5ASEiIwcMx89WzZ0/Y2dlh9+7diq154MABFBcXY+DAgYqtydQvNDQUx44dw927dxVbc/fu3ejevTscHBwUW5Opm0ajQf/+/bFr1y7F1uR+weTA/YKpBfcLpgbV7ReVbkYkJCQgKysLvXr1Mng4Zr4sLS3RpUsXxMbGKrZmbGwsvLy84ObmptiaTP2Cg4NBRDh06JBia8bExPA5mRlcz549cejQIcVumMb9gsmB+wVTC+4XTC2q0y8q3Yw4ePAg7O3t4ePjI0s4Zr6Cg4MVLwt8YylmaC4uLmjbtq1is5yeno6kpCT06NFDkfWY+QgKCkJOTg4SEhIUWY/7BZML9wumBtwvmFpUp19UuRnRrVs3viEPM7igoCBcuHABaWlpsq9VWlqKuLg4PsEyWQQFBSlWFg4ePAgA6NatmyLrMfPh6+sLJycnRWeZ+wWTA/cLphbcL5gaVKdfVLoZcezYMXTp0kWWYMy8lc/V8ePHZV/r3LlzyM3N5VlmsujatSv+/PNP6PV62df6888/4eXlBScnJ9nXYuZFkiR07NhRsUfJcb9gcuF+wdSC+wVTg+r0i4duRhQUFODChQsICAiQLRwzX46OjmjevDni4+NlX+vUqVOwtLSEt7e37Gsx8+Pv74/c3FxF7t5+6tQpBAYGyr4OM0/+/v6KfEyD+wWTE/cLphbcL5haPKpfPHQz4vTp0ygrK4O/v79swZh5U6r4xsfH47HHHoOlpaXsazHz4+vrC41Go0jxjY+Ph5+fn+zrMPPk5+eHxMRElJaWyroO9wsmN+4XTA24XzC1eFS/qHQzwsbGBq1atZI1HDNffn5+ipxgExIS4OvrK/s6zDzZ2dmhZcuWshffnJwcpKamcllgsvH390dRURGSkpJkXYf7BZMb9wumBtwvmFo8ql88dDPiwoUL8PLy4ptLMdl4e3vj4sWLICJZ17lw4QK/hZLJqm3btrhw4YKsa5T/XWnbtq2s6zDz1bZtW0iSJPssc79gcuN+wdSC+wVTg0f1i4duRqSkpMDT01PWYMy8eXh4oLCwUNY7Xuv1ely9ehUeHh6yrcGYh4cHUlNTZV0jNTUVkiTxLDPZ2NrawtXVVfZZ5n7B5Mb9gqkF9wumBo/qFw/djEhNTeWhZLIqL6NynmT/+usvFBUVcfFlsvL09JT9BlMpKSlwc3ODtbW1rOsw8+bp6alI8eV+weTE/YKpBfcLphZV9QvejGBCNG3aFDqdTtaT7OXLlwGAZ5nJytPTEzdu3EBRUZFsa1y+fJnnmMlOieLL/YLJjfsFUwvuF0wtquoXD2xG6PV63L59G40bN5Y9mFKio6MhSRIWLFggOspDHTt2DJIk4YMPPqjyv6mJVqtFw4YNcfPmTdnWSEtLgyRJaNSokWxrKI1n2fi4ublVnDflkpaWhiZNmsh2fBF4lo1P48aNZT0nc79QnjnOMfeL2uFZNj7cL2qHZ9n4VNUvHtiMyMzMRFlZGVxcXGQP9igxMTGQJAkff/yx6ChMBs7OzsjIyJDt+BkZGWjQoAEsLCxkW6O6eJbVq/xcKfcsOzs7y3b8muBZVi+5z8ncL5hSuF8wNeB+wdSiqnPyA2fR8i80lsE0V506dZL9TtCiubi4yH6CNYbSa+7UPsvl50q5Z7lr166yHZ9VjznMstxzXL4OE0ftcwxwvzAXap9l7hfmwxxmubI5fuCdEXfu3AEAODk5yZuKmT25i++dO3d4jpnsHB0dodFoeJaZyXNxcUFmZib0er0sx+d+wZTC/YKpAfcLphZV9YsHNiPy8/MBAHZ2dvInq8LHH3+Mnj17AgDee+89SJJU8avc/v378eyzz6J169awsrKCq6srnnrqKcTGxlZrjYSEBLRo0QJubm44cuQIAICIsGLFCvTo0QP169eHjY0NAgICsGjRohrvWJWVleHrr79Gx44d4ejoiAYNGqBTp0748ssvK77Planss0NEhB9++AG9evVCgwYNUL9+fXTu3BlLly5FaWnpP77OUK9DLra2tigoKJDt+Pn5+cLnGOBZVvssazQaWFtbP/L7UBf5+fmwtbWV7fjVxbOs7lm2tbWFXq9HYWGhLMfnfsFzrBTuFzzLaphl7hc8y2qZ5Sr7Bd0nKiqKAFB2dvb9v6WoOXPmEICH/iKgzEgbAAAgAElEQVQiunHjRqW/b2FhQfv27as4Vvlrmj9/fsV/i4yMpPr165Ovry+lpqYSEZFer6dnn3220uNOnDixRq9h5syZlR7r66+/rvi6uLg4AkCzZ8+u8r/p9XoaPXp0pcfcuXOnLK9DLpMmTaIBAwbIdvzx48dTaGiobMevLp5l9c+yo6Mjff/997Id397enpYtWybb8auLZ1nds7xz504CQHfv3pXl+NwveI6Vwv2CZ1kts8z9gmdZDbNcRb84+sA7I4qLiwEAlpaW9/+Wot59910cOHAAADBnzhwQUcUvAJAkCQMGDMBvv/2Gq1evori4GDdv3kRERASsrKwwd+7cSo/91VdfYfDgwQgODsbBgwfRokULAMDq1auxZs0a+Pn5Yfv27cjIyEBubi727duHgIAALF26FIcOHar2a9iyZQvs7OywefNmZGZmIi8vDydPnsSbb76JevXq1fh7smLFCmzYsAHOzs5YvHgxrly5gtzcXMTFxWHChAnQ6XSyvA65WFpayvq4oqKiIuFzDPAsPwzPcs3wLPMsK8HKygoAZJtl7hc8x0rhczLPMs9y9fAs8ywrocp+cf/2xMaNGwkAlZWVybExUiMHDhwgADRnzpyH/v6xY8do5MiR1KRJE7KwsPjHLlCzZs0qvq58h+zzzz+nqVOnEgB65ZVXqLS09B/He/zxx0mr1dL169cfWCsxMZEA0KxZs6qd//HHHycvLy8qKSmp8uuqu0PWs2fPf+yEVbWuIV+HXGbMmEFdu3aV7fijR4+m4cOHy3b8muBZVvcsu7u707x582Q7vkajofXr18t2/JrgWVbvLB8+fJgAVFw1MjTuFzzHSuF+8T88y5WvawqzzP3if3iWK1/X2Ge5in5x9IGnaWi1WgD3ngeu0TzwxgmjcfDgQTz++OMVV1ru97DPCs6ZMwfZ2dl4++238cknnzzw+4mJiSgrK0Pz5s0B4B87cuX/e+XKlWpnnD9/PoYPH47WrVsjJCQEAQEB6N69O9q3b1/tY/zduXPn4OjoiP79+1f5dYZ+HXIpKyurmDc5aDQa2W7EZkg8y5UzlVkuLS2VfZbLyspkO76h8CxXzhRmuXzG5HpcIfcLnmOlcL+4h2e5cqYyy9wv7uFZrpwpzHJV/eKBNlD+Vp3K/rCNxdy5c1FcXIzZs2fj4sWLKCgogF6vBxGhbdu2D/3/hIWFwcnJCStWrMCpU6ce+P3yf1jKyspQVlZWcbzyP0igZt+XgIAAnDt3Dj/++CM8PT1x4MABhIaGwsfHBwkJCTV8xdVn6Nchl+Li4oq37cjBysrKKF7no/AsV45n+R6eZZ5lJZS/fVKuWeZ+wXOsFD4n38OzXDme5Xt4lnmWlVBVv3hgM6L8i0SHBlBx5eTvdwstd+nSJTRq1AgffPABWrVqBWtra0iShOTkZFy4cOGhx+vcuTP2798PrVaL3r17IyYm5h+/7+3tDVtbW2RmZv7js0p//7Vp06YavQYLCwv06tULb731FtatW4eUlBRkZ2dj/PjxNTpOeb67d+9i9+7dj/w6Q78OORQVFcl6grW0tDSKOQZ4lu/Hs1wzPMs8y0oonzG5Zpn7Bc+xUvicfA/PctVfx7PMs8yzrIyq+kWlmxFyPdqrJsqfe3vgwIEHnrHr7u6OW7du4ZtvvkFWVhaysrKwfft2PPHEE1W+dc7HxwexsbFwdXXFwIEDsX379orfGz9+PPLz89G/f39s27YNt2/fRnFxMS5fvozIyEgMHz78kQPxdz169MDixYtx5swZFBQUICsrC9HR0cjIyMClS5dq+N0AXnjhBQDA2LFjsXTpUly7dg15eXn4888/MWnSJOzbt0+W1yEXuU+wVlZWRjHHAM/y/XiWa8ba2lrWG1jVBM/yP6lpluV+ZwT3C55jpXC/uIdnmWf5Ubhf8Cwrocp+QfeJj48nAHT27Nn7f0txpaWl1LRp03/coKQ88pYtWx747wCoffv25OvrS87OzhXHedgjXtLS0igwMJB0Oh2tWbOGiO49GiU8PPyhxy3/FRUVVe38VlZWlR5n+vTpFV9X3RuZlJWV0YgRIyo95t8f8WLI1yGXJ554gsLDw2U7/nvvvUd+fn6yHb8meJbVO8u5ubkEgCIjI2Vbw9vbmz788EPZjl8TPMvqneWVK1eSra2tbMfnfsFzrBTuFzzLaphl7hc8y2qZ5Sr6xYOP9nR2dgaAB3akRNBqtdi0aROCg4NhZ2f3j98bMmQI1qxZA39/f9jY2KBx48aYPHkydu/eXa0dxEaNGmHv3r3o1q0bnnvuOSxatAiSJGHlypXYsGED+vfvD0dHR1haWqJly5YYOnQofvnll0feROTvjhw5gpdffhnt2rWDjY0NXFxcEBQUhGXLlmH+/Pk1/n5oNBpERETg+++/R7du3WBnZwd7e3t06dIFy5YtQ58+fQDA4K9DLunp6RXzJgdnZ2ekp6fLdvya4Fn+JzXNcvm5Uu5ZNoZzMsCzfD+1zbLcc1y+jmg8x/+kpjkGuF+U41k27VnmfvE/PMumP8uVzbFE9Le7W+De2yisra2xZcsWDBkyRJGAzDy1bt0a48ePx9tvvy3L8VevXo3x48ejsLAQkiTJsgZjx48fR8eOHXHhwgW0bt1aljWGDh2KevXqYfXq1bIcnzEAeOeddxAdHY3jx4/LcnzuF0wp3C+YGnC/YGpRRb+Ie+g9I+rXr280O75MveS+cuHi4oLi4mJkZ2fLtgZj5edKua9c3L59W7bjMwbcm+Xyz+zKgfsFUwr3C6YG3C+YWlTVLx76oO9mzZoJfx6psTp58iQkSXrkr6FDh4qOatTKbz7j7u4u2xrlz9vlWX44nmXDuHz5MurXrw9HR0fZ1mjevDnPcRV4lg3j8uXLsp6TAe4XVeE5NgzuF+LxLBsG9wvxeJYNo6p+8dDNCE9PT6SkpMgaipm38vny9PSUbQ0PDw8AQGpqqmxrMJaamloxa3Lx8PBAamoq7vtUHWMGlZKSIus5GeB+weTH/YKpBfcLphZV9QuLh/1HDw8PJCQkyBrKVAUGBvJfWANISUmBJElo0aKFbGvY2dnB1dWVi28leJYNQ6kf4AoLC5GWlobGjRvLupYp4lmuO71ejytXrsg+y9wvKsdzbBjcL8TjWTYM7hfi8SzX3aP6xUPfGdGyZUskJyfLGoyZt+TkZDRu3BjW1tayrsOzzOR26dIlRcoCAJ5lJptr166hqKhI9qtwfE5mcuN+wdSC+wVTg0f1i4duRvj4+OD69et8kykmm4SEBPj5+cm+jq+vL06fPi37Osw86fV6JCYmwtfXV9Z1mjdvjgYNGvAVZSabhIQESJIk+yxzv2By437B1ID7BVOLR/WLh25G+Pv7V/yfGZODUmXBz88P8fHxsq/DzNOlS5eQm5tbcc6US/lJnM/JTC7x8fEVpVRO3C+Y3LhfMDXgfsHU4lH94qGbEU2aNIGrqysPJpNFaWkpzp49q0hZ8Pf3R3p6Om7cuCH7Wsz8JCQkQKPRoF27drKv5e/vz8WXySYhIUH20gtwv2Dy4n7B1IL7BVOLR/WLh25GAEBAQACOHz8uSyhm3s6ePYvCwkIEBATIvlZAQAAkSeJZZrI4ceIEWrdujXr16sm+VkBAAOLj41FWVib7Wsz8nDhxQpFzMsD9gsmH+wVTC+4XTC0e1S8q3Yzo3r07Dh48KEsoZt5iYmJgb28v++fgAMDJyQlt27blWWayiImJQVBQkCJr9ejRAzk5OXz1ghlceno6zp8/jx49eiiyHvcLJhfuF0wtuF8wNahOv6h0MyIoKAgXLlxAWlqaLOGY+YqNjUX37t2h1WoVWS8oKAixsbGKrMXMR2lpKeLi4hQrCz4+PnBycuLiywyu/PzYrVs3RdbjfsHkwv2CqQH3C6YW1ekXlW5GdOvWDRqNBocPHzZ8MmbWYmNjFbsCB9wrC3FxcSgpKVFsTaZ+J0+eRG5urmKzLEkSunbtysWXGdzBgwcryqgSuF8wuXC/YGrA/YKpRXX6RaWbEQ4ODggMDMTu3btlCcfMU3JyMlJTU9G7d2/F1uzVqxfy8/N5x5cZ1K5du9CoUSN4e3srtmbv3r2xZ88eEJFiazL12717N3r16qXYetwvmBy4XzC14H7B1KI6/aLSzQgACA0NRWRkpEFDMfMWFRUFe3t7Ra9ctGrVCl5eXtixY4diazL1i4qKQkhICCRJUmzNkJAQpKWl4cSJE4qtydTt1q1bOHHiBAYNGqToutwvmKFxv2Bqwf2CqUF1+8UjNyNSUlJw8eJFg4Zj5is6Ohr9+/eHTqdTdN3Q0FBERUUpuiZTr+zsbBw6dAihoaGKrhsQEIAmTZogOjpa0XWZekVFRcHCwgJ9+vRRdF3uF8zQuF8wNeB+wdSiuv2iys2I7t27o0GDBnz1ghlEQUEB9u7dq/gJFgAGDRqEU6dO4a+//lJ8baY+O3fuhF6vx8CBAxVdV5IkhISE8DmZGUxUVBR69eqlyOPj/o77BTMk7hdMLbhfMLWobr+ocjPCwsICYWFh2LRpk0HDMfMUGRmJgoICPPnkk4qv3bdvX9jb2/MsM4OIiIhAz5494ezsrPjaQ4cOxaFDh3DlyhXF12bqkp+fj8jISAwbNkzxtblfMEPifsHUgvsFU4Oa9IsqNyMAYNSoUYiNjeXBZHUWERGBPn36oEmTJoqvbWVlhcGDByMiIkLxtZm6lJ9gR48eLWT90NBQNGjQAD///LOQ9Zl6lP8AN3z4cCHrc79ghsL9gqkB9wumFjXpF4/cjAgJCUGDBg2wefNmg4Rj5ik/Px/bt28XdoIF7hXfQ4cO4fLly8IyMNO3bds2FBYW4umnnxayvqWlJRdfZhDlP8A1atRIyPrcL5ghcL9gasH9gqlFTfrFIzcjLC0tMXToUKxevdog4Zh5+vnnn1FSUiLsBAsAAwcOhKOjI9atWycsAzN9a9asQb9+/dCwYUNhGUaPHo3Dhw/zzf9YrWVmZiIyMhJjxowRloH7BTME7hdMLbhfMDWoab945GYEAPzrX//C8ePHcfz48TqFY+Zr6dKlGDx4MFxcXIRlsLS0xHPPPYelS5dCr9cLy8FMV1paGqKiovCvf/1LaI6QkBA0b94cy5cvF5qDma41a9ZAo9Fg1KhRQnNwv2B1xf2CqQH3C6YWNe0X1dqMCA4ORrt27bB06dI6hWPmKSkpCQcOHMD48eNFR8HEiRNx6dIl7N27V3QUZoKWL18Oe3t7DB06VGgOjUaD8PBwrFy5EiUlJUKzMNO0fPlyjB49Gvb29kJzcL9gdcH9gqkF9wumFjXtF9XajACA8ePHY+3atcjNza11OGaeli5diubNmyv+mKKH8fX1Rffu3fH999+LjsJMjF6vx4oVKzBu3DhYWVmJjoPx48fj9u3b+PXXX0VHYSYmLi4OJ06cMIof4ADuF6z2uF8wNeB+wdSiNv2i2psR4eHhKCsr47ftsBrJycnBsmXLMHnyZGg01R43Wb300kvYvHkz38Gd1ciWLVuQmpqKKVOmiI4CAHB3d0dYWBgWLFggOgozMfPnz0dgYCB69OghOgoA7hesdrhfMLXgfsHUojb9otpnbycnJ7z44otYsGABSktLaxWQmZ+lS5eipKQEkydPFh2lwujRo9GkSRMsXLhQdBRmQubNm4fBgwejbdu2oqNUeOONNxAbG4tDhw6JjsJMxOXLl7Fx40a8+eaboqNU4H7BaoP7BVML7hdMDWrbL2q0lTxjxgxcvXqVnz/LqqW0tBRfffUVJkyYAGdnZ9FxKuh0OrzyyitYunQpMjMzRcdhJqD8H2Rj+gEOAHr16oWuXbviyy+/FB2FmYj58+fDzc1N+I0r78f9gtUE9wumFtwvmFrUtl/UaDPC09MTw4YNw6effgoiqtFCzPz89NNPuH79Ol599VXRUR4wadIkaDQafPPNN6KjMBPw3//+F927d0dQUJDoKA9444038Msvv+DMmTOiozAjd/PmTSxbtgwzZsyATqcTHecfuF+wmuB+wdSC+wVTg7r0C4lq+K9+YmIi/P39sWHDBowYMaJGizHzUVJSAm9vb/Tr189ob+b0wQcfYMGCBUhJSYGjo6PoOMxIHTp0CD169MDvv/+OAQMGiI7zAL1ejw4dOqBNmzaIiIgQHYcZsRkzZmDdunVITk6Gra2t6DgP4H7BqoP7BVML7hdMLerQL+JqvBkBAGPGjEFCQgISEhKM5qZBzLgsWbIE06ZNw/nz5+Hp6Sk6zkNlZWWhZcuWePnll/HRRx+JjsOMVP/+/VFYWIiYmBjRUSr1888/Y8SIETh+/DgCAwNFx2FG6MaNG2jdujU+/fRTTJ8+XXScSnG/YI/C/YKpBfcLpgZ17Be124w4d+4cfH19sXz5crzwwgs1/b8zlcvPz0fbtm0xePBgLFq0SHScKn366af49NNPceHCBTRq1Eh0HGZkdu/ejf79+2PPnj3o06eP6DiVIiJ06tQJjRs3xrZt20THYUZoypQpiIyMxIULF2BtbS06TqW4X7CqcL9gasH9gqlFHftF7TYjyhfesmULkpKSYG9vX5tDMJWaPXs25s+fj/Pnz6Nx48ai41SpoKAAjz32GPr3749ly5aJjsOMSFlZGTp06IAWLVpg69atouM80p49e9C3b19ERUUhNDRUdBxmRBITExEYGIjly5fj+eefFx3nkbhfsMpwv2BqwP2CqYUB+kXtNyPu3LkDLy8vTJ06FR9//HFtDsFU6Nq1a2jbti0+/PBDo7szcGXWrl2LcePG4fDhw+jcubPoOMxIfPvtt3j99deRkJCANm3aiI5TLcOGDcP58+dx6tQpo7tBIRNn4MCBuHPnDo4ePWoSH33gfsEehvsFUwvuF0wtDNAvar8ZAQBffvkl/vOf/+D06dNo1apVbQ/DVGT06NE4ceIETp8+DUtLS9FxqoWIEBwcDI1Gg/3790OSJNGRmGAZGRnw9vbGCy+8gHnz5omOU23Jycnw8fHB3Llz8dprr4mOw4zA5s2bMXLkSMTGxqJ79+6i41Qb9wt2P+4XTA24XzC1MFC/qNtmRElJCTp06AA3Nzf8/vvvfJI1c5GRkQgLC8P27dsxaNAg0XFq5Pjx4+jatSu++eYbTJ48WXQcJlh4eDh27dqFxMREODg4iI5TI++99x4WLFiAxMREuLu7i47DBMrKykK7du0QEhKCFStWiI5TI9wv2N9xv2Bqwf2CqYEB+0XdNiMA4OjRo+jRoweWLVuG8PDwuhyKmbC8vDz4+fmhe/fuWLNmjeg4tfLvf/8bS5YsQWJiIpo1ayY6DhNkz5496NevHzZv3oxhw4aJjlNjRUVFFZ9F3b59u+g4TKApU6Zg8+bNOHv2LFxcXETHqTHuFwzgfsHUg/sFUwsD9ou6b0YAwKuvvorVq1cjMTERbm5udT0cM0HTpk3DunXrcObMGTRs2FB0nFrJz8+Hv78/fH19sWXLFtFxmAB5eXkICAhAQEAANm/eLDpOrR04cAB9+vTBqlWr8Nxzz4mOwwTYt28fHn/8caxduxZjxowRHafWuF8w7hdMDbhfMLUwcL8wzGZEbm4uAgIC0KZNG2zfvp3fTmlmduzYgUGDBuGnn37Cs88+KzpOnezduxf9+vXD999/j/Hjx4uOwxQ2ceJE/PLLL0hISDD6O7U/yrRp07B69WqcOnWK305pZjIzMxEYGIjAwECT/8GH+4V5437B1IL7BVMDGfqFYTYjACAuLg5BQUGYN28epk+fbohDMhNw+/ZtBAQEIDg4GBEREaLjGMSsWbOwaNEi/Pnnn2jbtq3oOEwhv/zyC55++mls2LABo0aNEh2nzgoLC9GlSxc4ODhg79690Gq1oiMxhTz77LPYtWsX4uPj0ahRI9Fx6oz7hXnifsHUgvsFUwsZ+kUcyIA+/PBDsra2plOnThnysMxI6fV6CgsLoxYtWlBmZqboOAZTVFREHTp0oM6dO1NRUZHoOEwBV69eJWdnZ5o4caLoKAZ18uRJsrKyoo8//lh0FKaQVatWkSRJFB0dLTqKQXG/MC/cL5hacL9gaiFTvzhq0M2I0tJS6tWrF7Vu3Zru3r1ryEMzI/TJJ5+QTqejmJgY0VEM7ty5c1S/fn2aOnWq6ChMZoWFhdS1a1dq164d5ebmio5jcAsWLCCtVks7d+4UHYXJ7NSpU2Rra0tvvPGG6CgGx/3CvHC/YGrA/YKphYz9wrCbEUREaWlp1LRpUwoLC6OysjJDH54ZiV27dpFWq6WFCxeKjiKbLVu2kCRJtHz5ctFRmIwmT55M9evXp8TERNFRZPP888+Tk5MTXbp0SXQUJpO7d+9S69atKSgoiIqLi0XHkQX3C/PA/YKpBfcLpgYy9wvDb0YQEcXExJBOp6MPPvhAjsMzwS5dukQuLi70zDPPiI4iu5kzZ5KNjQ0dO3ZMdBQmg2XLlpEkSfTzzz+LjiKr3Nxc8vX1pU6dOlFeXp7oOMzASktL6cknn6SmTZtSWlqa6Diy4n6hbtwvmFpwv2BqoEC/kGczgojou+++I0mSaPXq1XItwQS4c+cOeXt7U4cOHVT5lrP7lZSU0MCBA6lx48Z0+fJl0XGYAe3atYt0Oh29++67oqMoIikpiZydnWnYsGF8VVllpk2bRjY2NnT48GHRURTB/UKduF8wteB+wdRCgX4h32YEEdEbb7xBOp2Odu/eLecyTCHFxcXUr18/atq0KV29elV0HMVkZ2dTQEAAtWvXjj+rrBKJiYnUoEEDGjVqFOn1etFxFLN//36ysrKiGTNmiI7CDOSLL74gSZJozZo1oqMoivuFunC/4H6hFtwvuF+ohUL9Qt7NiLKyMhoxYgQ5OTlRfHy8nEsxmZWWltKYMWPIwcGBEhISRMdR3JUrV6hJkybUt29fKigoEB2H1cGVK1fI3d2devXqRYWFhaLjKG7t2rUkSRLNnz9fdBRWRxs2bCCNRkOff/656CiK436hHtwvuF+oBfcL7hdqoWC/kHczgogoPz+fevfuTW5ubnT+/Hm5l2My0Ov1NGHCBLK2tqY//vhDdBxhTp48SY6OjhQWFqbaG8SpXVpaGrVp04b8/PwoIyNDdBxh5s2bR5Ik0ffffy86Cqul3377jXQ6Hb322muiowjD/cL0cb+4h/uF6eN+cQ/3C9OncL+QfzOC6N7NTYKDg6lZs2Z8t1UTNHPmTNLpdLR161bRUYQ7fPgw1a9fn55++mkqKSkRHYfVwN27d6l9+/bUunVrun79uug4ws2ePZs0Gg1/7t4E/fHHH2RtbU0vvPCCWb0N+GG4X5g27hf/w/3CdHG/+CfuF6ZLQL9QZjOC6N6NiQICAsjDw4MuXryo1LKsDvR6Pb322muk1Wppw4YNouMYjT179pCNjQ2NGjWKr2CYiJs3b1JgYCC1aNGCrly5IjqO0XjzzTfJwsKCfvzxR9FRWDX9/vvvZGdnR2PHjqXS0lLRcYwC9wvTw/3i4bhfmB7uFw/H/cL0COoXym1GEN0rDF27diU3Nzf+jKeRKy0tpQkTJpBOp+Oi8BD79u0je3t7evLJJyk/P190HFaF69evk6+vL3l6evIPKg/x/vvvkyRJtHDhQtFR2CP89ttvZG1tTc888wxfOb0P9wvTwf2iatwvTAf3i6pxvzAdAvuFspsRRESZmZkUHBxMrq6uFBcXp/TyrBoKCwtpzJgxZG1tTb/99pvoOEbr0KFD5OjoSP369aOsrCzRcdhDJCUlkaenJ7Vr147fOlmFOXPmkCRJ9Nlnn4mOwirx448/koWFBU2ZMoUfnVYJ7hfGj/tF9XC/MH7cL6qH+4XxE9wvlN+MILr3Gc/Q0FCys7OjX3/9VUQEVomMjAzq3bs3OTg4mPXNpKrrxIkT1LhxY/L39zerx5GZgpiYGHJxcaEuXbrQ7du3RccxegsWLCCNRkMvvfQSv/3fyHz00UckSRLNmjXL7O8R8SjcL4wX94ua4X5hvLhf1Az3C+NlBP1CzGYEEVFJSQlNnDiRtFotffXVV6JisL9JTk4mb29vat68Ob/NtQZSU1PJx8eHmjZtSidOnBAdhxHR+vXrydramoYMGUJ5eXmi45iMzZs3k42NDT355JOUk5MjOo7ZKy4upvDwcLKwsKDvvvtOdByTwf3C+HC/qB3uF8aH+0XtcL8wLkbUL8RtRpT75JNPSJIkmjBhAj9fWaAdO3aQs7MztW/fnv766y/RcUzO3bt3qV+/fmRnZ0dr164VHcdslZaW0ttvv02SJNH06dN5B74WDh06RA0bNiRfX19KSkoSHcdsXb9+nYKCgqhevXoUGRkpOo5J4n5hHLhf1A33C+PA/aLuuF8YByPrF+I3I4iItm3bRg0aNKD27dvzo7kUptfrae7cuaTVamns2LGUm5srOpLJKikpoVmzZhEAmjRpEt8JW2Hp6ek0cOBAsrKy4udb19HVq1epa9euVL9+fdq0aZPoOGbnwIED1LhxY/Ly8uKryHXE/UIc7heGw/1CLO4XhsP9Qiwj7BfGsRlBRHT+/Hny8fEhFxcX/pynQm7dukVhYWGk0+lowYIFouOoxpo1a8jOzo6CgoIoJSVFdByzcODAAWrRogW5u7vzjesMpKCggMaPH0+SJNHMmTOpqKhIdCTVKysro//7v/8jnU5HQ4YMoczMTNGRVIH7hfK4X8iD+4XyuF8YHvcL5RlxvzCezQgiopycHAoPDycANGXKFP4sloyio6PJzc2NWrRoQTExMaLjqE5CQgL5+vqSg4MDrV69WnQc1SopKaF3332XtFotPfXUU3wjKRmsWLGC6tWrR+3bt6ezZ8+KjqNaV69epccff5wsLS3ps88+4xtVGhj3C+Vwv5AX9wtlcL+QH/cLZRh5vzCuzYhyGzZsIEdHR/L29qbY2FjRcVQlOzubXnnlFZIkicaOHWtMO2OqU1BQQNOmTSNJkmjMmNszFk8AAAtASURBVDF069Yt0ZFU5fTp09S1a1eysbGhb7/91thOrqqSlJREXbp0IVtbW1q4cCE/WtLAfvrpJ3JyciJvb2/6888/RcdRNe4X8uF+oRzuF/LifqEc7hfyMoF+YZybEUREV65coYEDB5JGo6FXXnmFsrOzRUcyeb/99hu5u7uTs7Mz76YrKCoqipo3b04uLi70448/io5j8goLC+n9998nS0tL6tKlC505c0Z0JLNQXFxM77//Pul0OuratSslJCSIjmTyUlJSKCQkhDQaDb388st8tV4h3C8Mj/uFGNwvDIv7hRjcLwzPhPqF8W5GlFu1ahU5OztT8+bNKSIiQnQck3T58mUaOXIkAaBnnnmGbt68KTqS2cnOzqaXX36ZNBoNDRgwgP+Bq6Xff/+dvL29qV69ejR//ny+m7UACQkJ1LVrV9LpdPTWW2/xD3K1UFhYSHPnziU7Oztq164dv5VdEO4Xdcf9QjzuF4bB/UI87hd1Z4L9wvg3I4ju3QjphRdeIEmSqFevXnT8+HHRkUxCXl4ezZ49m2xtbal169a0fft20ZHMXmxsLAUGBpJOp6Pp06fTnTt3REcyCRcuXKDBgwcTABoyZAilpqaKjmTWysrK6KuvviJHR0dq3LgxrVy5kt9aWU2//PILtWrVimxtbemjjz7iG3cJxv2idrhfGB/uF7XD/cK4cL+oPRPtF6axGVHuyJEj1K1bN9JoNPT8889TcnKy6EhGqbi4mJYsWULNmjUje3t7+uyzz0xlIM1CaWkpLVmyhBo2bEjOzs702WefGfPbp4S6fv06TZs2jSwtLcnX15d27twpOhL7m9u3b9PUqVNJq9VSx44djeF51UYrJiaG+vTpU/F5+itXroiOxP6G+0X1cL8wbtwvqo/7hXHjflF9Jt4vTGszgujec6vXrl1LXl5epNPpaOLEibyL+f+VlJTQihUryNPTkywtLemll16itLQ00bFYJTIzM+mtt94iOzs7cnNzowULFlBBQYHoWEbh5s2b9MYbb5CNjQ01bdqUvvvuOyopKREdi1UiPj6ennrqKQJA3bt351L3N4cPH6aQkBACQL179+abJhox7heV435hWrhfVI77hWnhflE5lfQL09uMKFdWVkYRERHUunVr0mg0FBYWRocPHxYdS4icnBxasGABtWjRgnQ6HY0bN44uXrwoOharptu3b9OsWbPI1taWXF1dadasWXT9+nXRsYRITk6m6dOnV3wv5s6dS/n5+aJjsWo6cuQIhYWFEQBq3749rVq1ymxL3oEDByq+F926daOtW7eKjsSqifvF/3C/MG3cL/6H+4Vp437xPyrrF6a7GVGuuLiYVq1aRf7+/gSA+vXrR5s3b6bi4mLR0WR3/vx5mjlzJjVo0IDq1atH06dPp5SUFNGxWC3duHGD3nnnHXJyciJbW1uaMmWKWXx+uaysjHbs2EFDhw4ljUZDrVq1okWLFvFbS03Y4cOHacSIEaTVasnDw4M+//xzs3j0XGZmJn333Xfk4+NDkiRRaGgoX8UxYdwvuF+oBfcL7hdqwf1Cdf3C9Dcjyun1etqxYwcNGjSINBoNNWrUiGbNmkXnzp0THc2gcnNz6ccff6RevXqRJEnk7u5On3zyCd+oSEVyc3Pp66+/Jm9vbwJAnTp1osWLF9Pdu3dFRzOo1NRU+vDDD6lFixYEgHr27EmbNm3iGxWpSHJyMk2bNo0cHBzI0tKSRo4cSTt27FDVXcr1ej0dOHCAwsPDydbWlmxtbenFF1+k+Ph40dGYgXC/4H6hFtwvuF+oBfcL1VDPZsTf/fXXXzR37lzy9PQkANSuXTuaPXs2nT9/XnS0WikoKKCtW7fSuHHjqF69eqTVaql///4UERFhtm9RMhfHjh2jSZMmkZ2dXcWf+6pVqygzM1N0tFq5du0aLViwgIKCgkiSJHJ0dKRJkyap7cTK7lNQUEARERHUv39/kiSJnJ2dady4cbR161aTPYedPn2aZs+eTa1atar4d2bu3LmUnp4uOhqTEfcLphbcL5gacL8weUclIiKolF6vx759+xAREYHNmzfj9u3b8PHxwaBBgxAaGoqePXvC0tJSdMyHSk5ORnR0NKKiorBnzx4UFRWhd+/eGDVqFIYPHw4XFxfREZmCsrOz8euvv2LDhg3YuXMnJElCcHBwxSz7+PiIjvhQZWVlOHz4cMUsnzhxAvXr18eQIUMwevRoDBgwADqdTnRMpqCLFy9iw4YNiIiIQHx8PFxdXRESEoJBgwZh4MCBRntuy8rKwq5duxAdHY3o6Ghcu3YNXl5eGD16NEaNGgU/Pz/REZmCuF8wteB+wdSC+4VJilP1ZsTflZaWYu/evYiKikJUVBTOnj0LOzs7dOnSBcHBwejRowe6deuGBg0aCMl29uxZxMTE4ODBg4iJiUFqairs7e3Rv39/hIaG4qmnnoKbm5vi2ZjxuXv3LrZt24aoqCj8/vvvyMjIQJMmTRAUFFTxy9/fX0gRzs3NxbFjxxATE4PY2FgcPHgQ2dnZ8PT0RGhoKJ544gkMGDAAVlZWimdjxufcuXPYunUroqOjERMTg7KyMvj4+FSck3v06IGWLVsKyfbXX3/h4MGDiI2NRWxsLE6ePAkiQpcuXTBo0CCEhYWhffv2QrIx48L9gqkF9wumFtwvTIb5bEbcLzU1Fbt37674BzopKQkA4O7uDj8/P/j5+cHb2xuenp7w8PBA06ZNodVq67RmVlYWUlJSkJKSguTkZJw+fRoJCQk4c+YMCgsLUb9+fXTv3h1BQUHo3bs3evTowbu6rEplZWU4duwY9uzZg9jYWBw6dAgZGRnQ6XTw9vaGr68v/P390apVK3h6esLT0xPOzs51WpOIcOPGjYpZTkpKQkJCAhISEnDp0iUQEdzd3StO+P3790fbtm0N9IqZWuXk5GDPnj3Yv38/Dh48iD///BPFxcVwcHCAn58ffH194efnBw8Pj4pZtra2rtOaRUVFuHz5MlJTU5GSkoIzZ84gISEB8fHxyMjIgIWFBfz9/REcHIzg4GD069cPTk5OBnrFTK24XzA14H7B1IL7hVEz382I+926dQvHjh1DQkICTp06hdOnT+PChQsoLCwEAOh0OjRs2BDOzs4Vv+zt7WFhYQGtVgt7e3sUFxcjLy8PwL3Bz87ORkZGBjIyMpCWloacnJyK9Zo2bYp27dohICAAvr6+CAwMhK+vb50LCTNvRIRz587h5MmTiI+PR3x8PBITE3H16lXo9XoAgJ2dHRo2bAhXV9eKOXZwcAAA2NjYwNraGrm5uSgpKYFer0dWVhbu3r2L9PR0ZGRk4NatWygqKgIAWFpawtPTE/7+/hUlu1OnTmjWrJmw7wFTh4KCApw4cQLx8fE4deoUEhIScPbsWdy5c6fia8pnuPyXg4MDbGxsAAAODg7QaDS4e/cugHvFICsrq+KcnJGRgdu3b1f8vbC3t4e3tzf8/f0r5rlTp06oV6+e8i+eqQr3C6YG3C+YWnC/MCq8GfEo169fr9jVunXrFjIyMnDnzh1kZGQgJycHJSUlKC0tRU5ODnQ6XcVgOTg4oF69ehVD7OrqimbNmlVcCanrjhtjNVFcXIwrV64gJSUFV69erZjljIwM5ObmVpxQ8/PzUVRUBDs7O1haWlYU4QYNGsDFxaVilv9+RU+j0Qh+dcycZGVlVZyT//rrr3/845+bm1vxA1tWVhb0ej0cHR0B3CvCfz8nOzs7o0mTJhVXQsz0igQTiPsFUwPuF0wtuF8IwZsRjDHGGGOMMcYYU1QcbzkyxhhjjDHGGGNMUbwZwRhjjDHGGGOMMUXxZgRjjDHGGGOMMcYU9f8AogJYEE7YlZQAAAAASUVORK5CYII=",
"text/plain": [
"<IPython.core.display.Image object>"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"combined.X.visualize()"
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "a3cc32d9-07b5-4d20-87ad-4c2e1f55164e",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 369 ms, sys: 172 ms, total: 541 ms\n",
"Wall time: 540 ms\n"
]
}
],
"source": [
"%%time\n",
"combined.write_zarr(\"combined.zarr\")"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "7ffedac3-3365-43e0-9f08-5f9e14b570c2",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"CPU times: user 197 ms, sys: 135 ms, total: 333 ms\n",
"Wall time: 198 ms\n"
]
},
{
"data": {
"text/plain": [
"<17125x36601 sparse matrix of type '<class 'numpy.float32'>'\n",
"\twith 26550469 stored elements in Compressed Sparse Row format>"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%%time\n",
"result = combined.to_memory()\n",
"result.X"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "419f9575-d8c0-437b-880b-90b8e88f5b78",
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment