From 501ef5c18b935ea8e1c3999f76b3eb24fe3463b8 Mon Sep 17 00:00:00 2001 From: Nicolas Barascud <10333715+nbara@users.noreply.github.com> Date: Wed, 10 May 2023 15:59:33 +0200 Subject: [PATCH] [MAINT] Move to pyproject.toml (#68) --- Makefile | 40 ++++++---- README.md | 126 +++++++++++++++++--------------- citation.cff | 2 +- doc/_static/logo-dark.png | Bin 0 -> 133088 bytes doc/_static/logo.png | Bin 0 -> 143663 bytes doc/conf.py | 70 ++++++++++-------- doc/index.rst | 2 +- examples/config.py | 9 ++- examples/example_asr.py | 27 +++---- examples/example_dering.py | 11 +-- examples/example_detrend.py | 54 +++++++------- examples/example_dss.py | 16 ++-- examples/example_dss_line.py | 27 +++---- examples/example_mcca.py | 72 +++++++++--------- examples/example_ress.py | 35 ++++----- examples/example_star.py | 14 ++-- examples/example_star_dss.py | 27 ++++--- examples/example_trca.py | 27 +++---- meegkit/__init__.py | 8 +- meegkit/asr.py | 59 ++++++++------- meegkit/cca.py | 49 ++++++------- meegkit/detrend.py | 45 ++++++------ meegkit/dss.py | 46 +++++++----- meegkit/lof.py | 15 ++-- meegkit/ress.py | 2 +- meegkit/sns.py | 8 +- meegkit/star.py | 41 ++++++----- meegkit/trca.py | 24 +++--- meegkit/tspca.py | 15 +++- meegkit/utils/__init__.py | 63 ++++++++++++---- meegkit/utils/asr.py | 17 +++-- meegkit/utils/auditory.py | 2 +- meegkit/utils/base.py | 11 +-- meegkit/utils/covariances.py | 42 ++++++----- meegkit/utils/denoise.py | 37 +++++----- meegkit/utils/matrix.py | 46 ++++++------ meegkit/utils/sig.py | 56 +++++++------- meegkit/utils/stats.py | 27 ++++--- meegkit/utils/testing.py | 10 +-- meegkit/utils/trca.py | 9 +-- pyproject.toml | 137 +++++++++++++++++++++++++++++++++++ setup.cfg | 24 ------ setup.py | 27 +------ tests/conftest.py | 5 +- tests/test_asr.py | 105 ++++++++++++++------------- tests/test_cca.py | 112 ++++++++++++++-------------- tests/test_cov.py | 7 +- tests/test_detrend.py | 46 ++++++------ tests/test_dss.py | 43 ++++++----- tests/test_lof.py | 18 ++--- tests/test_ress.py | 65 +++++++++-------- tests/test_signal.py | 23 +++--- tests/test_sns.py | 12 +-- tests/test_star.py | 12 +-- tests/test_trca.py | 17 +++-- tests/test_tspca.py | 39 +++++----- tests/test_utils.py | 57 ++++++++++----- 57 files changed, 1077 insertions(+), 863 deletions(-) create mode 100644 doc/_static/logo-dark.png create mode 100644 doc/_static/logo.png create mode 100644 pyproject.toml delete mode 100644 setup.cfg diff --git a/Makefile b/Makefile index be7d4afa..5132ca7d 100644 --- a/Makefile +++ b/Makefile @@ -60,23 +60,32 @@ pydocstyle: @pydocstyle pep: - @$(MAKE) -k flake pydocstyle codespell-error - -flake: - @if command -v flake8 > /dev/null; then \ - echo "Running flake8"; \ - flake8 --count meegkit examples; \ - else \ - echo "flake8 not found, please install it!"; \ - exit 1; \ - fi; - @echo "flake8 passed" + @$(MAKE) -k ruff codespell -# Tests +ruff: + @ruff check $(CODESPELL_DIRS) + +ruff-fix: + @ruff check $(CODESPELL_DIRS) --fix + +# Build and install # ============================================================================= -# test: -# py.test tests +install-requirements: + @echo "Checking/Installing requirements..." + @pip install -q -r requirements.in + +install: + @echo "Installing package..." + @pip install -q --no-deps . + @echo "\x1b[1m\x1b[32m * Package successfully installed! \x1b[0m" + +install-dev: + @echo "Installing package in editable mode..." + @pip install -q -e ".[docs, tests]" --config-settings editable_mode=compat + @echo "\x1b[1m\x1b[32m * Package successfully installed! \x1b[0m" +# Tests +# ============================================================================= test: in rm -f .coverage $(PYTESTS) -m 'not ultraslowtest' meegkit @@ -94,3 +103,6 @@ test-full: in $(PYTESTS) meegkit .PHONY: init test + + + diff --git a/README.md b/README.md index d5dc75bd..809e023e 100644 --- a/README.md +++ b/README.md @@ -5,19 +5,23 @@ [![DOI](https://zenodo.org/badge/117451752.svg)](https://zenodo.org/badge/latestdoi/117451752) [![twitter](https://img.shields.io/twitter/follow/lebababa?style=flat&logo=Twitter)](https://twitter.com/intent/follow?screen_name=lebababa) -# MEEGkit +# `MEEGkit` -Denoising tools for M/EEG processing in Python 3.7+. +Denoising tools for M/EEG processing in Python 3.8+. ![meegkit-ERP](https://user-images.githubusercontent.com/10333715/176754293-eaa35071-94f8-40dd-a487-9f8103c92571.png) -> **Disclaimer:** The project mostly consists of development code, although some modules and functions are already working. Bugs and performance problems are to be expected, so use at your own risk. More tests and improvements will be added in the future. Comments and suggestions are welcome. +> **Disclaimer:** The project mostly consists of development code, although some modules +and functions are already working. Bugs and performance problems are to be expected, so +use at your own risk. More tests and improvements will be added in the future. Comments +and suggestions are welcome. ## Documentation Automatic documentation is [available online](https://nbara.github.io/python-meegkit/). -This code can also be tested directly from your browser using [Binder](https://mybinder.org), by clicking on the binder badge above. +This code can also be tested directly from your browser using +[Binder](https://mybinder.org), by clicking on the binder badge above. ## Installation @@ -27,18 +31,21 @@ This package can be installed easily using `pip`: pip install meegkit ``` -Or you can clone this repository and run the following commands inside the `python-meegkit` directory: +Or you can clone this repository and run the following commands inside the +`python-meegkit` directory: ```bash pip install -r requirements.txt pip install . ``` -*Note* : Use developer mode with the `-e` flag (`pip install -e .`) to be able to modify the sources even after install. +*Note* : Use developer mode with the `-e` flag (`pip install -e .`) to be able to modify +the sources even after install. ### Advanced installation instructions -Some ASR variants require additional dependencies such as `pymanopt`. To install meegkit with these optional packages, use: +Some ASR variants require additional dependencies such as `pymanopt`. To install meegkit +with these optional packages, use: ```bash pip install -e '.[extra]' @@ -50,90 +57,95 @@ or: pip install meegkit[extra] ``` -Other available options are `[docs]` (which installs dependencies required to build the documentation), or `[tests]` (which install dependencies to run unit tests). +Other available options are `[docs]` (which installs dependencies required to build the +documentation), or `[tests]` (which install dependencies to run unit tests). ## References -### 1. CCA, STAR, SNS, DSS, ZapLine, and Robust Detrending +If you use this code, you should cite the relevant methods from the original articles. -This is mostly a translation of Matlab code from the [NoiseTools toolbox](http://audition.ens.fr/adc/NoiseTools/) by Alain de Cheveigné. It builds on an initial python implementation by [Pedro Alcocer](https://github.com/pealco). +### 1. CCA, STAR, SNS, DSS, ZapLine, and Robust Detrending -Only CCA, SNS, DSS, STAR, ZapLine and robust detrending have been properly tested so far. TSCPA may give inaccurate results due to insufficient testing (contributions welcome!) +This is mostly a translation of Matlab code from the +[NoiseTools toolbox](http://audition.ens.fr/adc/NoiseTools/) by Alain de Cheveigné. +It builds on an initial python implementation by +[Pedro Alcocer](https://github.com/pealco). -If you use this code, you should cite the relevant methods from the original articles: +Only CCA, SNS, DSS, STAR, ZapLine and robust detrending have been properly tested so far. +TSCPA may give inaccurate results due to insufficient testing (contributions welcome!) ```sql -[1] de Cheveigné, A. (2019). ZapLine: A simple and effective method to remove power line artifacts. - NeuroImage, 116356. https://doi.org/10.1016/j.neuroimage.2019.116356 -[2] de Cheveigné, A. et al. (2019). Multiway canonical correlation analysis of brain data. - NeuroImage, 186, 728–740. https://doi.org/10.1016/j.neuroimage.2018.11.026 -[3] de Cheveigné, A. et al. (2018). Decoding the auditory brain with canonical component analysis. - NeuroImage, 172, 206–216. https://doi.org/10.1016/j.neuroimage.2018.01.033 -[4] de Cheveigné, A. (2016). Sparse time artifact removal. - Journal of Neuroscience Methods, 262, 14–20. https://doi.org/10.1016/j.jneumeth.2016.01.005 -[5] de Cheveigné, A., & Parra, L. C. (2014). Joint decorrelation, a versatile tool for multichannel - data analysis. NeuroImage, 98, 487–505. https://doi.org/10.1016/j.neuroimage.2014.05.068 -[6] de Cheveigné, A. (2012). Quadratic component analysis. - NeuroImage, 59(4), 3838–3844. https://doi.org/10.1016/j.neuroimage.2011.10.084 -[7] de Cheveigné, A. (2010). Time-shift denoising source separation. - Journal of Neuroscience Methods, 189(1), 113–120. https://doi.org/10.1016/j.jneumeth.2010.03.002 +[1] de Cheveigné, A. (2019). ZapLine: A simple and effective method to remove power line + artifacts. NeuroImage, 116356. https://doi.org/10.1016/j.neuroimage.2019.116356 +[2] de Cheveigné, A. et al. (2019). Multiway canonical correlation analysis of brain + data. NeuroImage, 186, 728–740. https://doi.org/10.1016/j.neuroimage.2018.11.026 +[3] de Cheveigné, A. et al. (2018). Decoding the auditory brain with canonical component + analysis. NeuroImage, 172, 206–216. https://doi.org/10.1016/j.neuroimage.2018.01.033 +[4] de Cheveigné, A. (2016). Sparse time artifact removal. Journal of Neuroscience + Methods, 262, 14–20. https://doi.org/10.1016/j.jneumeth.2016.01.005 +[5] de Cheveigné, A., & Parra, L. C. (2014). Joint decorrelation, a versatile tool for + multichannel data analysis. NeuroImage, 98, 487–505. + https://doi.org/10.1016/j.neuroimage.2014.05.068 +[6] de Cheveigné, A. (2012). Quadratic component analysis. NeuroImage, 59(4), 3838–3844. + https://doi.org/10.1016/j.neuroimage.2011.10.084 +[7] de Cheveigné, A. (2010). Time-shift denoising source separation. Journal of + Neuroscience Methods, 189(1), 113–120. https://doi.org/10.1016/j.jneumeth.2010.03.002 [8] de Cheveigné, A., & Simon, J. Z. (2008a). Denoising based on spatial filtering. - Journal of Neuroscience Methods, 171(2), 331–339. https://doi.org/10.1016/j.jneumeth.2008.03.015 -[9] de Cheveigné, A., & Simon, J. Z. (2008b). Sensor noise suppression. - Journal of Neuroscience Methods, 168(1), 195–202. https://doi.org/10.1016/j.jneumeth.2007.09.012 + Journal of Neuroscience Methods, 171(2), 331–339. + https://doi.org/10.1016/j.jneumeth.2008.03.015 +[9] de Cheveigné, A., & Simon, J. Z. (2008b). Sensor noise suppression. Journal of + Neuroscience Methods, 168(1), 195–202. https://doi.org/10.1016/j.jneumeth.2007.09.012 [10] de Cheveigné, A., & Simon, J. Z. (2007). Denoising based on time-shift PCA. - Journal of Neuroscience Methods, 165(2), 297–305. https://doi.org/10.1016/j.jneumeth.2007.06.003 + Journal of Neuroscience Methods, 165(2), 297–305. + https://doi.org/10.1016/j.jneumeth.2007.06.003 ``` ### 2. Artifact Subspace Reconstruction (ASR) -The base code is inspired from the original [EEGLAB inplementation](https://github.com/sccn/clean_rawdata) [1], while the riemannian variant [2] was adapted from the [rASR toolbox](https://github.com/s4rify/rASRMatlab) by Sarah Blum. - -If you use this code, you should cite the relevant methods from the original articles: +The base code is inspired from the original +[EEGLAB inplementation](https://github.com/sccn/clean_rawdata) [1], while the Riemannian +variant [2] was adapted from the [rASR toolbox](https://github.com/s4rify/rASRMatlab) by +Sarah Blum. ```sql -[1] Mullen, T. R., Kothe, C. A. E., Chi, Y. M., Ojeda, A., Kerth, T., Makeig, S., et al. (2015). - Real-time neuroimaging and cognitive monitoring using wearable dry EEG. IEEE Trans. Bio-Med. - Eng. 62, 2553–2567. https://doi.org/10.1109/TBME.2015.2481482 -[2] Blum, S., Jacobsen, N., Bleichner, M. G., & Debener, S. (2019). A Riemannian modification of - artifact subspace reconstruction for EEG artifact handling. Frontiers in human neuroscience, - 13, 141. +[1] Mullen, T. R., Kothe, C. A. E., Chi, Y. M., Ojeda, A., Kerth, T., Makeig, S., + et al. (2015). Real-time neuroimaging and cognitive monitoring using wearable dry + EEG. IEEE Trans. Bio-Med. Eng. 62, 2553–2567. + https://doi.org/10.1109/TBME.2015.2481482 +[2] Blum, S., Jacobsen, N., Bleichner, M. G., & Debener, S. (2019). A Riemannian + modification of artifact subspace reconstruction for EEG artifact handling. Frontiers + in human neuroscience, 13, 141. ``` ### 3. Rhythmic Entrainment Source Separation (RESS) The code is based on [Matlab code from Mike X. Cohen](https://mikexcohen.com/data/) [1] -If you use this, you should cite the following article: - ```sql -[1] Cohen, M. X., & Gulbinaite, R. (2017). Rhythmic entrainment source separation: Optimizing analyses - of neural responses to rhythmic sensory stimulation. Neuroimage, 147, 43-56. +[1] Cohen, M. X., & Gulbinaite, R. (2017). Rhythmic entrainment source separation: + Optimizing analyses of neural responses to rhythmic sensory stimulation. Neuroimage, + 147, 43-56. ``` ### 4. Task-Related Component Analysis (TRCA) -This code is based on the [Matlab implementation from Masaki Nakanishi](https://github.com/mnakanishi/TRCA-SSVEP), and was adapted to python by [Giuseppe Ferraro](mailto:giuseppe.ferraro@isae-supaero.fr) - -If you use this, you should cite the following articles: +This code is based on the [Matlab implementation from Masaki Nakanishi](https://github.com/mnakanishi/TRCA-SSVEP), +and was adapted to python by [Giuseppe Ferraro](mailto:giuseppe.ferraro@isae-supaero.fr) ```sql [1] M. Nakanishi, Y. Wang, X. Chen, Y.-T. Wang, X. Gao, and T.-P. Jung, - "Enhancing detection of SSVEPs for a high-speed brain speller using - task-related component analysis", IEEE Trans. Biomed. Eng, 65(1): 104-112, - 2018. -[2] X. Chen, Y. Wang, S. Gao, T. -P. Jung and X. Gao, "Filter bank - canonical correlation analysis for implementing a high-speed SSVEP-based - brain-computer interface", J. Neural Eng., 12: 046008, 2015. -[3] X. Chen, Y. Wang, M. Nakanishi, X. Gao, T. -P. Jung, S. Gao, - "High-speed spelling with a noninvasive brain-computer interface", - Proc. Int. Natl. Acad. Sci. U. S. A, 112(44): E6058-6067, 2015. + "Enhancing detection of SSVEPs for a high-speed brain speller using task-related + component analysis", IEEE Trans. Biomed. Eng, 65(1): 104-112, 2018. +[2] X. Chen, Y. Wang, S. Gao, T. -P. Jung and X. Gao, "Filter bank canonical correlation + analysis for implementing a high-speed SSVEP-based brain-computer interface", + J. Neural Eng., 12: 046008, 2015. +[3] X. Chen, Y. Wang, M. Nakanishi, X. Gao, T. -P. Jung, S. Gao, "High-speed spelling + with a noninvasive brain-computer interface", Proc. Int. Natl. Acad. Sci. U.S.A, + 112(44): E6058-6067, 2015. ``` ### 5. Local Outlier Factor (LOF) -If you use this, you should cite the following article: - ```sql [1] Breunig M, Kriegel HP, Ng RT, Sander J. 2000. LOF: identifying density-based local outliers. SIGMOD Rec. 29, 2, 93-104. https://doi.org/10.1145/335191.335388 diff --git a/citation.cff b/citation.cff index c2dec4cb..373edd39 100644 --- a/citation.cff +++ b/citation.cff @@ -5,7 +5,7 @@ authors: given-names: "Nicolas" orcid: "https://orcid.org/0000-0003-1495-561X" title: "MEEGkit" -version: 0.1.3 +version: 0.1.4 doi: 10.5281/zenodo.5643659 date-released: 2021-10-15 url: "https://github.com/nbara/python-meegkit" diff --git a/doc/_static/logo-dark.png b/doc/_static/logo-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..5d4f20701b4849e6eb5912249f64bb49cd73b151 GIT binary patch literal 133088 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%0DU_^Tiq&Z-sJNi$3QWB?AP_9MxxF1 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

?g{!wOc=`GdgJvd(V`Zz}H2xl63o87DN5t zjwubazglgFh+qOZTnjMM#iKf3{-A2tWUoCp@+llQ6COZb$2zuju&isT01p|%<#ZTi zPDw})#KhVw%MbmM!Os?@7Rw?xoG5p-l@ErG(qXWQXt6yhb`Y|`^uJ=)&5t3j@H%bi zL(PZk!owPSiBsG#o|p;L&3PSJExdM$8TATu*rvE{s9F1?$bGBQMN@d17ftg(_6LS6 z27?X97zSdVzWR8b)QdC3Jk&TaZW)&?e+ejcApM4<-bi77B}+q2BSS-lB zABxSS7G}Qh=hP%n^YlUTG0v$FG(YfI9m}=+=D+5DGTSS|A)PE0wglaN1PCFLPHt4> zU#s{i-#7kc#afk%Q*Ua21zbhb$eHZ5>$pK52npfNkkDivOzHl|4#7S1aCWtQ9%}yl z5C;!8Nr$?~(StxZ@?yn2ny#CyK5r~cQg1N`-lmquIITQ1P6aP_`C*C^qn2<2#^R|zsN zVrf`Y-lBrK9T~N`S}#?xx{E}h|F6CG{--+p|Hqxd*@UbkI|@lkw(PBt zV;!TAT|%-VJ7i{)jI#I0%F3SE^K+fk`~CX7KL5e@hp*f7c5eLOd9LevJg&!n+#iOk zoFV+AXeh9-;-`Z}E<4702STuCxq0pO?h? ztW}ye1h?5E4@isG?lNm^*MoNa;>RTxRP>OH(Yg!8#exmeCdeKhteR$mmTF5kjMk*` zVJIK3ctlPf$}oR_b5wjGpC}$ngiduor%d=rM1qEHr%3CUq)25dw@*+-YRZ)|KSiQS z4PSjRp-&5t{XstCr62k?LNwo;ukku?44%>G)(n>ePE(zN6k~t6vu4pbu0Ku%E%X^ua(m63jI66!@ zI7QVieSPj*Wt{+&I|XC?@yjaH*)-EO9V98(RC&yaYUT6-WtB&NxWIDBm_3LC(NF~feA3Yf-fbLhlV#Lnk^;jb^Xwl+kZXcTX zFHnnTtIK(X>vp~TceR(|9pfG8Svq5feD(z4BNU;8OCcsC%zM^rtw@tzDfmFkj2Vis zbe(OL{3whEQPeFO1_c+q=~5@`(}lz0t=U#foZIXIF`aZoD>fk#bJQwKHI?X|aw~L0Y`1`~ z^M9yI<5zGV@O8N4*!phj6X+3}zCj$;h4^D2qA{OEk2(E9jO^-b&*!|ntV8w}<`h}j zW|S#ZX!fGI;>NJ(HKT+tOR&RB(Tw14Mvj_>!4{5PpU4K8I7u!iWiF~)8zO;wQ2KdjqDV%*IkDQ7UB;6ex!>|wPBY;>|X+c-OLRyi@Nejz&k$FZ-1}PIC zq`V4oYMQgB`rI6TlU~-~17%e9Q6{V@Yq#|UMwA=Llc3?%&HHtH`xYPZ4MtAcB{`cV zdUaw>-jrZUg*)ya<;M@ieldKySryxgBxseK+=>`DGJFk>{;7TofZ{o3Me*J3pAej> zuh>nB^@2`4D?&y}9n`&_=W2m%Rx?LMQcv7bf~^p2(ogSW8y4tl2@no|yEQpmAlAVq zUd-$A+^yv!h}6$BM=ttm%o-$^&h2;Jp!1;XPv?hWT_u7+B6;R*ui1}5jC39GuanPw z7ndG4{gv2l>KLfN>PTnox>5@G?Qs}K_ttGpY9t3>&rme%u%SCv>TS_A!bJW`4s^vF zh8nE5^HTzrwv{#K4hc1iDCD*0?i5uCYj2c_LWnln*#r5PiJ;n#aV4br@v8uLrd2C#5@KCof(~+stqQWDuKlb2k}!#v&yvkZ;9-zJndm8)pImdrDbi}%G6_;%0e|U< zJX8)l;U*4XZZmB!tGGuy5GhhiY625jp&%}qo*d}4nHu{Xy0IYw_W{TlPjQjRKDtX= zUd=>6%rrAra{K6$l8G(Uwl0Bt`0Fi})Njvg!)N(AVlmQYumxQyJA-&v<9AGTdfY+$ znY7Ou)6<*q`mNme33!;MUSBn_S{z^JW$B%sfrKf8syRUdY{eM%{7>G6p1l*Gf>(&y2+F781b3(MJS?(AA(U1cP-?oh!^zVD z9f~M!=FbE6Z~so_?x?Cq$tb8zdU9BtjCBy_h4-m0t`E#!UR#eoT%WuACUfRS+-1Sz zZ)83K)d05XzM2g0>L4s1nuxi8+N6gj3K0cw&NS>+wD_PPb|EOL-kC@UlJ-34HR*+Yqp!L&)2zK&_0|s8j;(X{(9##jetsM)S4EVYO=Guv_(E+boJAk z#A`G~VwSv%TbH>6z?vLmJ~j2l#8#hO>mQ9g+`&~u7VQ>2h}vViNZkb1jky9 z(&VLK*W}FzqATP*U$;uqz86<}*$x|e+K<{MKAnFu9w73HBZH{dVC&Tz;))7E;+`tk zl{di)Lgo~^r*5hSUL7*l$ZZ9^L+iCjX9ByBFxrN@!9RAL6dUI+ru#{~ZvS*P7w)WS z6Z||!Jt82RUx|P)@BMaZ7laM#Odo)f9T-bJYEO4s@hv0odGe-i3ic}qE#ulJBX#nL zvxgUQ`cW~*Q8R6eg5BFeh0W#4Y4z$JZ|R0&XGQu}9p%|LB_#8Uxm>{=7JYrER+CqZ z3eQDT7_0^1PHQG@8cmpBtG2My1IA2M4Z8Utoh=(yZ1MvLy`q|?nHS@rJQqh;{rLcyyG?NL?b|9k`VF?sf>Z_=LG zJl9P>1+=ddQQ>mx6Pj=v=WE@&paMj*{Wsy@kByt}D%N!9{RLO}43pCLum3vQLUnvb$|JIEbQ2d$eLQA{7> z2DjJj(P-1%^ZCO+f4Wn;_Xo@dp2uG}T&59eD9zn?G-ZEeG1`XWwpt5|30fYmqF1t;1gl+HW2nlizKCf%~qWDuLLf(f7?Z;@NN2^NlB>dikzE zI=zA|hv1ZLdRFm!!fe@1Z(jC_$RV-ebn@2%!{49N%Wt+Ra)<1$*NwVNc_hwCD($dk zl5Zt)@xwe(@Zb~iKYGq{UPT9SDV}mAL{uUI5{mf+29HWC?#l5ldON^0b=&%Hn~;h^ z>i~KTms;+_Ki`s%n@=4-oPBq_@IT8kP9;YZERk);9;A;?JoNoybYEXR0kK^ogGm+K z`a6(J@J^?R@`D?zID4|hCJ246d+e5Ybx11k8IOp%;04CB`q-mF-&?U_0O zsYPdTP*+H20c(MX3rDbc0^dQ9NcgxFQ_d6o zOT(1+w0T$-NK}cU1ICRH=zQ25&-vMXxku|Lclvj|W+Y}Nz#{#bB@262DfKrobm}_@ z@I0vi^9G5#WzW4_w!V31CkkRAXoE^da<)_v`{ZJtj1bGT8{6+Ryyb-VM8*;EK;<9t zvn*@p)Jb%0#D3fTs8`Q2WeMdp#y>qlFm^s4rZm~|6G5X|%OzWq7$;%H{i*|osH`CdZo6Nl*LJCy_vEA4g4rInW$|}u zE5%el{rRS`(SS`z)TB|!Q-aYSLzMF-9d37O6C zfC&-$r8gU)Fd~;6Kq(S?ymd5xoUdqFQt2GIpLf@;tF3P(hB_tvB9`%D7+HSRn1ovz z9iPXD&K=5mfyK%S!`hK4UbD=7o+#3Wsh3PY|M%2^g(?Lh8jGAGe-mu@gGdpVXEuLwXc+wD;`&9A ze^LSenXQgab8%-h$$4k{j23$RS_Y3B`E}~eW;lAwC;66$5UJ~T0%HrtFai?j?vPG1 z^P`>SJ^HBwB_ZhR$3t!M9yME_s+}b7MCaf&j#=lpe!qM9x5VWRPVQJ;hxP?Zma^JM z3TxU=)=1FH`grNM#)WF`;ShK7589U-KF6HqTc;Cn`^@;XNMx zx2=Dlxy(IpH6vEkr*rJ`B2a`Kr2$y7kKyOu!B5J`Rll2>;tIMh=^A;vPG`xUTFafS zT9ZQB_(=!y4-D5MQHRQ>5`XkydxH0Z2Y8lSJTfmz1E8CuPDI0Is@LtMXH9J5v_O#bmq>65{2IwV$XGeNtwlLznKf)2nPr$#t&- z%szh;epNyUS1Nqpr#!Ec2$Xx-D7LO{xForh}>}Kl$^Zi#AH?Ql1fblg06wg3euV9$NWYnDGsd5?0UNuh1WoiW~Jp{31P@+gF9g}B@)2M4osdW3ydb6V5 z3ygxxZwKeC$+Lo{fg#a7SD1pidRgY+H%T0$-k$UMwPc3}w=4R+;kv9L=L5^#GFmgT zZ%v}~1LNU4Q|G5s{W}@WwJ0qM;hF^;PJ$#rE0#>jAp?~WQY||sK3#1%VpJhP!1zKC z8E*fnu0$%v8xPik{&@J~AkRl@JpOL8cfQL^6p#f8&SD};&QF3c6j9jSs6tOYZR4HA zUhB^U@Y`Y6j8FVY64XPZIJV9~7el$)Xp9{9O+*#D)h1*&Cr%9+nYMq3ZIMqL`rYc{ z3^r-609b&&)=oATA1p|X-SO2S-cFR#2#J)wU0X;vgG%w$+vd5@CxCp>5id9jyzzvV zO9JQvfCeZZcg$Ld($&0He_e? zf=yfO_+!*EspA&B@uvL$Ui54g^x59n_GP8oojx^snTm&08s=?il@*FBj27fx`~R0@#1h3&M0xg%*Z6BoBTg+4*^|7FZz>VE#;IuA5Eu~n6|5|r*?2frNz;uM z{La~fh9jP4+T%X%!Ua{3kh@)||cjE#G#v=!n1xI_3e%ud4UtC!C) zh@1dIiHvtDX$%RO&rpZ}Tf;w7|E`0aN9Ds0_mmpw^)&6ze@#_w;H)OUWyFYR_ASGE z_PCSbl{4O7pEy^}>pP2k(-ymSA(ltWZMCSiyyN7QqkAAqen=+%R#{#DQ9G|y$k1i+ zTo$sq+yBo6=k()Hiw%1ay0c!B--in;wU_p+go~CI=o)%th+sZC^uKJ8{8jmEAq)Oz zcri-|*i;Xp>*Q8LVzU@LU-5&Ra`yPK`j5BaeVIkjP-@<`c-DTF_Bo1}yYT`no}1q; z_FwPt-PPSaetS*QEC53|srPD>A8#i8XC*cq%qe@0%C^sv*MM0*))VU{t=k{B5AOPK zEf?0EZU3|Ez)`X{$b0>-Ljrzz&ho|Q^k|ymedR;|^3&8oi&%nT;tC7>{Z>csl_x(r zRLowi*pNh>zapjQbo20#`R}tA@S8+NRZRIcbW@UlvK=nqwJMu_g|L^_)sFpsLvFx+ ztlZu;iGzDGq@r-KQ*y5sM_)}IzhYsPfrR%P!g%^w@j+e4s)QWFH~mt?olW-uJd@~K z!KnRmNL+*<1)WqMBJc^bOe0`ekZy=AZ zC;FZpzO=eFtbKW85|X?HhUcgS&R4jB^CL{cdcxpG^m~7CfqZGd zpKrMw$pfVa{l&MMC`;UHW*J6lEfclY@_FNuC$Ss8=g05i7ezjcq0J{oT~hT;0PjN- z8(uYFF-blsyqecQ=XXEDO<8mUy)KqLYkqJR^N`iYgPN}cd zNe++WUY*Oz?7PoUW%5Et?Aq3ADxTsGj&%~%APHaMx-w+$=s7l4oFwU9UL%Jk$IAVk z3FXh+rKB^5H5i@9cr`#So|OM`pWeZ7Ur!utm2MzTBq? zf4du80bXb~+Y+9`;SEZ-c~^u2$v4}L&V)XQSl|ENa$(cs2d`C0IF|G5V}%W8j}mO0 ztw)J}EYb$NdJ^`q&`^30AUZtexfDQ^XM^ag9R)q}F$@5@dUUZjy`;=`*us7C@XsS% z48n;P11kKUw3#o48l9NBHB;$|JjV(crIHk16g``Hu*ZPsGFgy8^fIfojRIz zhl5JOP!I!mp@mg+>iZndj~1J^3$>7jG0Do%-?V$Q*GSC&oDL{e6s$dtzdM%C;MZ@i zcB89&a)ApezB1bFUhPIAmHu`SM0X}hiiNmYjD55;-u(S7$J{_kX>a^l zw>hX$HBcQgAWK(dO!pIbzSv_2ARsi3anK4%?5mTtl8PjOz>gB`)El5Fp%T`l@; zjKF(k6WyiLclpUN3I^CFh7s(B#l+}M$#0DnOk%~V?=L@zc_xNaP5Ll9#9ZT?0*+k; zoDeG6Dc7C7OOmrob(tB9pS(N)xqJ%%@Sc@l%Z> zFkR8F8mI#xg#NMTGs##dnoHjaz+_P5$Q!rQqutRo#n39zON|UxL!TexY_h)7@WksP z(x1+vS-z;hYKV4T#S7UTF_0!aJ%#Jn;qJ-~p`QchLfTELaEQW=d7MG4#pPQ-P^_E7)UVck^-FGajcwotk_&l2z?@q0Gi*PIpt6rSPnJ0gyjXv$&|W7J#wKFDQ3YTCXF3VbW{8TM|u10bg?A>=6vj$%Tb zuZ?}pn!JFyD8P;jcBtEOvdy%$XVariRkFC+cz0_jQQG|Y%P^7tFpasG}>kO(23uJ ze`AV5Nlh8eAm9CBee}Jodb7-#0?a0=T$l8>KFbMPcBvC5GCb=LeE(-&1Ku!FWTwpz zHCGIN7jUg)s6iaQ{6v4D#v^16g^|L&2$s8nhU_FhI?f0B{e9E~0 zbi99?98-iQROydUY zLw%*-oxU9)lzr$Nop7nCB^B#kf0Z()?iZRgXoW&7CjiD59 z3f{RrFhij*y8QEiDfgJ8HYaEUAK$@%W7p&_?gDii4KTexY}5LOzotWvrku!4YY6i9 zS&shh!J?8Ce?H1N2xg1;fjsEg3&?J54iY3p(S9X&<}6F++a2Pt-ADTZ z@c3Ih{=|HXZ<62pI4#L#mo$Gp2Z(BF(uj`5?>ot#FQW5g^EXNx`;Ro5=7WwaT2N30 znKY(!tXz|G5+fGHt^P}o6q_yX8f=*>%1_Jj)izffZuU<^YvWixrm*=Pu%HF}S|}Fn z3kk|dr=@()P6qrVtt`8I14T@eA$6rQv&-_IbYv~|KXNenX^;^dqhJV(>D*mMf&jmt zkzSS5=22wx`--VvTO;X=A#wxhv8h#dMl~vgduK%y5hZ925Ce@)(0xcw<2V zQuaB8)x;-G!7bxLi;FbG^eT%tz+ucB#BNPwHOrC^M97!29g&|4en%FdSwDh8+NKV_q1yx#du7}($S$J`B4R^4whkxI}-|lnD zsI#>XoUYPszshXiI?BQcW|CrENni@Hrq%LJTz$+zGRgZrBOhs1 zX+Zooj0i1Mu1YQ+*U+p)5#-Piq^A$1p19eMS2!29$edLE%WeVh)xY7%dHT&XkvJ3F zUO9V8VeEnD>3ZLMb1&5`MfQg#u>NpgAAe5`lec0UA>Srx$%ipfhU6+%xK-j?~XQTsNgY62QF%tSUc#se@`35e^F_Yd-diQGS+HXS) zIqDgfT+?<%`cRY4^{HAR^iVreFJRkC2i|66yZN`I?9cQuUN>j~1uF8o6dz3Uqh@Ai z@v2ogw$mxwffCUMp%>P7nu z24-Jeq4*L>j-9E} zhPemcf!}tfgLyQmL^@+%v~mO|W5t;c|BT*;D_uA=ejfPE&ySq=Ey$vXkRIAtq}TUf z$q|b){9A-)GB&?o%JQPK{T26chhz-(mix``9j$83$nuN41L36aV>PI}`t0h0xCTE# zE%Y;Gs_W&xSiy^k1L1Bd;e2J};k#H+&R|ZN-pZo?R^Udk{)*xwd$v@X9j`oacfaE* zy2M>*tZ=XHyo(l|yvjdyyueYaJdl@(a8Nh{SZT5Ok4rd7Z#=BTS(e2ffB)#**aIP3 zwf^WK){)AfAMpfXuLTrJq1(wz{aIwW9NpR6``7C?T8nV5JZH}(oPmAG@uw@^&xTWK zwja}9FLtv$yt< zyC8QGY%AMV>ce;fU)(nrldGP#xHHN}12=@HhGV!FZ-e+@;k^!Tf9HSjL`Gf#C7fpn z=gUP5$I;~vu&vS)_JWK8pp((mt^rp%V*uLkJsoPcT5tmq=pKYSYjq)dD)W~|#h>wBrgZc9-*PHd)B5FhyD^iOPFF{3F5i?<`fMwTJ zB|;iTuT8n7{oB_|5>9@86{*D#Iyi>VEZ@N^AR@o73C4H$4tj7aR!^-Z`k{QDqL|v9 zMb4}IF81tBk^a$omufcGSJplOP6Dx1qtj*GQGkqFXV?6iYV-|<+FlJn&&>VRsp9tC zu-V07cX{yKx{z4rpOnBeCGKF<(ZZ`<5AuJ9sy+GkVK<)Ivk^3r-Y09&0EHoqpC6ap z=WhVM&x0spjVi+e^ZIH_R_`X2)*{T^WUKl8l`5Q#{htS|2<5g6nbKjw(wE(RecD;P z@6vir_hO)gNpG6sOIl$I_N~I8J7d6htV#XWxO8i&ZNg|tA4QO{zjV;8H*2h?=v4Q= z3&SxXSl&H?3%nm|s^2_XZ~wbpnUztC^_7jDy-#ka$2d$BDSP&Uh7dhYj7!iQI@M-* zwawG-H^qvq=0%8=9(lT+0)hPN1GW`Wx_`XikM{>an4;``L7=S*M*(YesRyUlgt?9h z(Q0Y&7ZR+9Ez-J*Sl@E!BZvoD09cayZgbJfnR6Ezo@=(;f|OWxckKa|$Zds1sfImC z4T~=d_NFED9T*9am>6sy#?k3Nk1-m#Xhq~(S2|cD)>`_xf4LA)-=NwpBN^Mrh@FW& za4}bnrzy7^y)S;c(@#uso}+9GESHy{`ZhsLbQk(uYQ>OGVL;J2$AT5JkA0EjgZO^} zjz8oHOn9SD^d#gajTTC8qNhQiVdXi|(Xwv6o~Es|PX15CBJ$Xi7Q)c-?H(;(eaH7U z>;JntuuS6yWK;tq*T z9oaks`73nF45(tS(ZECe^_0t)07oTF1_;p~`Z<2z#F^f~iP8O>$AT~Z{^=YApc8My z=|r#Nyvl_N|IMY1oCiebBAjw7oS(dAWFAvy%t9I85%>AV3z#(aC2#NG>m#f#KySkI zrg)_tJ+gUk@e{&>ksK7wdZl)=uP$c&f z!Yfen2{iv;2TDRK^hu3s8wDB1l7Do)uxB-I;&EJ4=ea%ilZ}15osJv@z3v`@A&FSN zAO9~r-b}PQHnZ!#i_`wV!SQSOr1};m;^~(;f5Js2Tgj-ii2VJ&36uF4(?`AK3*2>1 z8s@z`(m7R7MwF0aMdJ}hFIK?C_PZAdhpi5qb{AkEg2ltfI{9)qh?M^39G39%Vn<;qsL`X+&0RIhUYPz+ z7Q6IMp+3e5+5dzpLy=LBI0tIW5xbKy>4w;_Z_UfiBW#4mNC(A?nfil@@1)ileHuB( z-zy1l%UQe#^^API9CW8b1RYUmYr%o@=8ZHk}$fwEAI?2EmyWMre~v3q%kDd5wWq)GgrBAkOxC zM<*5FYwcAUq@nf)eWyQgYtYnyQcTDW5saPdcMDyg5C0LFOwi=L1I?CE-RWQM_P8Bn z+r!5|_QqB-;dStip7APix^iS)?tNMrywgMY5*Sy0+nlFY@f%Wr-Efer(Yp5W=TtGC#v0?AZZj~9p8^^8$nWCRJ>56>lfh@t#@s=-PB6u6* z%>VQS{%uCESl%Z$mjQ(EEwx5WY||bW`LA6B;skkCx~P45L4W`SyEr-)& zUqO_>t}{W@`YJXP-ua4*DY-}qz4hCuE&VHj8MX+b|NVt#cY{~blUmUDpr#={9mwnb zn18_>Z_nHV6fLP|8OFy8-~@hvuMpriwroF36Q0A$m5HiF`4B{O2 zWbsG&3cRm$T5X>VuT^}>AC=h*vRAGra{Br90F+&)moN{C&ES3H%Br$LPe~+w5Qi)`@j3er)#KuE&0=FHTzl0!=wEIqx!RP zU=5xZ-PJr6#NUS}fYMdXv!S>>1CN~b3kZ?7vmYp{Wjn@c3EZ1Mc~{QHz6=}|CSI{L zqF-)%p#3)t3Z0P+dl@n5FFC*WcL1mExeKg+Z&u!^Qf_G!nLlm>?dZEdHN2O#3o}Vh zBJmak+Csj82~>^%V**`I{$eJC>$28Cgx*T`L$$L@v=`bRgt>evB_JRqP*sq7@P2|~ zSIrz5)_2xJ&Zg8c6z~6$1QwgRVRx#_|E=GJMlV&An7Yk)L^uDeFq}cs?G;JzED(=- zTTW!ZK%i_2jLVDux<4jgWsGO%`#5&qX|B-2Q}!MVhobZ`q1JK;q-p=K{kEPT7RP>g ziuybWN+}H}j%Ei41s<`UTXjd1=k29C4x?&JeH84>2Qr%6_6U zOMbQh!ua1BO)mdCKyyG(Zo=lQf13Cx65E2Txmyd9)y+FQM(%c8X7BZ_B*9jTPMyos zEqYe8Ak=kN&Lf=}OcM#Lp9<*bO!{qrKA4|*M}>QQqyJ@X0L_y+45Q{Z^eS(mxH8aa z6xGB3qcbbjncxB~`~vTThfyY*v!Dsd(WQ{s1^#a>|M~1xHU{?DMV2Gc{d2Vh=|x|D v{ff=sfATVHpW=xA|3Cj4!J$uidS+mx=-t|txbg!zNq&q_g0)b9y zsAKg&AZjoO1ZIWO07oXmWrKhh$X#V^We}(^ihj@X81NZkt*)mH0(lF7K!F4hXa_hH z_!|Ur7XyK2EI=UH1Q6)7^UI2B^1v6RHijB^w6#I!fcH?)F)AhyHSmrK_zR*s10r7y zcn7*d#qqEAdQ{>dpbH>z;NPuBb|A>#bHagF^4nk>j{`i7r>Ccg=S9ksh|9>xh>A&wN=OI;X9&CD??15g629+-I=aX| z*TLGjS-aXfKLADsLB6h~m6Q7e1zukAjsErLsGl}ocK^Q9eYd}l1w5cA`5RGj5i!yK zQ?mzlcm6NU$lv^5n*n3=ugCfyH}kS|K59f6jH5ovlY1bmYv*O-V1%`Ew7E~7X~j#I zq~$4n``^C#_tX7HOT&M+6qk~b{LiNU@zsAfRdI4~a=q?sX>Fq@{`(y`s@UjTv7 zAPubY4KJ#>q2nLS^q(m%T};28bnQj~()Ai2%)1fI7pQ&`@j39l7!=B@%*J_x(}DOq zB#;3b4CPhLdI}+QYGL4*STnv<#Hb}#ig z`Yu*(4D9Z89nR|LzriBl>JX-&f4{KZgzhbWm~r%w`mZn4A#`9N$cpO!JY5~~1qmGf zGN#fYA_xvc^F~AY{&@k;=KB9WJD>ZJU;96o4i^I#x~}u=ck!Ik9Ir|;B9)mYSH&OQ zu~Px)M@8c~H-V%3pMVD;_T2RjM-KN#dUy_9JgK`|2A}5liern5yeQrL#T3K>{U0}eN5O7i_2*Lwr@dwXWh4|irFoP4d< z-$+-#yLIQeO_tLBcct8e37vzCxx;bMgIC_`+2#re5C(Q(IQh0cWk|xgAbQa7q`S`* zG{}Q(af27e9l*Uea^Y!_~Y!wEXjGg_(fRSg_u>#sz!|QpT`mMrcChMhT)wxi@ zNvXcnnb}zmHm=`Uuf9G#dfoyUIG}s++I9fFX>;s9^Jl>Z%k-H$TsJ=~saXGEoXvdo za$3dqRATmIym`$|Ywcd^WA*3`b>(8+lz`o`fNcNG$`SqAot}KwqNb*gCB0_GjvvMz z3em7)1av4?@tYeMqao{OGL#`whg6_bML@9q%7uz-+5NTe*>3GJZwVmb%DJK*@;K;| zZ>`^SIBT|9p?6+9aBJ{qEHUI}^^Cp^GwbcxgQZ7GH#+23wP=OCr{zYB@+Ou3noKn^ z8j~trCE@wkfaoDsfim*DQHndZ?!)+Lee<1f@mIq14UAsHwhs3?4lhhkL11(`^2-gF zOD}i|y7e?qhBGyVYz?aMp83jS=>6w)Yf~M^@Y2H%&vyR~jtE>G*~zc_T=>YaQ!jzn zuYs6@L~Hj}?tKYoe_cnQWo{u@#0F1Z{Il6{FxQdwh{ylKPo-bs7qiN0)^qvy8cSr{ zrfzutbZNvyS=sFRCZNZ1qL&322~oq|BQaihkbBr+aueRtC9&6PXTHf4X(( zn;)#iw_?Wv4yFUR6ErOdqaDEGXS;PMlyxsZ@9-6vriVnA>yU4hN)K@b{)?8-{5ytj z5DcVh?VDx~T#fTuQozA>Xu)BR`M&u0Zxu8RFH-jxRB({+Us=_z$Zn~u$+56HJU=39<#a6}qUGMzh znqy1LQ2|w6zebiLJ)fQmcy$&&8e;iPx@I}z-gJ_uNcypMxO*%ibRWim2{QBFo|F)} zj0u_3W-2}Har-l33}bMLE-fuj9mmzZT}RD$BRjvwJMsiX?C*FU102dNP;C5P(;q+~ z%npC2M~U!_cv2nwQaZ3sMH6Nd#C+?hj^D`6tC*=%7=e5M#ydOqs_Z-Oxxz-8JZWx2 zeQ0@^Y&4u|gjY-uA;2X)<;jhL32+*}k-Yw|G1G&-|01yX*Kxi_gM<$2PuJ+i(X5A# zc>k=?`1oT>X(ls0OVoe)NobSWCC?E*PdEtU>nnU2Lm=!dt!4K@>zw>o6VFN%Y}#0+ zgE0?@49uj63*E8yr6oUZWq-ZtHE(ZjT$^+>X?);Iz*u(IHGTTKG}@tvG4t(~n^&r8 zqwvT@lGj26i$h6|L66bhBz^g{h39HZfOo2uorqRBXMU{IIQqtGbGY+|Ou5DiRRKHuw5*t~Fi#1@2v z78a|cSnk__HpbCO@E-+%Jsw~V4;Y`wUpZQezXJmq zJ&ll1yjmX$*C zgPy?enwFI>{AAr6|EZ9EY-0syNZQ36yA>8>XwV)1So){)ClT*NBZ|9WQ-Wr|*pxbC zeO^%3MF*4sMgM-QooGHXt89o!ihxTm`{Yd*iz9>u|sW6D)K*BE)DCI;2K zqAR=>Iht!%KiqMWtdn@vlGTw(1s|=_Cq`F1skWO=&>|0}>tsvw$n zdv2N!=|K$F8`bMhO8?Xy-`^Z`sx6Ytyaq~B5Pt;PW>~E8#;>DT)V-oRk(-J9+x!jY z5@#&1AE$2hv2R~_Goa+qS>wcRxbV+vs5?YNqrlq&e-}d)I0(_(YaZZdL}mN>nZY>} zm3t8v&k4E1z18eXy(Y!C97}rW(#!#WZ!S&;!vs!qhJJ3P}mv`q4)cqnk*PaS>$X^5?E3}!sk za5bRisnFynlbR)C!G3{F5yOI1UuKKl`Lg^sSCeGXEvN~#1GZz(`pEZ#Ig3u1!u^Wb zJY&bI zPG3$Bc~p!a#g`-CXP389wi*Pp%4+xL^Vw+8ufhURQSwCtc5jnf&SBKOE^If;Ma^lh zFhLeRL(F+-F80>#Q8oNj5AHgarr3n<=Fez^SgwM7PotrviZB>{9wpgSUOK=(-;ttJ zTk-qV6Fta#>T`?0I;s1hj8KDoX-jX9q(G-mcB%|6_D$8%Mc-+;&^om~?WefRvOcRP zD}{MFelyp5=F3LR)Ia!+J)dq?>o!&S;TXqQ0?EW56Telb>BJ-^T5BJXD3$J)4cCZ+ z@LzbZ>|CH`?2?yjAXFoos!)3Sp9hY{Sja2w&-qZipf)Vw;@ztygZC?+HP?>yM>&kI z#oxO3ZpEeG`&GHzilusb`a-oIll%~vE4Ozq%!6;}Y+yMxu=Jtj@{zQR=NaAUdXQ{< zmREEX)^9w2WWfSj?qwM49;@nFC>SxTX_FqQ^4-2XkU!G#i{kUX(34SXYizs!(K8i)sGYi$FVvgtvrsN^rc>(#8$Xdm&@-Cn zSr@YBU5himZ&Vrkh~gl^MalRue>$mJn-a-|z+>!(6M{-cH4Uw^!wF`9c^5(6Rz2c$ zRS#Qbgu}SK_y(u;xE8(C*5k^mY|v~lkh)yV!T1x=IC+DU5@+htdBBK)h}FLHQFZ6D z!)2&Dln#B_sWP8XZP({zX1j<+Epo^oZ2hvqhO`}_7Qpf+ZjUW*G!)lTdL*d~f=?kg z*DWCBMn$sGzF0CkqG|F-hmMAwro%!Izv~0Tq3XCZ$@r<~D^!IxaYk>795QVbA{byi zh0poslG`#Y6J6{5!?l{6n3j!4c7C`#9v~pJd;OK~8GNz46nvXDt=u;1OcUO9z94CS}N-jkz1g3wggbt)vU^aIjm@ zlj@|lhXm z*!-~1Vy*-IPP_;|9p(g#b%2is3Ysht3{9||yZ+LCQ2rr)b;_Mnl_+rpKP++(OEZPv zNONj`VZtI5F?G|#Mb*7W|K=&zA;XYe`Ms&*TUnx_-q4_?^HGF?%Eduy`Sl+Mhm)cK zMv$O#P>bB@_FsxIH9ZE#`f`g^Zr@+ale|&14PkHy??l=o?sGP|2torhHQ-~Mp492) z%RuIeC3Lf4Zwm&^xRGjcR}@AAsb|VoE>q@2JPI8N4c}IK$wdLS0Dx9s`eE#3T5tCP ze%JCc#y8r_WwQyd@RMda-fIl*X1~u2srQGuf&({G%7*=TgUbAKOMaZ2f1!H;Shosk zFmSzMUg1S7u?yq~W0LYHj!2s8ER|mo3kepI=q_NDMtKmQ(%g?Xov7v#7nyv{Q>8CDa`~k*Jl3LRYiZ7%Pcui%<5d;J<2}mAtE0}gI9z>vG$}%ZwvwMM38Ip zya=z;Zr*4WsmysH>wYiW0k3d0FQEY1 z5MRGseDMfvJPKT2^}BpRCNivKJq7}D6=@F1P{X`%RQDi)up{46^JoQm&uGzj%u!o> zf2$)phE_UQjylgA`*|zT2gZx#s3%7Ir_(|egHm(c)?sJjF58Ii@)}(t<|1i+x@mK) z6zT65s+NDL_Rzu#Tz;Qxa)b`PNRU^}%J;UKqg4|Kk_gXOtX!;_r2km85kdRB?6Ym) zUW*12JV)9%Wnh>Fd%%n4CJYUGLb@#_mP9J&^wcYySUBCjiuat$&e6l*iJ)!#(#YY# z=4nf`A!5B{Wn$3keK5=mK-O2z##-ZlTGM|_71@qBfmmN?y~~2s>pnFd;o~R4>%7t| zC_UV=dbFB3$^H6?YGXL+7kALb4*6nVb$X5ad|#B;!a&$FMvU-OgI+#D5>$-If;-Ur zt6+35!6IXih>FaV8n8`oIa>#WT?2)^rB9*n6G5D>lwTeSBs%D=s6wNpexBZRDoKT| zif`7v(KhobZ64G*akiBkk7>%hSo$qY;P7|tvq#*1Yh5eVkm^h-FEF9 z=K)&*!2Y~uR%uhrQD(!&OzsVHl(-y;(wn;wnC1D6Js|uDG2=NjAzf<8@M&*#ZLcpX zkfm;EW-5Wh1t4MMzcCF&N0HXZTiy?p1LhRI<#8wOM4UkkH3aqe!@M$v-FMaJ;*@aE z;J!y}7I%qMHpHMzY21k!ByJ@$-}KwVo~Oj;zkMqA@S+qe=7$4JgXZ{k&BP-p1_8(Y zS?jvcP)ULw?^n&^qJJ00vKj3-LW_<`3yD40T^MdLM z%4xz7KL9Fb30!??NC4~c;QQDTeGS&}Gw*L9!$_=Frf+%-X9vAs-qq`Jm{;r9s!! zmY!KxDhmC&JR>22(8-ZtL2)i<&N##qk>g>ywBp?&0mI}h0&Ah60%S}v8x7xvDW*&l zR7b{Mz(0Q*Nd(dP1~ZnYP%Um2BC~*;lb?&5cu*?>{z~8X;JbGABW~}^a2CWbfx(s0 zMtN$-tS4`Wx$SPI+$Pi$EE7*R3t(t0v=rLsv?%eY4c-Tk5ZQ7IAJVFuz^tLZ(aw+nAeagBDi0Of z-DKb7Qrez~?Ezr@^*QuT|2fh6c7MlEw$3{+KX<~1!l>Dm2KUA`rY>=(;i{MCJ5Ri< ziUSN*QyzRceZ^?JGUgw$(e`0olIO6|kl*Hzwkmo;Ed#&E!5q`}Lz{b=NIpmw#4*OOxMr~V44aV6e}d$?8N0fWS80>pvsjO3UzKP zgZLUc47vB_#u?pt&ZNh}!~bLjDNz4JCnu+T>V*x13Xuv=`xLQC2t7z>g!N7!*@(xi z&Z!MLK z6*fp^E*;z>stK3u4SwayQ<5EvFdSg!O#55kwkT#kfU=NGUD&_>l`G@JvMjhGO(2kpvBH{~>#fIx?(k3&ZQI~F!0Q<+A~qf=?O7s&hxukP@m`~F4>OMmc014e z&pXm1WwS2O0$4qswJ5@to_1%uBcP_U2^^fuy^B~npHqM-`AEa@6#j5`p)$W=1vNnc z7x7?to60vFp?*++AwwX!$>2cv_o43d<|-Tv=D~}p9JswI8nE4Z6N+@lepAvY_s~cZ zketp$%ROB&1E%tV9dv^DA3mZ2JKB9+M|k4H!t2EwlJ$7l?S>anbnpm(ly8uu{qTmS zNO{IfW-6uqKRQnyDOPQ*@AQPGwwC?4Wv|aHpmmlx%z6#IzW}FF9`9ks1P&3v7}1T9 zDo8MTMfswo4u?~fOLM?%ZdsgfOM&U-*xL>DPz)Ef%8bn(_xWPaYzu(HA<*fuE~VYM;^WvlAThYM zuP3~`aTAt;DAickiP&hF zBum&_LH@2S&lpXZn{ufcC^O6kdd*rVlpb?2piZDGAp(e^6bjZ*G?eV>avaJ|oL%6#HBegY1%l|aeFW@b-|3_Qs=IgT2LoSk|9 z+1Evu86$a-oG-vnzqXGso=R7R*ZuJX?(}fY`PX8m+ z8FvGS)ED0Ah|FK5WX`l;Muj!qu<2>M+Wkt6`a97c$sVg`w2)eDPj=z}rGghsi4GDFza4H6O0#Nayu6zrDO*a`T zv(~B78vpe3idtepry4%&G0wrnQ+R_qLQ9D5my{ zK8VcBhVDr*4H=wWdWb5OpH!CzM`>};dI6rIWk$Y5Nz#p|0-wuc-3z0)@RX{_~1$9sh-?`_Wo?`b-BBPU1~h0Qxa^* zPH7EpkG{qd@7_E_Xy8g2B)~)=>%u z^97$6KGTl~D@T0r^}+tkk~6+vZetX2cVn*K1}p+!0+Y8ymaT8svw$7ieyW17 z*&MMy8mbnSp6xLMPu|N>7NAQc2;=ZN6)`qcmv*8)yqk&Y$4_&&woCM5wSV3u(iKW~ zZHAsUJDYuo=n$ZzU#FGG<64I?Ev!x*Z)T7f$rWDroq4Y@SB!x#22`6iu1k%Z`6-4d zA`fDACM;7b9742bU=L4?VA&iLjDRu_U@0Ur7p?v(#gS696gvS$e8N%Z)gJ6%8Y**{ z;097w%kicj{r4*8OV6(xZa1Cj_OMF5!rudo0*8e_lIGQCJ=eNksGr zob99z(veanwSYnqAKs?;doMreRhUT1y1}rGi@~>V0`$bnx{2jwtKEQ&;*?W5RrJ^UZazpr~qzYJqu8MJ)pzAZT~j`G$J%B3hcPvzh()M((tO(mq}VBXC-C{qwSm z2Np4|kOW;J%j;b!AG@E~9GL(uP&KmP)9sKtg55YsvhPasy{WIy6-X`+wrc`l*#4jI zZ{ump$+bA-m#V`R!{F~lN$SPTmF{UlTUnp3VAf}c9%vig=6tR=`Sf~=T16h<>d0Ju zj(}EzF6Nn)JCD`t#0Hw%BW6P}9#)a)wf=Q)?%v~xqnlwmzPze+7F1td$r1MzIT5+G zRlH2`FApOFy8;n)Lq8rOR+s4M$tf@GAyUBP*S=c4AB&ckHq0X(vW|s(IGs`HpFiY6 z1SRiiOZ8_EBaDjgJX>TsE68G3J{fo3CrxAS+8fiX5yoraSoQii6SbYml4EyVxbZ&y z%n}BSyf0r3nYG+Kg4j5wAd^eBd|e%-N5jDjuJ`oaKCQ7BN96q^-!Cu<)OoUc#vbvQ zVV;;6ch+KHE7}kkHBdx!U2f+%nfd4tMl~>7+V)%ETZBCQA%1so#B3&6+R2PI7f-Hu zR{zm8So%d{I&D(%SBX?%ufoZj(8BHabPv=q-mFNbnL`Mu>8hpbKhl5 z^3GN5C9}qJvWZSLcq8_v%;1V}nh%Yu2Z8J z3Jf7}ADAi39xcd?!9=Bi_IN3~vc;2Mvd#G%Z(iyO`rS^ciqJ?}&?Kl-^F&NX*bF8m z-gN=Wu=*ogU!(_YT7CW*9|=j@8w!z<0+cnr07F~kt_J`Nk%us(-daRzl^`8#<%>rBkkOV>`TMXB^sV?-<6%9cSKVr@(JsSy6vOg7 z6`tR(Sm@>mF?M@(`gG;N+l{HiGk?%qulsu4?y2ow^CVLB{`!zyJNS!CS=d;W(Ej)f zf|$raQnUX06%NYa*`h&q3Y$OO61}TAiWpw<{(>{TZZ}P0xY?}qS;`51$8u+Y*b_NiH@a4VJYTY zS644Ku$7;#4~|}Ke^R|^3Th3h5GiM!=qqXD38;dGOqG<@W@$qL#v8);J-D}VrEsTo z1_)?;q__9xfT#H&Ch)!Xi4XZFF!?nA^HV9iShae^oEUDPVK$HT!CjtduI`(#yLq$P zq|$nwU1511{7T@c3YyLp^b#dDkfJ+qM5r-CY7X}o zu{XDkDS}EZTRgQ$kC4i`5BT+%{AZ5DT7SgW4o1XVFIZh3~`kcN*Axek3!pT!P^)|NjFIQPt+@WYZgr82Lhxb3cK>Zdf zG;Xi55IUXEbZ&T9;dY-wvMXO-V}aM)=hdn;~{ z8L>+i?L3zr{n-@M<{Oxxnabc^_`O6h#ka@-NI&jR+BXQud0yGcjuQ8*bAcW9d1j># z?#^6{ahWgaH86IncK=v0SoHje5BnSju)3eaJW44XVI2%UO0^jGVI>bWfpH)lLw*~d zHJvV$x&nh3Cot$#UJLPAtoBSZ+%eNKNHO%E&x-v34YH)wg&c+nCZELwo+LC~*HO@~ z_y4Mf?k0ImMsQ|^>^BhL)UkQ=D6wYv42a>rONX?L0bFiKt zFUGs=tv!QjiI60Y3DOuCT83g~7C-!oWU5yIGnz zhr{RTrRM%7u%%_qN3y6V?hOB(2~w@8-f3~z_EX~u3nh z=Vq2{cmzuWL^F04&%a&W=xwg8uwa^haBi^G&mCZ!8SWnC4DTr}ZayqSf#TvMl}D>q z+wEOTw)r7E;?n(bje}QIm}0a+eW;##kLce31z0Y-(uAUC=MINl1P<}V;2ZKDnJmVHM6cYTl@WwEh?fOzraT%thsAycGQjIQYHPlK zG|jWfX=#u~XWLA;{R{x@8WC0aOc9h?owT%sLIwVSdMIE^$z`DCr;1$5V zdY@^xFKh|byK}E0C;>i|p_qOQ2;(a2%{u-?1TOdQZ=vv+FAqOXiDy~b{kVQr#->33 zcKK15;{pmApBU^65-6$n60)oF`oI`sHJH(<~SV z)g>H9?luJ0BnE2n!7c*=KKsUNLAJ&L74Va!05KorEio~=n7?r^5Qr&VODx|WQhIm` zu|$@)_Q*`XyiW9ea$!<}_X+e#b=gCuMR|DODE%qd@W7Q9^q-fh^3Ugecm?yYlqdR# z(%L0U+Udbh$*(m)oT^C2)2WVgJBX=Fw&hT36c0i9?fc7wz-vMK8-w|>8-3Pt&tw1Q7#GMn z#s#svD9UnQiv+E-`-qCvTp$0V7O9=AniFDCDKMN2g|SZ5M1_-8HmW8B!{0p|S05NU z{sy!H=TTHsRIt-nir~<(W_!veIk3m?0{lv<`T%?|s=@f%jo&do4l2VDxB6f{Cvr&A;E0I92@S%qs!-6?Z|HZ4|=XtpE7`cP}Ndy}HA#6X4J3OKlJN9Jd5 zpUwrcuJ@Cv`;Q}d-2p5nbVsz!k?@<95&UDY?2f-6(~}8$IpwU+scK)97%RJi5)k1} z<)p);aqM1ieNNKzN?p*or^<^>oHjG|+mC%3!35*PN$>?X*ar0w!nvDf6^)61<%G|F&%bxcY!QTLNL~LXPEA)CW)tF_hmf;<9K~Bvn)jdWZZLdg0 z;qj@W9g0~F@B&(3VR`&T%5ajD(Z9o&Ufi!*R~Hd2&foqa2t^HHbiID`nz*$wao+|D zznbILyT_mmo4W7)IB-`_q`sY62fH-4`XFE_geM1JV5>1}rqk7Rh;(>mYqg84D9=@+VyAmlFiTrW52W2%KhLi!lct6Qn+&@5nq~`^{VZx&HU2b` zNsXy#S9qd#UQd+ zz}rkmQQ$EQ&7=*RI=T21X3EF@P7-PGTPykxn~<}PS9CcIA()ScxBdKx=Hq9+#FNRs zjyj1_xxQyxx7T~k&B^e-2gl)fqehDJ{Enf)jf6-KQowlzI7r~|g;Q#df29-8gwhUk z@6bghi{UD~%{OtXj{=t1hKD4$yOA)_5P>6{6LJEt@66_#*C>tpX2ed+q{j$(k&mmC$sh(ji4hkZg#5%!nh1rgCkZ9goDMeiGQPw1Ox*f zv@TZHkK#V7G+0K>!UdH)f0O~yP@P|1%Jh7}_jNY{vAT7fBmjafz>W(*QJ=}`n&oKJ zGIWUywP)TW-k-VGjnqaC8QUP+1tT|eaKtH63Se#C&CKnE`J*<=2H;3aM%JC07ayw(s z^q<f;vK8BaH9VKXAi&_EA@55k&`b9-69_2!~= z{2PH%StdXcB=HtN!KkxI4F-M1nHxLSYoA>69I~woG6%kTQ|urU1tjL~l7A&sa9rK- za@o%dYE9w#ZiIS7i8_B#yLD7FeHW5-sy)dV zrwcxiOLw0myh{I3IOUXg7>@{r9_Lz~{xjY05#h;RIF+QfgP$QyAu0tr9``QxFh}}6 zDG?NlR65v_*l`9#vhiIsy}5m#?%VGH6kzI;2h3DBVJ%__@^Iy$g>s9j6ASfR&z(Ng zMirj*o|hmSTCn3%X7=C}`HOeHW-=)4Em0KTn?%S4J3Atp0)Vo^+Ug(SBt9bI+)vfB z1mERzY#~#%7JFn?>({i=T^;hLrzq!6<>Svzg}i`|ig8`TzRWERnV|Pm7T{0zK*}`b z*%L+b%O&cabJl@v5!3N(2buYa3LWJY0BQY`X{5tvAD|Ri3za!xDBN+_zP9wxd*7;X zt^uhExEm`JREk=F=V8@9j5vN1U1z#D7X!0%W3u|T2B=I;fTG;UdBS0*3ZpO{*k}*~ zO9S(`lT#vn^MEbAd`rEdfdNOw4_YrT7gj7(%vK1;Y#-%WtdIjQ!+XtFD4*0J4+$Wh zGL5o%Y#~iD761uVb7j3VpF3}L)rbIUGsX%t+X%?FFl%9fTdZhbc;9c3 zgwpH75UcFm(p$*i2J}pHd=DC@YL zT-xGsX@H-qoO>p2m8vkp?KMGCYk@w>Kbd$_?3nrv_99#j4rJd%+$C zo5dYfGT30~11*pFiRTRUEradU_k+b^o~W<%p?+>O<-ri+7+wa#3^6{+e&~f``^P(p zjt0;g(RG|HTu*qdQ9V$Wc)oHd&iMjO*~X51lCdy= zdYn{xM(?5m`@>^wnV!7Edb{6m-TtP3>2t5aUM1O7?fSZySA=GlMy{JHJDF@jR=2U0 z^@UKD^{CrcwTwk@mumTR(tDXfav_tS2cSa>CX_zSQAmw3DB}B%y+z5e_+Ad$X|90n z$@o^YUi=8$qScPB8GcdpHcmp>>sy9Ks0DdP7uVVA_dT|b%S>qt(!ku^nLvtcQuaS` zm|BW}i2W3P98V~P_QSJztd2Fa)_>A;>L^v?@q4dzJ8pz2WdRPAa-*4xI0Iu)uT*S2 zry@Sqry$f2Yz+pBK*C92_hRF|lRjg0vsd|OU0g?OY11eSMM-5ly=HJhdB_$(g0JcZ&v2FpF)GSf$E2vS zETvh>{=HOq5GULg%XhRE48KB&chwRGUn9z!(qLQ}!vd0DD)yZMb_eNY7)hht_2E^_ zG;uxe+XKqN)Oe7WuDFo1^G=@gU^rDh;X<1R2(eNVZl4!e?ZmRQq=}`sYJcLCf#&Hu zg;h|mP*nXLwHvdVV2=I`6Hu?Xc1-hO7Io0!N_?$}Bf#)dpN9(NE7k{szC9E}_-$$* zJ1?|c!Q)&<_4z7z641m6m!1(uBtPYPhvn1;u#oH+ff@JD)WFFcMI^U}$0cB*a6Dl3 zODn@7$Wo|C%(-qFnfxdk7#01FiiOul>w0k)G~~lW^k&g57*h@4w&FH?L*tJJL|poD zw$=CySD$OEFn#|)SCsz^fg#>sB;T$CP^W-#^u2lz9;ox}gzOD!y6DtKTlV6cEUhyT zF-21-7!B@>;?_q-13>nnWAj{h`LM}B+l1KeQYFSZ!!feoCkoZwa3a1-bs zQn&@%JD31}p-NH%NSV*Kc}k8N2L(3LRo(+&)Oji9KEs#&3nS66VB0~)`AaHVMjFP0&`kT;wbqk1v0h=hd`FGSLfpaFsJy9is zQ7jm=jB)p$WPj$1#twz5a7aV645S|Kiy8$q_M&EP!DzoY$TO|SWWoe4+1`&kQE=Vd z>oAOJ+5o##cU)1|`IO@8gW`7C?C=i{P%pcce$vuFo)idl$R6dzPw0Yf`jsjPXSEa` zl~$R8rl5%DWj|dtX;tmiE|V}wWunOVnG9J2I!rRj1gwln4g+bJfj`p8481Yj_#Tg^ z4TGu_J!X^}QmZ0$FCEZNhvhRCYjQ(=e4#Oh`EB&XE+L1#{fhsnz2qQ?eY1qrHP*t` z$h&sedhcN{ub!Uv;A5v1yE{hKsbWX`z>m2wK|rFXCUyyIas3hLc&{(5(PP=xX6T;E zT7mxMf1vRxAhxldDl&4SWO9x$bmZp}&&NY*FGFV#h3X2f#AsCR6bR9h_arDjoW}5v z+P5!2);Q#GEIFodjK?e>{p0{GsXjaMYw@F##FCTCjIJFxa8RH{)HNz&BFO!nnk#2I zP0JuL$@XFc^)=<&39E=7JZ1(gObZ!~w^Pm{5IG4M48dsi@8rEdMOyEQ#4JTCU-7h0 zsvLw-oxc#OJ%wrF*mnxFC8ZSo0)R@M;`%$CQ$Ay)Ba&x~tfu=HQ3mW@XsRrkh1Yn5 zNprAI@vB+DuR{zHB3YIfBPZ9_e=aqk)>fz5IAF9Z53bCG39sCfo+DOFD({i}{R)xa zmDk{|c#^x%_(#@87oCx(*Hd%*Pnror*I@L>D*+}H*&a`*9q%9x}wsHv5dqw1Ob~gVI z4L>m^iB<8fL?^ZPtOFv1R~BwtV~^rV$E5DrKhrl5vifrK;UXYFlGrKg!f~83{`yRe zQJDip>bt9PJ)495Wb?Hkk{4b79bU0gKhqgNFX4$f^*Fk#fviODcZE0YPm@F z&u;-dovB{*bJ})}cbkO!Wv>@Jkv8Yi+9@eLY&oBAVsPA5o5(1^!^43J_S%VnWj^u4 z!NYL{jpf%s+e8`^9ZrRB+ayKI5@SS5>rZCrkUt!XjLzuegE2-KJ|QQi&U(lLd>j23 z+|Pv5hs{_#jJVuYex!dsAx(yN99=m_r6>kyLTZcgkO*>wC@Mj0qO(@MWi443^Bf88 zwkCkW^cl7Dd@A}S3A?>#z;F2b+k7d}sBGcMm%+Ku*$b)D6y zQqrlS{Rk}6dq&5ap+T}k7wv9VV;=SaIOA3QPg+0K9aH*BODwkT@{R?I@-EMIliC%o z8U^%a`1O_-Jm^5g!Q3XP2qLNJUy3}U_*EGpkv%uXv;)J6tS zKIAfzPlu!r`BwnaIjLM`)$J<@d&_yKEae(})=hK2^%W}NF^o8`#U$tQocsjFL<=FM z(dQ!ijeo45&xLp1whNg&=Y zSwOb=RVdl#m9kN6NRJK-(Fl38WBGY@QBe-8)QDs3yZRN7_AepJk~{|9g`b5P;CMzi z8klvSmQ!OAp{(57-*uF#i41;c!WtIH+r5bKBwHm)9$!eVZ5D2u6yF56U9l_hCGi}< zgI4EyvRkSe-~&h|(^Ut4`{o0x&Y`TTC#tT2u`giJUOn(}pe}8Xj5@FwL!(2mk2bmb z?_LjQgB_bIVth51>}G@CUH|0b^?p8#osVldp2(?5DfHVI=}!7me>@%G$I^D&qStDH zIvfh&4M8BDzE?iMrrKFUqH>gp@&}%UtV%9vlNw}^BOEh|d%C4NGGL!?TGKhVl@WV2 zYXJa>r5%n1Y@XMznva(koAMl`%3?PluG^hyya|((+~_w|5Ks>M(9l+PK6s5bUfG%C zgpJ!AZ0Op$kA~g1l&%p(pM{#k8BlAXY;0FBk|mBj96G*4szxkSZl0EE8%j`bQW|eJ z=pE`k-CXEjWXuzOkL}}sWyZGN-=3aldW?qH?ng1ACe3l|h1AbNjc1?Vx$t9bBxar-k5Gv4LV-j$!k_FEF%fa!s8?d>KH;sGK<4Xol1iX98W9f^lrL^jWB1 zW3!RkaZlflkR+uZUZsw)AUQXt8j*vf|?l0uJez&Z;h{zRX~KqR5Ts_iyx@fHt4k|$!Zr` z@~1v0=z_8t$#sIK|I}k^oxr{f*)g@OPpu2dvakunZiEk>Z~K)3p0jbda08(3)eTr; z!eu$hKk)GQe4b%b1?)VxPkkfSd~%FWUi~cNV4n^YP?0|JZLt&lUre24SX6EI_Gg9x zh8{uzsez#sDT9syhEPEi6{Hc6Zl!A|0g*;RQo&o04(aZY6r{U{9=hK>_x=2j6qxZbPyPIAc?yhw9d)}7v0Ref)!{=c!KKkx$h znvwAKzZ*jX7G7nttDHwMsFoUs-2V1)fFoN3%`m=Ntkg*Y9rb=`b9p!_c8LVAlb7uFc3Dn^EvGD8f|dA z^t}CV;x`%FW_bfvpWM^e9&yqlV+n4m z+IFy!?zFIDTOb-^?(+DJAk)05X=BWnzFz@|(!nVb+mgYwOCgQIv+oSzFekRY`F|dNSG#(iE+hEyJzm_4;`RQIh0|z+e_=Ic#Q*1L zU84bW_O|}T$0Xq+nr%@p(acGTZtiRDvs?z(h!og5(5!03|3$yg|J0((Vw~~nvbVsR z;8e+l+T@VEy>HxD;TyFH>k;9lA?e>VnZ4G@u}oH%+<+fxDAe%yW+HD$ops-Gtl=y( za(^OBV*YDtV`kFjcCNbgCMMYgD91z~v`6fV6N3q7otUF2XXkOwQ+uFOry(^pE;!$$ zy~AnwC+n?kE9Vxk?!5=6JVI7Z*3S~k%)fKKLwXUj|JOVP$RSo?J6xyr?=jeGj?_^}DcXc{^j-oikHK+iIz+CJHt?6+GjOH zbf|#e7FV5{tlw-}W*yt_-8%V!S^0XH-aDsd$;ak!1J|Jxk}WHBXcKz&3%K>PRrCVi z?+!L=Rua0q8Zs4(Y`CZ~ev>1W458t?#+xP~L7a}_GWS>UVsM%)8R)ZY(ywrXGtEQMngWW27Ui12RYX5bw7;U&Q=mM}c7ls; zY*EkP*gvC&JBN1u7c~(~h>Y)C0otvU5cQ-ASQqHANT`kRLw@Jw&ssNi zGt-}|dl!bUnO~kgi;!0E-vhF{e3fO*X1unhu8UW)(g4K%754E7M9wEq@~NIF{sJG3!o$0HM&t3Ifp@>`G|NE)7)oT&^O{!MeXG>3Ac9MZA5Nvz6|D)oqmx(O>EqJM@Bv-geCWU&15(zWio|NJ*p@SF6Z&R zx+q)Lc#N?L6D(r1_(fz~Krb|ZHNp4 z7I=SW)-63ejo42m@xSkW20fl1L|=CAzrI(RV;5ixe2?mIX^UEdgF`r+B5G+MavIC? zr;11L=Yf+JAjpKZe4tvkVnN#)5<4O6;kQXc0>y|>TLdz9xkh?-7KMvFvy;1?0$T#1 zu#pJK?bqCc94Fm5f0lGiC-jKCjZ0ljwh4v`?9e)%D&=+MHZjtkV+CsNkmQ(o-|Ogp zXC#U7TF^z&$eO>)ua<2%(>D8`z7dv=pYOJ1QX2MCcj9h%94J=8*~@_fB4HKW0623K zsM;-S1h}!~;t@x;3SHk7*!Q9XSKpchtj7P>9@_y8+W^1D|6F#gaMaj#{rUF4^32St zreeSxM`VP1ofh5%_Qk!0E08Wab*SNkG>0Wny;%oVjs|klg0ad4(T1%|pd3UUT9s{Khy!i zkOwpuTrb0fc5f_M7gYTdXK5B&g01*PONKlAVpOr3<{2-@X06NgpXF>V5ctMEg)LtK zr&0w<6xxW-BFQ`*`AGNkrnZtuKqY$tKs2}vxZ7Qd>*k~1DP87s{|o$fRijz_hs9ko zoezxfzEnAv8*o2p5opy-!;@~lKZ<=pt)2<8Q7BN;xsluF8PUl^A^h>p`XDf~Dulc~G%?Er_O3JT=1o1k;aAgutMT8UJ`jF>T^#>N7JFFndu)kFccCtO z)@52!A;bpI)ed#tQ~rHVJ^_lOvOsS8|7OK*&?pON6{BUCPV`gGhcMo6x2HHm3cYZ< zGYvc5JA7?khnj8__7_H-oHVzx#8gU!*wHtIl@5ZMhaZVXR*rdol>{bOhKh4Gc$!Pm zZqa_6p<~;Pk*TV8JyRIGto(_xvrrJX`we+268QOY0$yL*eJ7VLPxas-cp^{_Nw7lQ z7|HuA!Bbcs9w>cAi)K{`Pu$?KF+mbZv9WrOa`=9NW>5ZV?5J|lyN}z8j`Yepkn{EK zXrd1eCue9vSeW&GdBx3_K>T+h9dUq-aM3aKZd=xTTl-|Uey9HYXZ_Wy@c+GHNdT)+ zD!lu@oWMZ{$k?^}_K%l_=M$q7F^7nMekyOfHAg!IigtdL3c2^~6ll`uAhs_t!L_4V z6v+}uwM3z>ZrEsN&YN-~8kpBT*58U;fV$@r8%X<<*Rwg00#Jx@3xG%uu5Ag=w17c9 zkz^qPxID_PB|UaIn9RMM#7d!(y-c>tY`FDuT*XBHUXv% z{-Lg=n2LHZPr%p+ABP2yNwqj;f@?GPeVu>xx&J7GN+9r3#vZW*OkwemT1YUNnFyM9 z_GeuiSJq>qpv1o%nn7FpqXxMWiHlJ4< z1+~Dz$}G+=o$;uo@8YSmK$!aNA_Wf|@R*mDMATK|A#U=4?xQ0eKE}--R?Z9x~Zwv$tD#)I$g-L+$t{cI}koEOR1@Mnl6CP#E%z=4F) zz0invXLYkOA^+I!?KHoMauy+>GEVn!Z=Qb9t`VHf3XOzX~iaY_KMINHM-^c;NB*xX4$j&}%heB3-NHBcVA<$3a}hV2yVc~VrWeSJU? zp=5(k%L>N-2Q|Bkf87Pmb;hEN_7IJ^?t_Z-um1J&sc2fxYb$yLDkGE+=}e(-LSD*7 zSXZ&Jz*JKueyK9sDsMOQZHaRvEG)YJaIbE85iwv}+A9*2jY~wjHk(Y0Oj3dmf70%0 z21kBo|78P{4~^Q#77jEx4Z1d*Pt*Ji3?y@wTZz`6@p#9WvLCYVBYD%zl&1LC;bF%^ z-4H*(-T4>oH5NkJ%2rHIW7^s{tLznt5xd9H%$iBCurqG|67BBBAU7!LJ(Ms8`LU*p z6zME;n&4s{<0!Na#4IWa!~35!xBy4r3h>nPE^OiRk4QE=s*d`-5}^$`tl?c{uynYK zn3jFbd2e@PlN9k=rWdfgnWAXz|C+5Yc(x+r9d~}}*MTsETql9k$Xynogyy<(+wT=M zv~d31UMuHut8n$SlLIsG@rHc@TvQ$<{~+4%tDsa@r+Jios|TKKG~*IDMfpDh5V8ZNrDr{M6>Sb>X z?Mr=9rLi2Cr8hOWf>M6$&xGLbS4ES=i=QH3RQK*ch>aU(t6l}>?V1L$_ZPnSxH@y& zaEeNGJkLg2d{mIOB3w_*{`ZUibo@CH0s_D6LNe)|M;_D&j1biFne+m@wYAFAC!}FF zNbsfMB~~kJ^jRA3qB08!;9%x?@_<8*I~o`9al_@4l-VtBSPEbwd#hm^_|JnaR?TvY!BcbKW;%c;ENq z^O=XV@$RQ>`^YtUlTV~YsrjANo-pZV`)%-KfU31}@>#C*+fCa&*JgoAYU+X>!KDwN zh10+PMBg8cvU}YW$bdk7y331P*F6v}XgiGgdZa#v#_-aM)%5-2q5oVp)qz^ad9RJ0 zo_!Cn(>TmcLRzC6-a_Q+ntvYf3q^X|I)3wR@lbPhMZA%yFFf=T8ndhiH1WrNJ`YxU z@YocF2E5ML&@baDqY5kIxOnaz1zY82z-Mv#$Y2T|7K(;ROFu)D%skz zgCDZ`otmjj_D~Z@Hy(=|$0?dcdkG&x38^GJ;Q&`9YYg^*n&6GpjLEU> z%%K^R?pW4NNNu^1(K~XcWUuCLOR-TlTeJjMF5g%^=by?|Ze%gd$dzo2J_)+KZcG)+ z2?LMDk;JepZ@ir&P6vj)1#Xu?3vf9l!Vtdx{w3o~ek}v{w>h)>wx4fJT6`8PD1E*b z>G0F+(tp<9hnj?MpZ>ou?K5S-<;M~(^%UxXYK$ykv+XMWtmOu3(?Zg!M8CEQRJlhI zr}bHj?KJ1w0!bn-*jyUwhIrN)g_C2ZW*(&`GoAyK#5>NbvY7;6S_M~NLJ3|N`+cXC zzjitz+G;g~nFCw5i;qxr%<$|)EH-iPP|5QiaL;HvTlR~qpW}Iqow+;UkQVcRrD?RD ztqi0{L`+O!U5F7mhz2POyuuuH86$8sb*yetyZa>ty}nTtuFr>zIY`?S*$S z@yh0&>(>;|6?(D16-q-}I;9&nE~%G$qPdZKsux=ipEwNtLo(vKFY5cEK4&h8nopD3 zI82;QxUi`cvv@Y^Yf`sq;o2bFu!<8lOz5p1Z1@s9rYh(Q0&{kZ6W+cv-g z*;~}(p$+L0zvRnh1|*@kTW<5<`t9{w>XvSTvS)*l@lga>T-d=o_d;wsH;C(=dQFkp z|8Rm4HzSz|v=t=WGwz2|LMg?UqG;NO`fl}4yrUTEN)EetT)^%mZwI$&*02$W82Xw| zjLfsL^9dHa5w=rjLLA+*VQ<>QIfJ*szxA&< zzIpp^gsb)^DO_GJ{KlZm=C8#xmxHQ8L)Atk^rI`Q2zGy)_HH+9T3B9w4l%hIn=lsr zNk^>0vVqYhzo2ydJ^}`}@aNdH*Ni+G6E^Ql!TtWU;6U2=*gg0DDHAtk2)*-KtWVkF zt?h?=nLhLWLR!9=sb^5ZOI+>L&aZH@tra}{>^1IRNWwLv8P!b!$X?4W*)$(F63|yV z;sERm1nBF(< z1B|}$mP>F{bCfG*xjt@6ifm?C}k1p4Yz}qqKC3Ee*X@iW{i>n^-A} zA4YJvjk*tcPl9sFn^ZL7)%INd^=Jv?4UN7Fh^z%mjIF%>*kID}Cf)jQWBUcWiLnac9)` z_qz_bMJsGl&<2=KwV*)u_ustR9)5nXcRE!%s?PzJZS{%c%98)RL*=s@fMuFJQDR4{ zgs{E;%G7BTCBR9%F1$Bbjq|>o>1)4X7)3nOgSYwz8C6B9zWx~<;=r1w#>uz&<_SCq zPa2#6>^b_~59DEP0^EN;(iW1{DZPs-M%0CHedBGPdFLV+@@>R@8wj4rn?~=Qy|d3N zop!GUhK^XA0q&V+zgtWwNcd!C8nF)J0%NZXJhxuS8^!_5hD(uhMlcE&M9BWFvsA`P zx8Xt!vC>)h&UTE`{elA4R%|06yt%_oBfn8+IKZ}OSMceT+gO*9OZJ~xV(?MgaqSOP zm-v2f+efV+s#>3pn}?Gfov8bt6v*8K(6RePbq2vE-ftv5FJ|H8PXTKgcH??dlzQ@- zrI}#djPgUhsC7m0wq1YkLqE~^K~?f1bwjTm@XUXGq6&M|4scZ=VA%nmDK68k_$!h) zJh)ez9W53SMJl@ngJ@_R2NE%&kNhuA{p?h?lV9`73jQ$3B2ChGdKnTlW+=NIp2e<0 zH`Iw_I1(w3T@7Oe?_txlYXVie1H3%iYjN{!+}zR)0A0Ac_C@V}rwe?-<A(Q;ydZJ{_0qPR{QwPh!kU;uHCoq|XKSy~C2w8bN5|nD3exfpB0GjoqrCo~Jr3HO z6HA|@b22=*VsSr-x1y1Ewse2#XgPmXt zxj3aaG`seX?rzzJJSYi&>9LZ=1-U!*B#}(erPO@p=apRnZNx+}fQcqizAuXDJS=c0 zuImXY^LcHj5keDF;5#GCR;%l|^^2Ih4!IXkeuFJC<2;7H*{+Q_c@S#MBelG}exF@_ zX^eL0%nC~Gx7>8>%GHK;@4zC;10koA{?vY7Ws6>jeqGQdKnI=PXpKJ?9x_6!ThT%K zq+`uUZeq>DRHqs!sN_B8RDORqsuhFt2S#PawOVvkD~}M)O|#;zICpuvcy3 zAvHa-LGQ|&G$-p%as@R}AE`yZVH%Ap8iaLCG-T2g7o`~-K}Fi0yEdA^PS8>RD+lge zkM)Er#v2Z)m^Z;bjPnDLnuiZ22DZfKGoQMZRurqBakM^mi-}~aPQSK)A7;1m1loQR z&`jI^?*EM=$ldOu^iDnGfG*+4q3tF{OUn2P-Hxzd`<2KXW zo43|n6M^xZ{lI7Wr)FJW67U3sSniP4N%6RlM$9VB!!12+m1!XF z+ZoO2N+<*qeaK#?g^to><*0x z8q)^--G;gL*vQukq`Momdr|`+IyRo9XNJ#@Z3GN*`L_t`ZEl2mr_mOd0k7}RGNLOv ztN$Wi8Iu21WxWc30=zD_c3Ix8R#xeb+fgsu z01x^Qm@D&(B)9&K<&UI>H2aOFg>Z3y`qowGgEn9b)dq^OEdES_LD9o=Nq+^y>p&f6 z>*Q<)erT~!I$q=Uz#)u5}-+ZI0r0q6;$#2~=`{V48C25DNcy#tw zEoaBBZG0IQ+f>ljsS;#fq0=H^%<)qct&amEa9M3nuA!_G1HL=joJW?|0HVQcxvH7P zF8_>n*$F>3H6g=aT;2Zrp7&Lt3&e2oFEebi;Zf{2RX(w`pE#CL(JU&b{-7>?H%%q} zE#nj0xLqupx$|BvM@S$hiv_KcI`O=4-=d+|2db=XD0uTcS9O^7NHo4{|0}W)$=X`< z%C_~}s?GiGC2@}iJ!S52xJ~)E*$7^VM?iE(MmC&xz{2M_>fS%$7Pf&MEONsl)Q_Qv zk&wFMprYFEzW!3+7N$rk;=RMPpY&Br&Pt{v3_CxCSkpY&#b;jm(s%N*!~GkJuO|JY zm|h8o##3}ZhRIMj2B#m5Q&o#R3wz)4zSQ89)E((o1!hV_x~Mvur^p!Z^_DAO;SDKHhw&;V%VkLe)+wAebwj z;P!^UOntJzL6Enwf0Pa~^;z5tJ)uT-0#z*(B_XTcdp;^N^gBP0^3n(7u zv`Av>2VN>9`7`LzV?l z8k$_#%&BA*?ptw|&F?)p15A$$uZZ&6124{)OmZb)p$1nnMvXGQCJuk?O3hckT+_qu zAn)#KJgqq+qc`w8OqA;VXI}M6Rzp;HMIS@VB-No}b9^0mN)A-8`qbQ;+k}zXe0WS- z(Gs3Z*yU*kd=`L?>|SIJNrlf6^+RYu+689+<%iW7s=I}}F-yuXc&X%t6SLH0hp_VT z{;#3)&&)+-fBQ5>Gn>MqO{l)fAxv)>K&7Y*X_RIrxdJ7jT|}nC>62xs1IDLR(M%l$C0kk$a+gbQrvWID}b;=p%21 zG?ry@szJ(L6{hm*U5mkX7rT6CThk27E00(8yP{AOjFVC4OXA%3AOEUGD zSwHehgxb5~$}E}dSjr@mdNbh1bC6pz+22jq)aiVzrKal->$KAA1f#`ksORXdHW1V0 ztP6liO*n;IMLrQ8AepXBhkc@e0ss{osgBJyI2_g9`qU8E4-v$CB6nn>t?ok?eKVO& zO?IZ0z-j(94mm@iT{t?qUTI)h0aaw2k!5|!8PuD8KDGK0vp#Gv15C0^y93o<1793P znBvk6YTELJYKnDQnx$##4!fPpTUHts(ZuMJxED`v$G#$=*eO2_nFcWXjkU=5*kKvt zkCpqwo)!8P%1hC1J2c5b!rHtKzY?bu0mrw=2GRZ-A6ipgzI+Z_rI7Vk@e~>o^nReD5C?zLI^s}E;8#~JO=jzP zrDXR>rm^DcI>qGjFR@Fbwqaa9zA!YQ$G48?%HM0nnBS6t<_)x#PDPZt z3)-Y*y0*QW|9Yq@#k4~?)O)V>nsU?vQx0Foo2uOQsTX%;jt@PD>&Qax)7a2~#?3N? zSXyTS-9`3H$&Te-)?LeweiQgA01evZWmm54l-w**V4s|k_T`z8OqSWOzvyk7jcBM! zv~Rrm7XDJKDx$1e`8*=pG!u$Tn!01ddxls^Dr0#q6XE`|fhlmf| zMsMJc-;w{YX|(!}(m2WsM3F<9BexvB1K@MT3)HbrMTtr{n~&#L`da^_4-ued8F$lpkJqhRCFGGgUct0`v*tiOhZ_8(F?H1TsI!Qbs>fo%^x{Q<&E{RWSmLdsf2`I}rB zTc$@2>gn?U5?#5b6~q+yociuw#p{mBy|LLZYSS@`W{=V@4Zl8hHzLv9!N_2PLt6`q zE0W8TfBkV&lXe*VAVUpKi@dVRy?WYBM(f{IOWJQQW@}l-kB=l6nc_9hk`wa{BnEYn zowQU1Fgz1pJ=F<^3iU^3-Sb(BCe7-O{IOKc_CmI#C3TpeB8a?5-<^|qzEr7p|Ld^$ z)TJKH1`?qr5oDbU^=zg38}hw%e?wZn71qr_u}eAr0clAanhx+58P^wrls3=Kr2Cqq z0-@|*LrQCFu_C5)r;9l&6fP8BmDAKJ5BofQ_4e}#I3TAycVMP7&h8{>l4c8xKtr_8? zYGS`ooDPhB2Tf7Cs(+)%%K(@oC8d+s=#xJ?&LrxM%3kjIk}RmFSpRvrh5hmF>4(O` z;W1tljEX9U?O9eURW{qUne16Uc4Jw>GXP%H;x2eQE^th`Gd{6BqO)H6_rCu16xfR+JD0Ny`tuqL8&on1C4{CtgTL#W+`Jr` zJ@E{=`q}d^*?LcOnIY|LJ8iLZ^%nWO&5QOmret|^acl;={Dpo=aEGqpZ*9~?c;H@b zi(={~I%I^x7fH5FONsWEIy1Qn7z9J)YMvVy>U=NKH|TOV(UAQ#hS@CyjQxtxTaVrp znk&XR3N$MCZU%oTBU3PrW7zeDT+CA=3HrF)L$!87cSVgcwgt**UngSm{zs$tc+l*7 zso*kWVFX;(`0uS*K)NBjjSHCF4yMrF&5VHUp>gqN;2Y(b2VyJFbzeTJ>AbNJ1h-I^ z^>_r7nSQSkw(}#lqdNvzHhXu$`jdqP3Z4NSuCWjB-77K5dpXR;VHr3JPu~w4EE>na zas_SdL+X*L%#E5?hqHaX<+6;F$iBf;oBFRV{t4 zi**O`d@kj3hS;B228T_sc3`p^Vr9Bar^&p#Ye7eVb2FE6HSYTOB&~R(sHT#yn7n8HAOGdeR9HBS}8cT zc1E(yof%mMln=>FoTTMHo}FE%jjh^0Nn*$uR32Ua6JZV$JXE}_r`&Y!9u;VtwYaz* zywh+F)xGQc*rrmc^0gm{CU(fY9II|LRB-8XEJb$cpG@DdyJB9Wm=N zX{!ir*7f~hr7X#`|1Ta_2G0YM$t(R1L~kR{4z3D`&c7}`w>eh$z-#0{bR}Dk)NklefDqo=%5bCQ$5sF4%Y5f3I$e%_i_qPl0r+fQNz>*#VArG3Nm)Ty z)XitV^xJAcn|-R1GZ2UoP1nY=)ia$ljF;}4HE`D|Ja0~sr-0g9Wfk$RqHz8;1!}u9 zubR;pk>+(qc1kGN4W9Gf;=O+{RQ)%in;R*PvA~tZY|XF`__k%k>ZHPvf>l1|g&-^H>v0X@zNlR0`A`4BTa%3lcV z$qX8l1UEj^eG}YRo8(gajTk41V^SII82i~`-;YrxcK=4^O-gu|j7W-y2cv3NJD#WD z-O1;TgKQP}X*aTU{?N)WFyzj4BD`7el(n5)`pOSVxlZ5Rq$Le@cpEF-^pXFS**42j z-xJBm-Bv@L3%wex*jdv9U*_7e6c5syBYsm@e!x?VCk_ zRUr7ZawFu0R4|d4TbdUJv>Ghs3LSftY(D=yeRLTiZbHnnMfl?SL1-zFS7(Ka_!1!p zM$Rx#cz?{Io@lHESURLp|MULe6)~{)1a#K~iAi~f`tH4kVsluYk>D+@02h`MRB;od zs4Qa0#t7b5l$Uq&piEY6n#-%a!qUCRS)m7Hkg;3Ff>@fzhHugfN*A(h8lO8rvL&Bn zGCRA(%YYbVM~j`!oi*ZXApuZ0s$M2rwlg5zIv7QmRHs!i;)fZlHAD>TwedI;lwZaQ z8;O-vaVNhbJbS@PDqCGl*z=Qg#*_tFoArVoSM5^BE%Lp-oJia9&HW{Ufe}A)+#?eg z1EKqcQ(t^%o!{#d6F?rFX)5=3MehZDns`;@d^n<&aILh}qoLv*Q&5=aQfQfBX|!Vn zoJY?J+b^bkR*1eXvPgrBrAD!HnS}!}tG;-J{Td?6?Y1NWMt8ZvI$*!b#^(8uT3rW8 zawwD%bTww(s`{M^Fwr_<5`A*Taw%{4gu zNdwJ}Ot7?;jGp~!<3Zwkig{EEQnnn+c8c3!mOktKu-pi#a(4unTQnbM> zIY<@rSx~JTWEh)HAJ)Zb531V|!@;1n@VlMSM4ja2|UVREzgIR^aG$Drnv!vP_R}UbkPK3_pCb{2}m&*?Pq;nKkp9Z0AQ4g8y}QfZe<9TcGllSubQCK zi`fyRm@r##d%2IB(z;11Z*aaQk>7kIA&0q~bpyF< zgPTYoSp?bEAM?8ieiKAubEJ;PGM)AyoM0<3=6sOaLEWs8x$)+l$IbIr(K%7vknE&0 zQTEOV<*YN1ao{@hZ-4>;IK(Wa}QHC|o@DoRtN8g3@hyXDHy9;v8Xv%b0^%F19%`z530! zf_!hseM}Ekv@s>PNb!|K8cvl+j7lyDBq-i{QflwQ#cvcc=7T#4PmriKKhlwC5;p4o zXIQdy*QeuYmoj~{sBW+mmHMF&(^gUdE456q?J>r?Vc8M1&`lU6O+|G$YUd9=?)+%q z{eElN@UrpUoThjFRHq49ssz@&o$z$+#dvp%q3_F%-zoHd%2yViUQpSBk^H}fXS`&x z_oCaNn4_4qtIxKt5Ws1Tq?0~T@wvzNXSmHRiiAi)?ea4Z%On>vS=?a`b;@ab^{3oC zxBEV?h35cpLW^ARPj>5$ExD^M0dw>sZTboN^p-LRovxR1tAi9%SrC8`GsS=!7oeB4 zT;L`kORnW}yf;nI6#Ju>6e zJx1hm`wH0jtS#68YkSst~SPP>6yKICx2(R(Qv}XBPi-4e(F5?#yP& zMVr781-LaQ+qn|-G|X;`7s@PbW)U0f5fJ(y8^k>(2{(Tb{hR@azIG`92A2t+@FulT znUI;8bf#Jp+9zTdTX>^ORkT1RR8P1Q#tNb$mJR~Jb;B`tysU)oaa~8JeUK?TtsP-I zg77}xA%8|-4lbPGJH;04Pi144SQxl;BY7Uvm{Nd5Txyn2m+tt3m01`f)F zWskbjN<{@5fXqsF&4vhx-V^Ndyl(!}jR6JMg7`D8h7#(_*3^CYpxr!S2i@S#5q+H! zi`nXJ#q2&di6}}ci7b0BND)_pQq5~cT$Leu2RC@1F|Qd$_xG3D^CVLh-7hwXfU|)F z&`-*nooLqevDm#1-y*X}Y`Kl@;$$}dQ)T{O0OFTA_>S)_@dJ3rK9D7UzX*tG<6|kk zYmUa=t#Xg3q#SG-QJp&=PSD5L_I_XULpBvbAcPLN8{@;%zqAsEUx6Fmt9^Mf`g-yn z2;SgV53F@DDe)Q{2NHbxAS%}ID`kTBi!8DDby=7K;X2TlO{H^CG{_hN=?6VEoPQIE znyQ8|Kv90aF4#7;a#a`9>kQZ$aa7XQD;~iNQW!=LH+Hp>tSMk;Wkc6LJ)qPV8eGOF-igS+xIO#st#zzULS){FHSxWiCm}Pt z6*2Geo3=`48AszR=1#K1*TjXrB+Ffu5*;E7x%dX{0f? z_UueDPt!JQSem8KP)44m_d{v+{J#sI#J3{ZbgDpFN`2Q{EB!EK>Lalt_=;s zi=%%lmGam^P=h&MNATaEpF^YrSJ#_dcBK=I0Klcv*c7W}sgti8vEW2l@sF~{8mI(%HVT%fOm5Ao_5()V1>O!2{f|~ZCkqVO zLe>S5-R}&un>QNgFKXXkoGeD#!{B1=)0`#e2lJA%r+plvasaqT2G#aafju(P^v~OtB`=K!!1ynleNsG zv)U+DzF}MdIwuMJwWMM0Juat&BmH3Gdyh#F6%%iOnS_#IoC`k7Re)+7QIkV{#oWt- zUjyz|t*QnqNH`jL)Y{OJ8m>moVev?gdysikI#|&Q6U`a2!L-9xC7hrKH?5?DS-;zz z1j@C5T1)Hx_17N9`jfXz7h1cYpVzK^o3LL`CUVilpG9r&ilK5jf)w^(=e8SKHdBE4 z@~u*g0v2hxn6ZHXCGJjss@_7eUuz%Y*UOe-P;lZ;9d7|PrJ-wcTToOOqANE~>izjSzM6jxODhueh=^mE|=XH(o z2~w4V57cvF*#6%Wf(~mQAX8GXjGWKF3A9um9cr!b5XuLR%}3tQ=njS z8EMCnOITR|t}9Pwq7hu=;o?yKou^@10aNNRn6L^Q8xc)XjK^8ai)V-^TJr1~slJ1P zs|luO@tSEM=f!Z5FQR^!;77!Kw76`AiI)3s-5pbFvDC>LqJBwp{aEx2^7VI?xZqB| zxVPU>+E{f#>}@eP`OoBlS{!K^l!u$Mtc%ZJ?;}U4`Pt)4e4kX8>30*hnObfUbN8#C zSUf&cyoleWk~GakpvTO+dh-W4@XLt`ecqx;NkKIF>JWYrYc78EA?I6R4@t~v7f z7{KK>eEA?XvG|~%F;SqJk-!a%n9S|07I3e5yR|%fK&+~*|ApAbL>&k6-29++NJj-{82Qch^De{maUl)LOJ2k2y;rWwCB#kY5Du{XW(f1(3qaa-1g%l8KIDh;$G|2|AfwB~e5R&wQ@-(-Q<=jji_VQBenX=d>}N_gbFX zip1@^M!utkiiz#KVzF8R)5XzOX*qsyb7;NNzUAD_zJ41$$W$y zOy`#aad?wQzlRW>jga5uz^>i_9hPF)qhxaQo z?s=%6!R0DCQXB;J1+*4Xp?8x@=g>6^#VWHMg-^P(7dZenCY28FDUvAJb#8pO zzD9>-&Z<-DPWxr!ZEm10>W4SZGuXCxj2R3iCJoftO!ZIAYHu#h>5p1!GwRmk@AwG5DjGQ$b=vtx1d6GsKg)+K;Y>%(N*Ol)0y4`*HS4vHmpI8=^*Bk*8 z-cL&jE|GB*OOk-iB|`p!AaWpO>l-L|qvhillA|*9VN)%USjwzoaIa^TR_7YIF4iva8Bt`JxG)Vb!)YM}9(>9yFYb`o2=sm9V|k)sSv#OYE?Ks^h7{@v}XV%`w`1%H{f@ZW3w%ZefTVN^;t zef@4wxVjH6_HBHG$t?~pCMFhv$;2X07i`Yc`fEBu7sJ(4xOhmT z5TlKsXH!nUnI0Vjs}&~0N*wFU`Mgeh3}vzc=(%oHeywjLn6|aGrO1*fvHLS>F0-Em zNei}-3;#~AUG}+LapI}uQ1ZCJT$uh-OZAJJ>|hM4adV#!Xs&Sb|6G`w^)&t{H~BNf zZuIvjs<9SS%#9<1{{|F0kfC?SLnb&K@2Jhr{Nn?1FKc>`_GC`F2e=TcDhRH1e?D=3 zFKtr5{6?E6bYi^b(Me|{)c_w=y(X2{$GB9L#j24HAQKn4!nDQjTOT$XFERGDdyJ36 z3QJ11!k9IY#*w*YEHmvwE>8`dYFzs5-@>xi#BzVOYx()tn)Z!bg?$D~+=~`|nf_|Y z)*b(5{0FZi{W%!c*aA~HNHKr#-q~^MknASQPg#IFK6ZSKbKG@AAAxm$9xY^PzX2~D>?Rr> z@wUWR*sArX>54zdwA~2z*_4L3=Rw5|^ueFYPGEnbrx0ZyejBUjic>sjc*)b;1zy(w;X|yU?-i;->pR8Inz%PoE);DG+6sFGsw_k^@g4q z?@^NXzc0whX~>}iI*ce{^IX37Z#Tjn1Gn>A=jJO!2F#&aZdPO&qxQ=~;*w$EMWXJ{ z8=X!EPXh|ey3NepDo432JD=M16Y^_^!pZaGPm13;{R}I zWnoh34d=%V=Ew+&`j9*2`rOQ|Utsu3f*$@c3o5>+jwm<1j9j1FG>*Rkh2=1%@;g1c z-SZc747751*=T~{aNf)}cb_==Mg?Mr)mL7}Up87EsTA|~kGw){R~y9%d!eH8yok?t zt@QInZKLPQ>>_?M`K3#Ds7oLbso?akk0Xa8?hYeo6B_}Z-p^z`n10)tH`K9UT8IIA z=4a#t%7QZQUP>xU=36xQnC|g2NYoQ3EI$Q}+1I#vB#9_YhgY82IMzs4JiT-9m4120 zLdfw5tDL+~camccoBH$zU${kSel*Ox_TSuFn3nuWEUkDse=RhA*}EWe=9UQWTys;M zXmpe7`klOI^?Th1gW3&UjxHr!^HCg2`ze@!+yF1%9E^M6s=AK!!a1HM`7(pXpkcAq z9LD?NglxGFypqnR6}i4}C^v+9MM%&(N_On}Ojy>UhN;5Li>}|U^7Vy1std;5ok~4Z z9DP#x1`0*;>$R(Gjfc*`2hI`BA)t7Iyt#7OE(w^u1wju?$~&;FFJ^4cmm<&dmU4T8 zd<2hxbO7z-Hc{#v5|L(V^N(n|1aA?9 zD&e#fql+`%NBXALH+5x}f$FSiie)8q82d;!<&;oOlMbrbazHAMqt%e*?>rdLy@j|s zNsj-ubGvo0)4N~Y@mo*|If}AmM|+q5Lq&ALkGca6J*gKenH{Qp){#N@vFLI%o>Yr^ z9d=%O3}3!Lq(hdnD8~p=$KcJ1XcU1CjPU&1SsHm}AZ@5RMVfx#t zA~=ZDK<@p=RGDNy-_5^#g#k3(@-tkfJztqaCG~XCvix7ii+JbC6anwt^mzd(gr->u9t)GD28~Z)v8WX8B9Nq+FR(xEF*C#2&zX1G^~@NEVnE z@1$|UI5=E81Tg|lMZv7gi+b`g%C#8ApD`Sc4f|ZShM@t)W?(Oi&^XrhG@)w=~1&gwu}NHcO_yL}m8VYVu}W zixkXg$a2!G^G zlr2();;*$j1FJSiQy@ZbwVd{y{f5px9gRt>d?U2A``JDvn0(W*DClNSN4VnwL!5#e zpIDC`0nZ+~M9SN0Hs{O~V&cBDU5|C(;l3wMH3nwUp9jg3+uKZ}tqAo_K-TwK(h6F? zD2`b+YKqM!;%YU}H{B`y!5e!A7R8Hww2@cBwXPvhR5{4fX8h8eIIO^c^D5CCA0N9m zE-|>aDoz{|P@@D}_M2mM_Ah0!g7TR_Z-DJ^98;}2i4bthKOXs+ZRhcZ!IfR@z2Y<_ zPv$YUJAI{iElzOu6Kc{F-DgkFxfoufQ7Sj>4TI6Few_{r#KG~p{JQiA>wu;3Gn|Nu z*E>a-f24NnLU{eraIvVvMmiSnZT2v}?R#(3BeMaqh2amv!9k9Gvs||_#l633=d4(m z?b`SyQ|-lEOw}1C$KpTisZKAlwzEJ0N$A)PoPM2-W!7uPDeM0CMH081-LlzPy2TckV_qw3!-w#gf#=jbn-WqeZ$vCc6~&bS%TA)MsJsQIylKy0-6y@1=N}~8`|HzK z*9CkUGUC9;uMWQjql>C`Y#EhO71QHO5lDf7U@zH5t;>T<@UeyCxNpqso=>N`?YRB> zQzRa;wD4Yr(c~=YMRil{FgG@+iK7$;M2Tu#R`VZvf?P6!h6R?*RnWRbt?|2PJC)Dt zv=1oQCQu-i#_JrEF~Q#B9Tb5b`+jLzla{@SxjO%bXSemdj}qX^_#o)51{Bt8MqS{4 zckq$?i&N1s2+NzPXaJ%stHF%#g~s*~HPYL8_gINw8pm(PhY9-8X|y z<5o$p9$~+y&s6+ZtgL<;6vW-p`bi49)J1WGtRrKVX~Y+s<*Y%C1!uF7DoCJPSR^X( z2D5-&OCSjaQ zvK2>KheBkmHvp24D>TDUwte?Sc!M;@pZQUCj=*sCImD+|j@8#%J{20YX6eF7zlvu; zUy-l1c^2Et`O*g+AzuEHcym~$N;wBALwWa=!-K^EI;I`p(+vM7{OnHV;+a$YLUIQy zG303n7nnyZ3iY#o*WYDU%x0OMs_l)|Rjil#lVhRrI>Fh_7sgplx@MBRE%iCE-$fzA z#~Td|L*FT(pKR*09XO4&fKkRs%Uonv+76}z%_~(I@~oC?m4JAZ&GAyt%51h&f&00i zX&;&?N-J^YG7(_4R#3(*rPUivY;0_dDKGgx~_SfdzYKG-ofTA%LJ$EFpZM$tz{`%k|L zF=2_qf>?&tD=Zi}4WoB8I`Tg+M@LWu_NPo?r4clJqXJ7luCC={4-DwW!ULF7eRKI$ zg8@cpWl-r;l2}72wb-0Y&5hQpUm~;)?usF<$Bepy#yj2~T_js?c}d`Ivg<9#-;tb6 zIC~&Eo2i_QOuuDjo^+J6)#s}nrkmO8eR$+m>3i|1X}UNXOWqJ;ct$|EsQ4@5TN6I8 zfbbO1Z~3Kv-{aQU$w-JJ-0B4s#+ygh<`=xj?Y^LkQ-?X&w+G7CdAHs0$`v2nh|ea{PCfWC!9@#O#@T1qj_q9H z9Za!Ra?mtv18l?&Yma|X_h99zj>lrM_Dxt{2t;Ss_Fe(_)Tjm#rzsASr62n&)xunU z7J%Rw5Iu6(S?6SS_%24@Lg9K;h3hvbM4lCiP(W_evaqZtK5gNXv{}@;dq-tXj?jL4 zVx)jMMrFKdY^++tnCU7>m$ghT_sx?*!#BX`2vD_e)sY@$U@p7`CCV2Xg?}|B)nEvO zA_H#gdWIbfgovzm#8n!~Fm7&5I2Wp$uq&4cs6K4WOq}9Ay}pzBXHsI=Gdz@8m~rjD z1jV_VTr($Fn&x%{7(~O=V?8Tb!%n@9X^B!MzviQMhzqtzRbR2WHl6o9!sprZ-hzq? z=BVcAvpOuV4;0QU@I25#q%CVvVj#r&UFG$02-PqTb8`Tw@e!72_oJXQGgGop9s=-g1@u#-n*dM$c4P%wi?0|Xo-V6$8iM5o3)rVKv{kBVtJ zAN3GMdxK`X<)DteD(5FH#R0qdp99Yp14T1~YExfv-zov;{ot3QgzmBDBk&W6ejVE{ zIr1U??-rQ@51P~vEJp)fHLY^=HnLVeil$4zR5a!Vs7!_syhKtZ+a`4z1=dzz|1?Jp zOB+Shfr$13bR|jOuG?cFNtUR=()%g>lsgsbr|)656EOzxb`M3FaRxU!$e7LdWlmr& zfNu6mQ&?jjr1UukgGY%E#Zli>Gtg2;zm(UNuIJ0NaO~IG2&Z{Ok9Hoc(do%p!rjWP%)boy}ETRCc-U>hlV5PXQhA znm)5SfmVWfk zFI{2WXE9?mx}krDv(J1vB4YPdP;zNlI@tE~1fe>;fJ>hY zif4#XU_!#6)55cQa?GK}+*|DM_{SzXXyEwvt7;7t!o>w|Pxp08AExF`t=`_%>iagy zG%xGfu9Q#f24**sD@ho~LGo$gZBgX~-n2JrPyVXAt!Gb5`0vlVidn_*IkC_<_4y{X zVHAc`P6t)G3#GUu)VLJ-cz2pZOrdY_&(j?Z>)KCBBmE0NIu1-HQDCpD%|tp&1!}z~ z))Z^#y^QcR>NZQ=y&&KH$Mugp?O{QRX65fGpdiHwuJ3=Pbe8!5l2hv|O6?T(T##$V z*40G0xhn;`&iT{c^frh0&-+|}I?ZbeuQn`A z5%4qb{Svmkknb}!A)-P%gX?Pn>q`;2lKhz-+=xC!B z_E~;#Wm4z$*BP6m_h#V(B`FfhYA0+}8>=elGLRnS8M{J=&66NFLRz_ha#SeSyS_wvn|tMZ{p0e zJeIqM#hKOGW_}hfM@QXyoyI9JEGx#G<(0vN!6%v8X~sVs;PWsGvaQNFF+GML)NK5P z`nSIN@lhcvaoN+6_lE+iv8r`?#9LNBV}WbH+?@9?yI0BqzKI zTY6WR2XZnML|oZq0Y^VVUl*7q>% zX@fs&$@>_guVevz%Vj>tDCr)@=vzCikKmi2;7*Z7dWNQTx|Ws9pmq zrgs)@kxeWV;m?9WJ!5x4aLfX+;EFobl3)PVyJ*irq?B{T{5TF*4!P4i#5P8Xa#(a$ z`ZL`>x~RNg)mVW`u#~RSrJARfb;}T%y3V-y-}O;!RZ76GfS9dgpnALILScuHTIXm$ zuPnef@g~}Cbg3Ab{+d9q#|^|b1`#;TCMX<3^teLt!spd6UGNdn(JX@6GLqLxvn{ZaU~ z&60W@OO;}-?*7gnq!taaT-uLKk3x(qL zmStx*{nUgVCLJln%bd2>ug8j+@}1@}Q)l{x!%>eubh)jq_2s0NSroHWfds*sduTO_ z=8>^1f?;_aHbimfogut~JRIf*CS!8+lx{Iio?+wbMys3d@Pu`Vhr%sE^7G9w8}K+ zr}8ITP9k3LN(UWVYUwT}?&TWy`Y~DW|7o6ugwCbFP3l0sFGl?^mBYCN595y_Gk>fp zp~i*Zn!-PDHjv-l!;%$D!pah>AK_80k96$ zx9$m{@?yfOk^HcM4RUv&4g5V>#qtC4vNYv3sms9S!$>)aM$bD$Ae7OD;Ia+S>}*8! z)`aYnd^-eG1lV)svqF;_?sdw_A)Zd|h@j~utkqPbv(ihRQylvE}=>eWgpS@Eqlz! zp2)ajJ-N|vem27rO6ARj2j_K$GVE~|C|c-*eV=bD`yBih6zuQ=l(#vrC1=&6O$6$g zd`0z4L+{@3bo;8q{V$4l>wWAO<;!=HY)wOk-YQ=L?Eo?Ccuywar}HWjV&>rW z+iWDu8Ts(?+Y%UkL0YLnzw|Ip3gd!S^O*dwm#kLftlya6Dw}QA-8n?$^)aha1I8UT zc!vjU87pnewVq0)b&uVAEY<@|278}A1d*yFmPu=Tw02_f@w>^mp-CeBrZn05uEEqEw{$c7OI-a3V*qvAWbFxdqX|j|6Um~_7xd`wsGFDX zer7~8?y89Hs9HsfS#+^5?^80n`2v%ak2w{8%E|vUhXwo0LYl78XPTwosAk+QVyOQk zBnbyWBmA#YTNuPZNflVwqQsX-i#Q<7p+JLORk?O-LYK=Sz_SSDKEAhj_uR@;E62O{ z`Kb4@fqzdDGz4=jD0mYlp3bjgV*ADu$bGawi?m-oO|)KzvQtlgT?XkTMR%^UchyItuoRy&uVJMu+Uai=Y)(^Kqi00;_?dPw5~hw>=FY7172o5t^5;{vNgQya&p& zr`}scAwUh-%UJ5?m60eI-f-Nkqoii*4ST zq&huF(*F6&bm-5M&=o?(SM2q} zFQIBP_fA`1^fY0X0QZ?0(rq?ej-@AjuzB#4cWUx6o4KEJQYn2e|1N_tH?U};gnO*g zm~zWHWiI6&3pdE=lX7~ON12GO@M~d}r*^p?wEcjgL&#hc61#Zm7*vhDkE7P;yGDmy z%HLM3pICI0akP5CixXlgv7&Igr>PYQV$58cA9w@s)Q^#|FPPxj+MMe}R9Kt!c3c5n ziHJjMQAGj>EOeAaJ~TBd~5S1fFouEnK6Pl*b(gdfKPVo%jn?;<;# z#s+?9@%d~<)}HWPKFoUcwud8zO+;mxP*{!5k19=D7tqk)=uyi$9{`YqXWN$<`Ygzd z^S1kdKdJnGN-83ddZlODSjPi2>wk6eQYduONw{jNJLWi*O1(YE#Fpf?ZVveCT|3v3 z+^lB`Ku%w1L9uVw8g}{awx&M)wbpd_3*IIGuE{z}-2n12l6myiz%XLXZ4Z0ZP=u4< zPr$9jSD7^g-2yYGBvO;Wfk7a`6`JP9%gqumrXJ1ZLXQ$#HRVs6JCfEhc)mVr@h`n= zDzGOD1r(qN+zT4WoFSX~_qwlOhwFXP;8(Xmwz>{hn2MRVwM%Iz{K29<(%?r|7}so6 zX5V#o@%ZJ)VEW}T5TeZ}-nCtptS(=c`SmRA-fi80qrnW;nhHr&{&hJ*j>OBr6!a|r zH*TLSMd=6%ileNlmOH&SBDYz#_zVOnUm_5QKQav24i}H9=6|105md^GV-!&6-cQOb zvm6(RxbhRMm1>--FQWv1FV;%>Bm>HLD>avRwo-idvw+Dd94pq^oYdmn@_~j)nH(K? z6@Gs~uX>)ZsA0HYnnLWvJ?MrRH1mQh3-gMnij+Mm;#C}#9_W+n13)9j>uIq0GWsAU z1W2bPtQON2{vGv1-@(7z?l@&+n4KXA>}x4F$2yeorbx z3!{pUvi97s_qf)_0o_%_N}IC`#1|2g;_i*M+;7BR=n}6pK)*>~z94L&R4^FeWG6`P z(cjB0)+uy%NI2Lf)ZSy--E3e=_anEHt8~uiIgJEr>Tfc#)Zcw{+yAOc41Ld<^6Y4> z&x)(%tqf0xrMhPq>)=lp3rx1vtO?_1P%7uQ00Z%K`Lme+vgRLeOVmc$!rv$}Y#I>Joe%&1l}|PB67!`prMydEecu~Z zA1|V&%oG3&w3x3eD;)U!=a~u5Lp69MnU=%f-v0G=)*$^Qc)w4tATFmB;uuA$o&LD_SQsrGaM);b9Ve>dTIcE@jo4nXaXLYfV>VC;^Xzv} zv`BMNuFb>q#?aJ=ueAfD!rD+?pFF>bwuIKUH-EeB@=pdt9}IZ5e)y}OBe|r@DR~2J z8`AM*#PD6)>Xq6`F{6jLc$_UsV+1(#Bj!dX-d9_ZaO*9sY26%~+>jR>UGvd7s}wf^ z28=~WZhpuf0~k2S%CmFmAJ>{3OlSC18D;qapvGs2WiZTZg>q|jOh%OZKtPsrvhA;| z`wBSGc25+*T03%CDUarwI@iVkPJMq$x1kN-1#@H!##-KRHBYh2<;3PidR(q>5a|DW zia%@0D`ZuJ-IfGFcbH|t+C9NdCas;Iq|M^q9aXXI1Ht384L>y46Cd$XbgxHrtct@N zdx;&wa=K@AtDQv;pKP# z*&0{6$AImWPlNx+5ao-q@!nzj zL+r5f028>*T3~t1fX#hU6f)zFn2;G+tQ6#doWa54H^q*hZn7vrx$-ZkWDC_UZt=Ii zXG0pzb&Rl(`ZPD^uED+-vVd5s#b{9aWNG3tCyJTL;;Moa7?mCR8I&LFMlwOHp8qSg zoqbmvPzue5Fgb{_A6%$Pw^b?rLTL6HacP8B$yjB$!KnY7a>__XffLMynEYkuR&JO}PQrQ1f^I5)O(bA&qJ#hsNtkV5&*+?4Pv*Wbk^ilfK_h-vF z$C+xnU&%Lm2QVWLyiT@SKVA9f$~mE!e`dg37Cla%z5^v4N_IVBGka10#`S19HzDxG zTujP}E5PfH#kMM=q(ZTL%AnO+d7WrBX4RJo6`#npD48rSTkhR8vx88pU=}tqpeQlWu(-Zrr$h_9Je;8l&YKm zgBrCCnfN6Slf8O1i+8%e$JZRXrg?4=y4KbFE@=mAvcUqZN!P`JeyjXos3lU!l%-Cn`d zl7%NSYGqFa^s2Ud6gr!u_Y<<>a-R+214i-ZDefU>QGpHiIm3ZvRFav=4!9TH&zxU( zCbLqb4H!t&5q_$FunssjoAQm53#Y#`yZ-w*7+=7_G#N5^G24@Med6OBpC--Cv&gBR zv(O}c@M+?j)Kkv3qhiK0JHJR3<$-)o{py!`asgyJ(A+GuMNw^mo8psj{H0CnHB`1j05fLR}qf0mP?a$K$=wDFOly@0``TnNM< zi$++R7T(TNGmDf^)}PP*j=e6VV3GNl2;?}>vle{EMx~C@F!8>g;Kx3hp)BKHw@8N9iPm$wX3R*B5Pusw~@{Bm+K%vL~mMtJCMCeXc!%1g@ zFlw|*roN>QcxE+ja&*-EVl&W3 zO!Wh^GVfz=1$wz{lX5pwSdLnO)UzZ9f8jAOk^uJ}KuQRBb9#SB2`Wf!ZJn|`of$$k zTY5uE4?*5bTWL63Z4d>Cm20QYnxFhJk4>mI&0Uj7PY3(sRW>`X6Lgh_tGZ?<_Dz*! zRi(UkUU!DF<%<0#1%Hmwk^dp<98om#44!sOK44t)<{)aZf`pXRt>fN(FWla5mvGaC zzxSL{IW2p42K=6t*e_pCR;Xb+-NbC|3SE4$15+^XxrEFv_e@=zzxl`|Q`(%^zc7Oa;9@Orp*WO&nq#bu zH?Qzce@AwbIS1RLcNmsrLMXLX12GSx(6#rTOuskCG(0YUaz&76q-S&OS%5s-O;Fj| z19|GR1MmHIUu7KI3Rn8{rQ`f@;iI%s4{}z+{ya0^JdI_nZTNGsP{m-V$7-^O!YbO| zs%Ei`wIO`l!b&|PYk4;1p4%f{zEW}3S8Gv@!n$Of>mWY*C$M(r{vlEW-R%I;*^JM= ziT}eeB8j4Nl00xlA(JbVLiDHEx1jIV9QLQ~KkG<0)K>I6CaT<@4X1!&mpv|pLb_6_ zE+|o-nk4kmozyT+bhe+Z>kt|A4)->(itQ>Wgu4(6gZBlzCV6l?&+)v8+$&3nb1=Nm zOa|XXLJF)32irE1NDqmk-a68@6+ECUhjvHzR)5?0>`kSO+U<|ZOP1kF5jq5R*q33@ zqMp~n{$2EZ|7X~r5$0V!{&lC3HKj{fZNy-Aqj8D4a=ty5KIQ57tV-liYtT3QMeZNP zd(Jog$#b3^%d?k|Po#EJC0BN;5?od;94u#GSUGszK4Bo7h;{vMSmOl)II`rX+}|2NvtXEU%BxDFeQG&$I8wU+i)^A8AG0rYsBmsbWuFsB&b8|CoIc?oligjOszH$u8ik;&NBHA);Wj0NsTUz)VTt( z3mg~v>^{IjJ&)F;v7!7)nb?9{hlwaiet0m&thfn3%=N+P5t*J)0aN-(!ga-pP?sSQ zhZoylTKxUBU?hKmMy4A6+}a}^?_onTjQx!S=d5w+!Lx~D_oPl!^~Yxmam9XC94QpD z|8l#m4seRv(9nzfi_>r1U*4z`*DdC#i!L} zx$s?gsb$wwg>_F;J*>k`)ns}G^-?A)=jv345MG=MHz}1+xvb?vApQN%a(AaMJ z;DbI!>;k>YfXM8ft=Yu$1;?`-kg88a0XFR#Lq4b4&B9FGL$5=gj{8+@Nyh(O6v+;$ zM$H<94Dr#t7TbH;ORq>^Je3>df>9h$<$aMLi}LHrFtadn`*MtbjFJSVVXC6Svn6_b z1D2M=pAkU$j+wx6Skv3pocv50>ToUGjA$Wx2gwHZLF!R1VHMof=Y|)TOnG)($qJ_B z9HD3?FlDBO<4#od(E1nO)i3@Ehb0p7ePT^aGbG%Kg@o7;lbU zW_U^s*KB>W%hOnKCdgbzx3*Qu^9+B%d@rH+j+=e|D?shsGT&X{B^$YUB!n!~$u8>E zf2O>X$<*??w}St0=n=lWvhpP+#-CFtM(6e?nT27Ka=X5 zAbwToy45uQ*K3|%nYaf+RZgZq=NDD~?3&{m%e{;S(XgNN1K37W>spZnSC|*#+GaK^ zqvD}6e7^OaiuHisl_|_sLM=a523_&yIUiH}33my{FYRPyb;rF(3#Eew)h~nw zbzbkR6a9>@wcG#bDcX9T1+M64+-=n4E_FaoI~KaB~3f?K?(gXwQP&VDMY-orjQ29jt$>Lw& zgalECfl(?B#E@#=17z73U8T8f0ds}RV>G6e@GX9e+T#uc5aZYttNzN5(2bigoU-b) zxe&dpF9v{7giU07f+~6A{A{DMvo_vP%1igsFsM_IbH`uskMvcY$fj^t$xoH{p`TI_ z9V!1Q*me~Vlbg0+8T8j!x}a9=4NDw-(;5`K%C^?ohm3@1AVDEgltnd}oPE)cQ|PI()Es>VQ=}tQ z&JM_x8IRm||A+-R&&Fh&SWXLVu!GGEo<;fene~u8=6PoC&nHQfjUOP2M1eGN**r>^ zZ{lQq>TLb1!$a%Qpa(9txjjZ1%hXFjFY}XcQ*F9O{sZ|U>Xw>W`Bg(|snJ)c z4B*Qq;xMHNlj~&OpyL*`J*k(GPYlP+iJlt!rRLZS2YL!_-2H(hk}0XCs>;~%5wPZq*(NFBRNPTkS$PC*M|e$(_; zeEG)gq3F~^f*Xo1yY^8t^=&3@S-p6lt%_^G`g4|xa)pmNo|rHtOO;Ey>=Dpnw_Lp# z(}HXwVgkAte9+jpl(%Jl#q3gErqFFx&pW+yvsl;!_{-z63yBs_zx=A57qPM*j+&Hx zy8eX8qwm*Ukdv(9?BDrk5rBRa`?Ib}pB6iv6?C_@B`g3WDo;;>QH#HiA0F0AS_5U4 z4tEefQai~!Hh8VP^+7lG2(%7i!-v;z(Qnd4R;c}h23?>m2*Ec$8@t&KG4i!muW}gY zr1R(RSoX78G8{lWc-Ayd3&npZ=s6f5QcBf>_z{;%eCiY062BJ~Mi^0+aPr@AD{&9? zIV_A=5sSG*CF;)~)@z{z~Ywxyawk;dgo8O}m$8(LzX_EdFoC6rf zXVyP9r4bABCVtO45LxnM#hpGiD_@G%8~Bpbu<~u+iRMPZL9~wla@)qb6F2wOL%Byj zZXyRD?zP5w+4V*<9L62bmiV8S^x$k3-7tR1=n~?-~wvj2DAkz@YIS1wI^Am9(o^V&%+& z68$K-Pu%w9zI6br2%m+Z(j3; zQ}*(`J_Cw~cLskK$koM3cvs;=Cq1yHDjf^pIaY#-VhGpPZruJD#LbJl} zGvADC&r_b>_@sy^UpIzpfDFx%l8N(OYp+wi2VA~!t4yvv9)~pm-8^Fh|Ezn#F%s1P zp}Nz9>u>?UeeT6zb}l6?IZSxKSz+2haOg7Xu_L^fy+7%khjjkhazr0LO372|P`lJq zADB;Lpe~ILN>3TSvS555GK?U82?-iU6Nt20tc}CfS^Kln`585u-lD5Avl} z4r_G`jpcYTRQlPruQG$^`R zgrgQM#eaM`zWs<7uq|HpLig5h{nacx5UeS7TvAK_p1LYOhg^~Lh}Y%t`qF(9>q4pP zW?Nve7;C&;RNUIJq^!Si!#g|IUV7n{qrdT4bCYXpCfOWW{;Wgs zx0o)YE>k##aevjR&>5(b1>8V@nN7eWSoVq3H&8VG<2J=m_r2sT=-r?Q6NAmqF{qLLB1gg4LJRG2HYz$F+PSH$Y>3V}^0>mxPku-p-7niisWYME=n-(#$ zqKDr)Hfw(KN&LzgJ7&A=K3BtZ2v-MA#zW>YZp$l@atWo`?@MkjI?WMVM=7N3>tQW2 zV?=AJbU<&jaxT3bFGS#amnJzA=@q|Q;mED zpCTHTAjcBEu}EeAwA0@2Yz-fz#ngT4H}2t|c>TDk`lr`d%|9l zB#8*eCif-2642fkW)>iyZUi>S!h4!Awy7VPO5Z@F*RLx9rgApoZ2eDeJTQ4hg0gf( z$F{~bFRs0a2a}IbtpL0J193m z^_QFKs98<1J8Axr7{vDp=V9~p%{-k?EEBS^?;GsV@{r~uOR8F)cK*+PW(XR`lNEG8 z@As@9?xgf7xiMA+Y7+wRU!91*)A%#V!CZXXx8_Nvz3-f7{dQVe7A`Xx3$(7y72QMlOA zcvYWEiX{rQr@G9zr$|YYmoEU^mf@ANfhcta{)W}#^y~XMQ70{W?h+pPnp3h$aZ|OD zTOaClrv*PN=M-V)W&m`sdoy zBh7lkILTdvdYhX1iK#+o22UY@tCTf}_UEX=!kD;dJFv3YWU1^`0N!7`RMlImBch93 zpP5$%(d%(Qf#BaUHk{O4>3e;YNTq^c0|i23abPMxdowfaU9d*j8%F@g2{DB{AQxuC8sZ^7MddKlZ!IA=)o^CF&Z-sWw;Zzb(&5(|^!}bX#a| zY=ZKVr-s~*1`i0bNy;{LKJtod_gCHrg#p0Kl#UO}Xbl5tJX4Cbvwlb2I~ zT}(4``NBy>nVFW zXZ7Xxh)RIh6~BZ;P`G<KlhLc%E#ENWNapqKwe92ZcKpd_M?Z^Mpb24oEEOCgh`r0yIC9y% ze=9Oh_TgKFw>UZ&OO&XUaK4=m<7TBHtJ5^8050y=TV0OmjMrbBjdDPP&z3A@XxJsy zXxM2ehK5IIK;!Xw^rF8>EM6v$lp~~=5aW!`h^B{B+(({6HyKM*b#T+(08J3za=;enqKM@=zBqI5C?cV*QU+`V#uT z9;~s$t6eHtGJ+S&%7W|u(9~bFXRtaNfTq&qT;8(Cr@c8e{536Ww@dY`=*>rXxk^rDQc z+az`5^xMF3J>#g#BQjtNCk^BtU)E79wi(O&o>JZ!I5g+!7(f!~0{3SB%yknI{}hEM z5eW%3L%k0p_i1+eceLjjp3M~u{x+N{&S2d7vC)}w^ixXd2elcjcgt-KnHJdLE;1Fn zGr(>*c3wG(tl9eK*-%rV#POf~-HiAmThvdg9b@Spb?ek!1^>H?$>t7`Efl9l$k295 ziyIBY>g)Nc{w9RQeaW`Nr=baYa)5TuEAbF2r)~q-e(wfjqYCeV%o(H?6*GJy{La3z zQl~lE3neu2^Vm*U1{UdZBzNDh`Gv?*gI05}4{>OKAlNG)e1Yv0sx+*NY_I#azZOR} zm6!az&|EVglc4`+5dNoKbJfIOHgMDc$Rprw)oWX5nCBsnzy<^KiPe(fTS-UZC)NR! zrjUu;jDYHb#6)8rgj^$El$5W-xTkD5+b<#Y#P z;Gf<0mH7)-*fpEPmkH|UrB=;*mvtWcl2k{!JnRLkZ^z)dVA9g0>o!u`1rbE>!Th@+ z#wCjQ$_Dvc;u>|cS+O6+zM$tgZ&+!n8Dc2TFTAR4*+_7=h2oJ{uIV0KAHvyf3BB@; zPjB7IN{A&`5PW3W-I-?e2|pROxtc&vC}6o~J$kwb{puLlSOe1^B@+V&t0+3NnlZKfxAY1&jULJXp_J zRZKVGlES}qrMJ{$dCsQh60Btwqv`HH3TfQ#mjUFilHK4O|5NMVvU!3~F=*`MQ;<5h zc!&2<0~8nX?!3%SC!lATA?>u0;e>=Cq`PjXZnb&~BXndkbgWv4D`9MiV|jgXUjqYy_^a1 z2WVSzI3XQPiyh)YK?*>$9zpx^v?{1wpwx~Cbh8}SKvuAigq~Y7EE3X&p~syL_OyR; zx`*h}mm5jUEFus3uW>B*b^h%5>ZpoJN(;hb82dscD8w9u7;|xQ(1I0f49F5};~^YqOA3o+UqORa30CZKJC2-KW{S%~e0Q6A=2cvEV^poKIAvl1m;ReuIa3PeZ_~gcyttPEsDFJUoSmsUAE+-Q1W{Hf&?+x%mDE293 z44lHb4t?S>4PdGpbE+#+RGUh=^5|-&M;p6!iiid7fX=zX?Ggc(-qm7v-bR%aX}P^@ zG5;SGt<`fsI&DXf^`V${S^RCY)eX#$l0{zAsq$04E~(`)S>$bG_>Th)nZLd7GzWfN z3$po^_KAx9YU>tIS@)|e#Mwlx#V}v^?a%Y8m}7>;RvI}e9V*a&x%MUZBLzpv&}i7+PWvFcHDm78tsGypetM?4akrx+kqr zZ!NO?L2l}I{Qtu-Nqx3<>96$>2<%Cvm?+g20wHUq)i4H}ORhPt_-8espMdqkIAeyr zg7NqnpXxhf$J2yx>qzDvyoy}8QLb1ub?u7O+^duh(!1Cvp$05iQ|hXU zhT69KX6^I`9r@u)KX0y_T(5Ck;TJQ;43d*Nx|3?t8RvWbZDR}5&!ogNwQ}7cZqRXf z=1W%hE#0aDh~=YTrNJ06uR}h;f3r`f=C-)-22}p#j@3EzE_S(C&wUD9hoL}Y&IyKr z`5pD-5f;^KcX`r4h-Xg9VCIoW?@-h4AB+^9L~V`(nuD=RbukHrec9-q70Jixv#V=i zpTp;qj)bii74J{!RaaE`Xvf8*k5$&+g-s?G{w?j@RysYGmX_@X>AQ|fm(dQgj~$+9${C_frsRW}SWN(PrV~;t+qC26DD=N&MEP1PYS62D9qwtXXn> zdpGlYAZX3H1uREmUV8D5J$iRQQ%q!>Va$fgE#uPe10_-s?+%V8npR_IswdfhX0+Zh z2*gEmkjq7ic+<^3&j0V01GdHABg?dQjG2(SJc6SM0s{?DAMPE=W#)Yb1+Hg{-EG~w zyk7K~66$u7`P9~89vE#Oa_Z>HS(k$`C>d#y$VISe3oB0Yp_d)?a@#^o{?3e2$XHhG z!Kec%9p9rM-NFV-)*9e&#blGuK6)6cpr-6BTli+9rwo{5wG$vF%R~K76V4l7+sA*n zEKhlNnBclA)g!w!e5tO4i`saMnroER`e-S*C)<#(5wt0WCtv>UajoDcJ_d4^^=hI;4mBxB` zrz<||)@de$&+k`?S^Cc@N0=iX1dl>icjN7?_|XGlcJbSs_I79YMsQR- z0UqTdms@QBVoPtV?lnn`7RmSQ=>)Cgu=#04S;Yu3CcEfHk36l%egN#1`$%1$yW;Kk z@Q2t>l6dAV;~nM2J2WNewC_lDGuF6Qca-3iSO1Tuv+!#2{r~Wa(XGH}MM@eJ7#&iQ ziV{*&S{NYRH35}wkWnI{l2X!aqI4s|$k8F4V}w6G-*bNdz;n*d^XxwNeZOC?>jHp5 zw{y`&w~IvdF!5MK$r}-YX{H+}w#HfueOJov52oDDsFz5poz&HK#C z4ExRdjqDDuTmON`1i03lk@c*ACy5*8)-|;z)sGGBuVn-SZ2yC;m^6j&f05MbdISgs zysgy4RfF&wF@)?0Qf-`$31GdKN~#NQL@UNX$qs44RDi>osb23L-Dd^RYZvx>o55TTRODWtWOggkmaHIc8jnB4TzHQpt0eC}6 zHR!*3cerrAX9~1HI+`p2;OALoa~dxM652Js{()@AD z^HR{j)F+zMm-i(6%)wh)Hh;L{p3*EO&Xa?VXhUW$B&;ZyWbD$8i~990J0N$vcX{|%DeX$_uv7!&x{_3IqU)MpN9;nxW`y`9u>?Y zXr^;!_tpj~a6%kozye{iA`9CO!FI)Bh)1k)eT6&A zw!4FkCl;_xedehroc6r>#CL!n{@T{I(q~AL(F)>gr5E-p7D>Nuy#c=HvHzhNzR5Md zp*4EG$-sf<%`aH^Z#e7keKIt*UY(Jt=L)|ZlzPx+nW|y+sA8OakI`yczuL+#IJoKWg{{EXoR?5BQXi9 z8yiM}r_1B+zx9IzbvZ)}lcH&Jv$snuHj-%Zt5jU5Ae4Ba+p_#bO+cl@sv!63_Na3EvuX9(VZ z+xap?O?lYVQr?nH*NRP~aJsv^Nm^+55Un|D;(95oj>X94V`Ey-~wX zh7b1qNA?gjh<+51{6}f*h1oy(^-6Us2bT7$<4P_Nf?cBPxk+rQE?!b&M`Kw6L+Ltr z9a5I;`>s8gt5-Sz5C@ZU7l;64QC;e^inaUydGpqt`0XVL0ER6HkPMptp2`E$ySnNC zd^Y7x0aS;IUlShH|GI?*_s}|>RSrbnEqGKwLN(&mW_c4v9E8r5<0!I+XhDcJpIz3; zXVPTDq!)$>heOKk{ocxQIms>83qx=CZcWCNGEG!M#P4fXk0_BQ=aI7S;G@sX=0Hgm zX2RHMxP}i2vFyfw*7O)9Rc8=T1-hJE@I)yfj^ANw>1TghPCBXgvAGQsxS(8$rS|TjSxx;6yOmebA^eO zvYR|zkKg|0?%8WA&!A;kIqKq~8hPR;5TmqW-{<{tju_V@Bo+}7IsmQ9Awv60W0eZ1 zH`L85dYtd8SbWVq-&~iuI$&$wHNkwql#ngX5tzHI*2Z%hr0szoUk?AAmb~kP5%>k!n^fCZ zWqzu| z_|H})bVeVp$z<%uQx#1xaiH11=eYiRM(XY11*eeycSGRAtv`P#Fe8pu$hW}H)IVYw za#<(Kn_B-t*evANM|8Vz(cmK--w&Wum}+XM`UFvNR);6)cg%Vc&-EYVL&6Sk zKDRa-?k+^uZ6J~jqOw`?>Seg7ir}PC0wSEM7l0-K5ZGk;KT$fZ8*!@}=6$pBOu|yt z!I1V#K^{y_!zj61*Kg+&!&P_hTNUu$_fa4_i!sgyX-{{Tt!kGT5MD~jVdt^F z3dURqpIU3vT}as;3<8H>Lu22IhFU}aWKPEY^Vmj#jxw!`je{cP0E z#Pc3o*KI9NJg?qX3$K}Yy8{%^E79KgP(N)sS_3YXp6P#+tdrn0kgB^Su}|{fN9TF^Cltp*?jk+ zUj7tw7W5t<>|f!eJOw~lg<5toKV)$kf*vpdg)BQV+NBJ}NpKHXgG9%#8GmqviBs1F zpm(`+l}M@mRX&Jwvp5ct?`j0#UdQzLgn!1p5{khHDgshX7?I}HB0Az8*WOGfZmP*q zG5lTsA2uOrYi-i694wa652rM)L3DByFI-6ulu#lz-ce#nROluB&_G@>dFb5u0PZ2+ zz}YO~y9BCb3KeJj0D4ekzk=td>xu2LdlUwYxcWGYi90F!|Hu@TThwHk92`0C%zm79|p>_&2Ng=CuubLk0htldR9xxrR6Cm zB`S?igsdIS7anHKoh(Y7IFI(;txh+KNN##rdQFzvvJ8t7W8Vi8nHd^*LShEWUdkWv zv>eG?9Glu^T?wzttk$a(e0E;Da$?ciW~V9$FK3=&c?DmrOm>*z7ZZ^$tVQ z#h5EwnVLpxW=_4=qr$Q3!CgbO^=8bEI-JdjN)p`yuVXk z#}npi_tI)J*tpMr&F=DIP1#0;+JdxVMoRakvbYfyT|9km4UcoHnd|jTRYQm42y72# z!OZB(%sv5p6Pt1!a9G>OoCVcwVJM>UbY^LDUMftoE3fJDFl-jE+XtKO4y^+q8?S-; z_L}UIWAzSg@yeu*04v4)hyQBZ^Afrd^=a1W*~t5mz{^ba8)lzlYfp;)btqq`pE(3s zk7l}gF=1ps?$fsamNNLw@@Yonts6buDu>)uCPX0Ny+MTIQc8G?x_y|p@EZx(3wi22 zF)K1d6?s+EIq@|LIjl9<>)W6evspwHLi(ouebL+~U>d|v?C1-r_T1`)G;HWLr*bH7 z3&i_+=Zlb={eFw=wQXS(Cadk{CG6cIv#(-o>dbWY#*@4ZQ9T=7;%#3OWLr;~SCm^> z`rW6>d8(+j8J*ansMYJ`AfM2xN6Z-K0~U&jA_uq9w>JMcg}H=Z@`Q%xJ1`Q{lnVZB z*k0)A6H~{{7z?Uc&r@hbM-2D0|BaL+)sTZX4&_70m2H8cN)m38f2+tKj~gEs;qsrz zwVx8RFA@T|@m2kcS%Q?>fTWqs1St>S?mi=`aModj5V8Ueo;H(xJlO4Ou^mS|vW5R! zPBj#bW^kOytZ38XQzgY4^4a6w;h*J{O^GfPsb@Ja#{I^HoXXN6)MssfA1$8Ay#?2d z_waKG5Rv1k~`U)?YhH;SmNP2)9w-C#*i9rt0_t1 zzi>{$=Iz68XMdoid7oQtUX6n;XLApqKgmn(*lIjg40lcyzjX|O;NEt)$~K0db_&WtDG)35AE!zM9zNpqX?+^ zK2rk)K8|N}wD~RM>LJ|jcC0$Q(^;%vNZn>)haixHCS0eRDbG@Daurjf(FY^@Mr@#bRw>gSi-X;(|pJlc4_!e`qLlVhH40a&&Sm<&2b0FnI5-P0!ydgGh zvx%+)?@-?v?jqfXaPhcbB>|#-QE)#?iU#FMV<1_h#EMgSne-^Eb15&I=O-cas2o>!iQbCi-b_w=s20d zPNpUD){U@DOz85r_lUR`wo1POR?4=583Vk-3hmvI@1f(S5w?3@KIGd@h_&IT~t*orvQN<3pOD z*SGMli<)xBk4T$rji;s--lMS#Z~ilor{lRW?wvd9o5W4M#nJlm+r1M{O-pwwma2YlI7Crrlans z*$Q7WU7(1h@hYeuKuwXVnhN|X4=N|c3AI4QL`>=Vv+BxS-18-@<;_D4?j!;)+i}g` zIn8UT!raq=IsBmM6A^_tHLVV@iWDOLlhIiVj16t!34M>Tf{Uks}C4*&(#tAj`B` z%w)E{_l>xzNah(1ob@St&y8ud4AcD^;BpQ*-gtQ4*PfCW3#OQq|?{Y;&X8Hv-YyT z6?Ih=9fQd@9Et>0$85IgsD7+BID-s>BFd$mY%ZaF`qSp3%mc&M%zT3>X@T%uDl#fE zMVtUZ9FRwPwGwJ-Rg}1G01asD4t$CWX^Syf&k%(XdN>2b$3h;pq~ymg4kk+@ydW6O zO22eTZ?AJlY@z}FP^{MJ2)}6m>_A&{8(h-o@M(i4`}bT$suF~keOUS5p)wbZEa#|m z0&^BJ9$2({R3yP4!d5jR2GeJ!X7!NiW~uGIp*85*f^4tEdd^jg z)KjCq#P;)Etq z`+Duvak?ve!*DaC#(2p&{wF`90;oGx12Fba-JgD@;ep`-vgO$DC$WkGOruJB<;;f0 zM_!KtcM&O*URZFps*t^`@B)pyxPOIJc1t%goL?@*Wo?~YnkyBL|11<$T92|=Z@Z`b!B$y@SvBet8}j>x^=lcIM|q`t8`NY7Pq&ykKE*6Y zR*aCUinjhBB^I&I^8EAG0hFTyFEs1Zl*qr%uI(`c_B1YOY2{95mj%Cnv?sJM6D(4pCT9@kdh^DxpdfcA|F|7>Q$6Gs!hz#lG6mA-XyOZ8{P z_QVO2nwt0T>pMgiva4cMq8V!Ho=z|L%<*6+HRXvUsbN|nV>xq2?C7a>ClIsTj72}q zc|Jhs);dN|yupac^T#XicxmGGtubNR0D4OZ=wKmI%;9<4c)1Lx2BrruP|9X}p-yAg z$xP-4Hz}@A@u1clO4D4CQ%d~NORKGbgD$e>j2;Nj-(SkUy?S@loBsZ!$-2oO>$f|{ zaZ(QRJV{cT3`^t(nbmCi>luy@aEf$f>u-?xA-f01Ei&;|Du_K*F5m1Ha}IGrL#Jax z@yYsEIYK288xBn1Onn6YzyquM5OKob-~AJ-c-pe2Xp1mr8iZ=0?uIr> zuWKaw$Ra(tW{ATwFmVChIo?Hrh2qw%ph5L3DiQoZMNmRwJSjet5`g|&MCI5N+s1B{ zP#I^kmt0%iCXp<~4cF3bArZ>y#7(p{*_ZO~IQLDyt|Zu|=r@~G>~}N+*UPw;gkY)1 zkHQPk5@-ca*V?yhM{HZ`#lq-eH6!(|-#kJDh?~zc`o>=R!iP5ekRmzSX<0}MBx(EF z5uu`0%TKu(vC$&^+`GD%YY$^8zPD-G9@w&HX!4!hn8@BuoViy>+m!0!nP6Bt>dDoM zF3Eq2oLdgEOA@)=?!7bjW1>(fn5{l;Pyn^+Eo@%=-L-^WOhM+6n%mup`?KkUhn@T< zla1qzN(~@rV7-F$`uRg}#A{BE|EjiK+!=Il{O!nqaR@c0VTR|%^C3gGqA*k_JDU~} zjy9w_-%!d+9kxwZ`QjUbAii_Wh81Qo2lTEjKuSf*(xFxuNfCLcGkqUq+u+7Fh^!+u z1g(<5cUfv#8EwQy6R`)^byb*}E`eNn37H}FTzVZZ|K4Gy=u(4d`IOYn;m&{cONnVM zAT9ine-n06oXn0Y1Qs;dXTN8hS(cYc>aXoi(&0cU^CeL%CoR@=O{6kUZn-yh*C7Zl zSkd#TAc<#X#Rr&n?qFV@{s&9xNVIpD1^mbhP>$h9hMQg2kN-(J{2&3I^m*O;_**S*kaMNciJqViMNx)j`g z%>{Mo*p3wQwBf?<&AddVBWiXQunSihQYG;=%dwY{K;sP0y9<0acQ#6|hI{Y>_1B9+ zMQatcL#jM6y5uPZHVNN(Y|o$|d%lkR0a3K0xu$PLa-BhVVhl8cGHgW^^^|SH>g`id$_B+Tt}GIs5i-|azu(Fh zQFC_vkJxrf)j4-WI?c5RSjr0%IE18=N>YGac0Im&N}CBiaU$R!rM&l%>u8*!0q$hdM_rCRAa>H4jU$j^V}VSCMgl$fw5cKj=>Ix4+? zNrb~J^C-kVLggntWTw%}5s*O-;#N&b_u_h-WQdu~G=2fuqoOAh8>5#u0{44LC0Ak)$4_#))JB*m7UFcjp=doU}T5^Qjer0tJ-$X z9(dP4n6ZrQ8|wk~riw(NkzHh;;u%lOnm+!8S%^lgwWkrBsRF*}pcQgE`4AaI*YZ92 zsQDdqC;P_216FO!Qht2T=Qel_p0UAG5{fFxA7zM)e!4nx zd5S9_lSbCG?h7eM7yk0hep(C3QMGK2)O@?$B~N(vji~{jOwI*Xc<(CpYHqmT)C5n- zIY_FNJ-3t-x}hw8H`zYhD^GMaX^Di@C9}1zsRJvWM@~`JM#)rLLM!=D8pm|`m+|^E zK-Ds0Xs)o7#afzvogYMRWsLt)hgo`(yKTL9oDx@mm}gf_lEF7!mh~&l<4yFN#rp~!#=FUCQ~P&l(fkz%uhFrU|%7|HH(I(v|&>7=aO!@2#mIKC3Xbfe?C*ck6g zjMADr1sP=H2&JTp{r>KcDFYcG+-NdrUH%utPevAKjtVdfsI8NZBIwa=bEB8n&DUpMGPepR zT7PZ9no=}6Nkm45`{p)AG(4VuN8lBz^}>3vZFlxOriM|ER>A}K|74KSB*E^B@e#*F zJ+a>=HRa-I2+Q{RA!9ZF;ru$z7HjKLoS@H=Zr22@>F;yPvJX8Z^m974|9)OmGdIP-8lw|~Tqj%N$NTC#0TH0d^bUDB9jF%spY8T%;;XG3 z8IwQE5%Tsr5*TlAH0S>lo_X{oukE*lLF9;HNP%erS=fGtKpGURf>^TLf$5_dIjW@<02xbxXT>h*N)!BUKcDxwNLwG`ZJFC z*UO>ZQe3)aZE?v~M9_LyyXUsHW_Q`0tb(QB+meQJ@$^UUE|!u3m_Odf6vK;H=X>)3 z+;kEBDnwCvUQHG?{#y_b;5{9mcTIt*$=Q^bsK$l6Wyn&dnncA^&4b$^>*`#rmuy)d zSA07Mj6+uss9=0S&I1_xDi99}^+@Db1eno&NN`7Ahw$1FGIY=$j-lxHe7~`p?E);k z{5eRjR1`T6J&Xi+s=X3`1TIODWZ6G&tc6VlVZPp*Hy z)(@vqIgoB-l(Vq2;-rK~PDb*DGqy%-zKUqIWL26f?pm){4z>7P6RARatWr75*>>!A ze@hvCYjphx5OT~cFL7tbIJ_S*lT7~c_MQ$V;Au?j>YGJsHtc>MP*Q5(mOYB<4XtSX zjb!(FoPWn7DhF}5yMH$Yl*b$Zgn|4$KbRtWG0|hd7mI~w#cP1le8>$)w2T0bOVIZz ztxnU8F4<@SM=D9(zl{=KM97J&Djy6Zc==UFGY>k2Yhw0B^LSV${k%z~VhqEke({Hx zZ(zYIIHrVmUMu+c%t79Z)f*8S`3oZrZ&2aW$rB69N-Q6J>;s{q+e`e!E}2?r{?CN!r^`Qjfw)_SUhmJ*ySqzpv+EkwCQFNy zk{webLB<5Uo_*jNS&&vX>H@5P%X!ax;BATf5!Fz7?CHLkqMG}G8njz8un?{EyMy1u zIc%&pRRzJvUARA5mJayw00&@+Ag74D#iV8wxbpbK{)hWJvlTju=X8ll|6%oQ|0XGY z%uXK9PQ;Sacueyl+N*H$^YRlX7u~GvW>#jiiM4RxRCl zk{h3T`^~Eu@bAUe*xQ3F*M$K1El(Dbp~v-Um)>on#j$%HqWpgcv120vdp^H?8-s|C zyFxCTEA_MEzODV2*d6vuxD~=Lwk6R#B&c8xkxIbPNvDHV9pIm*JQGF45!IAaZqUhQ zsME+qU>sK@Sv_>Vc1dnZHhN9&*|&vW*q&3+7D^Sslt>U0Sm z+Yj0p%}!Rf^tFj3ja1oAm~SqRSibNUmtu#q5)Is2udV0HxA%I(hS$s#`{QnMc^%rl zqJ3F{w4&R6Iz&Hrf^5Q#p}By*og1m3KCj0niai0Zt@sF*Yq!_Pw6w|pUN;aWGNuPE zbdI0S*Kvtfj34uI8vSQ!3@@nt~8%OonHKbGB)q^eyVUTOwH)Jx9Bio(vyLQa_|!%^zIl)T^?%rg1-r@nB9-wYQl# z=1k4Kwm-tDK69-1l^xq~mO4Z$6}lC9701QSkwC|qH7Oy!$kv2q`!{(bLGb*8q6Ht- z2O@~F33@2^-dh=MrInxOb8T-QDK1*e{X5in@B3KmJ|b{66dAbMRGsU$1;5xRJV%qt zJ#?!r3cC;p&@>G)sEAA4%#Mc?o!s&6-w^Nn`&Ww(yB?1Sx3%?U+(tc848ebib4Oq- zwtKK&U3J<=x+K`wyzH%95?h>e5GQ>bg_>PQ@$<_1-O!aQ?>&6AsrzsWJ0W0R1d`Q z@Kppz(-Dxl0HdDMQeIcnfq>Zs25)xgN(iLJX`0ZHHGE7sIB|O{@GfF!CuboU4tcEz zZq-lO?2C(HeruJ!c8ZVIq@znilw=KLk9(< z2GI|rf7cBydfu1>C-AN1+x~?5>-aOWc|B@53ae(}rUp5^6oQ7RINCf|dL7`_NvBNB zN!^C~`ZUBb(?P!6vLWdV9#kK^J;(P&IvvT4q6~7bOR_cG@!X^?TaHRS!QTc%ie-CK z+f3KVdP5ENavm9Ha;)Bf*>38FRsY;KP8b;Zer}f*@`2PwR3X!0CgYug zUt@*q=}m>dEo&V4E*CjIHHmpc_L#M7o|$E*#k{iMu0}VYLhGOCz~$07$7-DKNs6tS zSpR`%Q;0L=zhQs)h8Sm2v)5@F@1YdCmz8~nah2Z_8AXgs0^8N1@>(C0#N~+d$y?EE z??`_Bai+TwMTn?FsFE#xc0~R`&!n7e=JS^R`<6%GcDT)_fzk>#lYr`%PSH5Y$=6EQPYdpIO%B>n3hLmiYV`UMb~4w# zJJ%ZIS3AI&E$e&FA!}g`d_b-5>6AY}e-sXM&2yO!*^SIwIwl<}b0NbDK_T9fgD_1X$s72Y)>%V$sEzw%o!|=XbMdQi zQ*li80oA|RvC1BP&*!d^=5J}H`WJ4q*~ORF-i|Wa9H^@3*r(g+xOuh3jmBpt)^Ax@ zLAa2EwVrvFo6~nFONiG})Lp_02D8=IC+Ky8isQ!J5*GK?8v`;HnHLLR-f9yE^S&Am z^^oRQE?){+P{d!_f&U%5#3oi+M8?J^4?EE~yhLsB%M8YIxw7U*^%n>QFU-om-C<~a z;4UfDVaQ?Lt{Q%aD7N!fd1PhIZat>iv3zQ; z-$2M06Yv1k`KWMrh2t&n*1LioXUpD?eTBg2+duik>+hY_u)d{_aKGHJQTjA~Lma`v zy;Y}a`$+h#Fl*glLm&qG`UAsD0~)2rWE7=Jp+Su<%(YNbbp$Ww9Jud$Uo$3*`4T3n znQ^O7Ykjav=~`E)?k7_$H3hTV@2?i%^kN@2n#*`KB|VPqjJQ`LNcLgvD8ERA3^Byw z(<6NE!Zo*g_fS%H!;b?wk}~q$m4*|QI1W&F;U{Ybt;4_Ln*tkatr17&g1tkn$X$v2 zZ0Nhy4ljPu)8bzuYODmN2OI5N;2zL0PlxJG-y0Fxz~q)fQu!CdPYrI5xyHB#t1yPF zQ?hR*o?w@R_=yi3kwd^OIcqCsj-gE%fBDX^>Ttg5LrF&tBx`$7dg#}`3TK{fR9d>K zUtxy8&DLM8Ti5qT!@LotB5ELs%iQ$Zk`VHlmCdMFo~+dyaS8SfIwrAr+Z2#6!L?e) z2JtJ*2a>Zqm}NVfl9wt!u^fvg7mnAmd!0+y06nA{YRl~qBa*NYy=g_gpTl9alUiS@ z`|PD#p&jgq4{UiTRQ~$RgMuEQt+<6Q=Rn2z#9ni3Ho>RogClZ$JM+k4msWxiDR8v{Vn{h{=>+{#V54Z_Zp`L*PvUHF(;XBC$RXcFOr!r`k3}DCv{&|@+JSsfd zau>6noh{L)mMN`&G}7iH=S=?e!{287_$TpPlLS4_2AE@wG@d`kdp=HF&g|g6EG|Lq z3UB)u6=!|Vo^4`$qP<*sIiI?3^}3Jw)nO3Bj^wb{nXbluIrO=-oCuMg5@u^uF{XKc zlSy@>M{RdF_wWz?Gy7VsR7OptrkydoI@ZrWk|q-111GJ3dqZtcalYFHrQZq)fb38U zgYrNSP@01Fj(9J>>XzWqb_|)B;?aph0f?hu9ocaskX}D7}17WG^D_e@0`{O!c81z%=SCP{`e}@$Po&|S}>&cmRf6s z#Yqa396IdimY-AcRmJERp=;r#Aoq>i2^I8|n1o&mP>a8_3CErz{r0_&wTY^{6J%v# zBdoRwvSf~i%vrMe8csyNT>SXpSKEf?kky|8pjR+TT#@$YjkhUDzIKauOAoxA|oJ>@QCI@SGQ3jUxvpeLLw zk(KKAPg)PU7nb@_l(e5YvpZ4c11uKVJ;W!DE}@#i2(i=+L~}^sJzi3Ug49u@T8DEl z9*57?wCHN4w`xBu`7^HJ2d-}GX+vb&_Ex;A4Ib%^t=R}a>8@CEWt*rAn>`&#F&?b= zpqQiQR(5d4%GkR05u0PI$(O!hsnlRbt?DN>{*4D}R7(%RQ%?_G(}mlT;SrIJo8;nq z6E7>3a6Y!+n5RL@fPwOhb;HM%uhh@|xmx{Hb%WF7d}%Vz^3FG&Xq|ps`RhJ&d1ABO zQ#14AyY051G5ns+m4X)SkzFMRjuKnyM+$+oG4Z^4%FiwrD*vRp5zM6oJmY30=w(7a z?qS^}d9qn1{ECBZVr`3ZCVs#zCVP{*#5;hSTcOv-(Kgo6xFrZ9=e3a*uv7h zvfWiL%WI}yL0rC^ds!%YS-O4q+|V4d>d2&>U5+8Teu^U<_X%U(h=?jW*@|V#C$Y7I zlgN?K@xw5|4M9{{34->!apt%g?v8zj>0=59?Om_>+~mYvzv7Q;Dl( zqzenmuvmT!+n$)$*yMV~0Zl$A6jbNeSnFGSQNS%#56)USb^Ol<873J=AHcIr$SOEah?no}#ygq0AVs-Sb68T}HHL7U(D*|>Jp9y35R3E|5X|88fCDU>A% z{wrl$1uevQcc%{zPlLF7-=|5UKa$SCz{-25;75Xva_)TB0gaBcf`8t>6;pvb^55SJ z>@Bx6CU!1oQr95g9KNuWG$|~vR~XA{8+ni3G)$V(chS#t z^1fWz!^6v(-mjHZ@4fTNUUoIE*-!LsmkJ3OL&eIMtHEtFhf@=6zL01BVj>e9GL?AJ zT}VgcY;)*J^el(2@l!{ zPVB*+eT^A-3X}SHy}l#5t-ajTrl|rhhPH#EVQ45Z>r8f{bqmfq`sfm~VZ^|yWB2*h z;)i<=Cx$G2BivKM`Q2D{)k|F3Q8$>#Gt!nUGaDN zS2I-M1N|Q4W;Mbt*x~uqec>FsfE;^#n+TdkEi%TzVS)NR6<^+mZD|G)pcId=QP6r} zOlMqNDBQ}f+bf#sABzNZhPyTP!6&5Yfm$-I^jso4gYRwUsFQksMqq?(%6S`erGze)y_n(xqcRT$S#1o zKTTmER*4JSb}}+ONn&`9ecSQeWbQucPec!J0net6*Z33saxw!#n7*wciUSc7`CZdq z=S?MXS@zH633mz(4J-yukcsuMTkz50KW?z)9^2p4o<}RTe7}qpQSk~1f5f${jsa-e zypy{1Jo3SG?@MFRU-@U&L+rDa{lQ^egDC3Y1t!aq9(ViSwv`+sN#)<`Xv!hrtv`-OdqMEj1M z`fhbcw(TIjk{x`Le=k%I3ef!q?TQRGNC8k??@z;|b)eCyQN|A8SoOhD!>=$SN2}S7 z<;aX%es*sauFw0g<`q3^f_nWO@cfC7?T5gI()QR-!QQt$v1{o#d*+E-aXH=`qTjw#TWGwF zGF`@e{lhj-=-e;9r38w3@+{hYW@d!;iq*@GrsaWXoZ@o)&O&*3?Kg7tzLn9}V5P+C z7;~*8Z%y&zS}tbOJ=C1jkO|7r;Jf#3fOM6M5}V=;^vKO2IMFq~e)!!S`6>w}uaHq0 zSTV9pF)Z)knA^4swufH-S$8`>7?HE%HZ0^PJ`jGrLGFaVbey z9+h@TaWLM?x-pL{@vmUGbsX8!bG+V&Rp0bOf9=lT+^Ci$A=Lej-o1y*gZ*A-Iq#9az-EUuYb$ShoZwrwj>=ye!ckS&thQHbvc*t)8=4;|^!n4|(_>C}K_6Nf zDBZ-Tj&?SXRT7AS+I5meJ8d{=ugoZTXij}$c7JkoOMoZ!5 z1M-7ojryL3!1cRybp8wSgfvDo2yNHXvs4Y0QmUAw_|c4?0k`Lo;~-s02$T84)k%rV zMP&8JVa13_KqIjzS@*(;E#!mof%f2WYTTcw(Ajpq(U>dtjjXm|j(G#7qoe+FZm#pm zu4u7Bv4erR37KcUp)j-S-38+Xlm|DQsYJZh5 zWFT5A)Av(OwmyWbyyp2-G{3pSq37KGWQh6gf03Mw4LjK$1+<_K9;*BkN7151sS>cT z?<;H6hy>*zRp7xn2jyzJkduH`!ma1p{tEm?dG`490YJm|?T_vFSJrdB%3UXIs=yzZ zH`>#yjxAEUb|+&hs%=#DXmMzkD#INCaE8?#nn_9@DBd- zu@Eg>xIZTxfA6VQ&Q#ORgF%d)Bv=%irqJZ*;S~bQwk72~d1##}`@(KEPFV{~+fst4 zIws+hnmLqy=d-;v9dfkP;>9AXS=v_tx!wB4XFO5wd%U8z4&NQ zk?nbB9%_5&L(5UAyFs1~)PN>*DTb#jx}$R+Li&D9VZm=Z^687%{v8Un^=MzOG+C5u z=2I`^kR*g3)|R4_BHxs*^f@(7mQ+39Ny~DgG;dW>4g1rGxF7^5@wH~>DZ+F2wwzIj zE$Ky_>h6b{Ab(A0ixz=7Y@ZqBN7S?t*ZhueCu7Gei(qZSybY?zt!wv`0I&{bAq{rB z>Ta48Df^x;Dx<=17=wVo-zhH-N0%Q9_sr^#g>i4K_dyBvlCcwbV;YWO&YgOtvqg*P zdf6(>G+}&T1i3HOPYczbD^;OZqN6 z{0^qQ2_+{cMH)cO9F~Byi_~q^)N=e*%a!;@cWP;vi1BYhxnpa-u7Y zG6|)BWCXK^TR;nz*PEQt>@sAc9ZLcB8TrUSqClA&+;-hFP)+gyJ2#?pY9iYh6 zUsRigyt1!8_t040q2X^`H9Doyk^F$>#=Ik2W3`f9WEVF0?s_ufHTd2u;WnwJd6Ub0 z=+SS{?8CDzbgKz(ZJ}bdsL{f56&UooqOK?;5aFYmw3ydau02c+4BuAsU@Q|v#UxCP z@&|Q(NlR&LL?2d+lQjPh>Dq}Wb-WM|8}K=*biY?T5y>44lv0=lSC$C}zSKHf_K&`# zqU*G6D6qgr6-m!dh!QN9WH=X`!=yI}DVZ(HfBZrw{HT=%39sk*#9be22KkdKmFAg% z_Qtemy1#x~AiWk_#mq#E^$j_l{0GAgUXC2AR0y8bl}%k+|71{`vp)%`N2UYWEGJ(a zP#T<~y$I}BZDoB0ZU3X>#9%vg5zyj6$;dCMrPl}5^$8n$f=RgrjIKYyvDo!)T*um9 zRfNhq3zO~^)G_)uw;OD9D-S2z>CN0zmZnS-^k1HACcGv#l;(?mLM%>1_ZL()fq}nA zIAy4f7~K|OH}<;ybW8(@$g53R z&ZF!i%q>l3niTGEg+kg3#lwJ3I2k@Ism7#G)@Dbr#5y4-XbK`hkno7mS4Q1CJ|vGynlnGS;R92J%GOwr%d9^?%fV>IB&!cu6SPRfXH zYTc$xQOXs{?-y1so%vj~S|V54`|^8sfYgCQ0|`k22y}s;c{ufmseez6>jW6=#Z|QT zJ|9Ml#Bk`dk35o}(ohaYc(u^-DH7L_ERab%U!@fxtD~i-Y+4K z|3jSteOB8Va(?3V&-1Q8l^k9d9vSX1*4~2Bq^9O2^d?cyI8(98TG#oip2TvR!6RuIAc^Wj^= zQPxBVx09VPgU1Qn(=(|kk!hcK03%xTe>9ziSCjAmhsS_XBNQnap_E9B5;kIhAc&O8 zN03HIrABuPsNg68kr9G|N_PsIC@^9S5s@A_x^vWTe$V-x^ZWMU3^x= z<SBAqo>7 z75c&{`-&g{B>q}DQx0Hl`!i(@V=i+82@Xxi0$NJuT{#f;Bz+`SkA{k?N|L#1z&BN5fkw3+>N6)6g~?*)8vY+@E;iuQ`kTmEGGDxyI6( z*g0?7P9}zWIl%oW;_$`)o|jx1*rRh=sQmy5d1CrjtJIT+1tMhB{$r5c<%Z{dzv)}L zgp@Z!bdQA(u{o+sy=v8hFOjy{cK$YSmh5orLitl`Qew01j=|Tw^2wN(^F5I{fneB* zSx66kK8?+q-1+kK*%AZvnMcUPWAbtki-_`L_-)U#xkrk0IjvexhyVEVUEG>$cP7S_ z1LVMtCuq*lI59er6hoEvA{ z45&xD)Y8g_&n4{IZ3c=GEG6&f5pM_JzE!W<1%w+YB>;~MK+E6K|I-A(VdeA_l8B0* zaR7xzm|~<1GBG+dok5kXuyk~j2?};` z;UR$x<&gH41a;@?M_ny!lNZw$XVaGdB!n^`VF{snCuAe|{(MS|+whBy{U7Yc6BHQ{ zxxx!CyMXbUfiDTt%?l>02-S zhqxpuqiERrN<2HR=}(cjgI2`SfBt2YYh{WvU)6M@0LA|iKk!k;)f&BvhDY)giO=?b zG@T6A%ayC8>8G#0pE!UR{3@66ubK6!)emm6n^H;9GBSaf7J}AoUm+VlK@mH$C{CK zeH5^kq0c2~$LVeMx}c$6zGbb|E{vu}$qY~~{gommJKf%0A`Up=B88(n9CY`5=kFfIL{-bbN6G*z<*&Ox-WE=th!Gn7O`%krjL1{8;ImKS?5PMCd_a6?o0oJzUdN3&Ps!2=`rjRv{ zPQ8R=0-`(E)nG;rolXC-5$$kFRm)oX%j5`0qHo{W!a0 zd-m-?`ZZL&YuIcIz?8V+LMbbI_l?#Pht-RjC(!Z(@N;y~cn$0m#QLz#^P-V_*_nV5 z4`g3Lj?H|5v@w1xyN;w!W9mYhnw<>3#_y|=s)*xZzNVb5YOLXv7_8609#mpna5GD; zT5iqF{N$)Xvcs({k#*_0lGbr^@zFdac? z0f8M~x&jWjvd}*gauPT%w7~5=`f50`HU${*LGj9S?hU!ch_U^M6H@KLO#S0FRbq-eLaY zK7MPK%g*05dLIyz&(0}W@v?vFZs)7-!UXT4USWgHyg72`^?UO1q};(`f#Vbb9$opd zrDuyL|89~0e(ih)`}ia38Iu5Anvn1)V~4ClLLWowA6lw5mc8F5#?0|~Y2x%m1+SNG zyI#_;tq1|zld+M`7B$~YwQ6s{`!a;A1v)0uh&)5sJ~aEy0wyZWAeoMZ|Gf_*{AthQ zJ8WR&@4hQ(5zPQ4$GZL$`40dVRa!CU$Gl^+s`X)aY(b_A=onl|BB8{=JA>~K(YQ=nP9d%w`rb7|6eSG%}LUI`pl$-rva&kJ>7_Z3v$!;jKt?m`eQVbp# z;{piSH@rfVK%TjERdr6++;5BBBQSZFRp+pS%D_eF<({K}L^|+!r5?8JYeco)MXNo~ zNfQtrJ$W-y>N&Dsd?fCi5)h>N?SMqF)QvR9{p3P<<=Jn5VeZ#Xmo2}R2Gg2vV;{5} z)iE9nVzx?+y_T4woV#)|*pESvXJVWVunhElIj#&b!{|;ToWwYo;t=U6=oqaNaxB-0 zV4#-zSrqTLI&oK0tDgEw6rGKWD7Uw9HhgN3w|~vENVg*5Y&E_$S?pQd@?QhvLGP!pjjKN37hl{L|# z8$o!$b3}ImSUmC(5|>&1>&PZ7;h>xUY*xF)RMhZcCH1eO9bc9(5Gt!$w>pIk2nlYvP5^ z2zlhiz+>R+v&D0P81|0GCojs@rH02p=B-M1Jeeu|&dLwDeF(EfKgTCZdbz-QAk84L z!}OCMVhGtOx>@aGx0RR#=m-+MMj}c2w9!xz6_h50CbtJpKQ{WMn5_W zi5nqm1-Sd%fV(*%;TBtj_Ej56kR=PWamJ-2SrCMR`0s2o>7o%V)&~!=MIkWK!Lh3e zNaY zu=2XuEg^COZrS7XEW7n&mcx46Ev@!|^{3*OP)VPf8yJnrx7xBWPV`^y$dlMHAS`uvJ~ivuXHd zx1RXTKxL_0FP2F+-U=BGYe5U6Sai8isp<#bc&~w6WZ-FG>4mWja!?PSQ4ed`7&Oz2 zbhT9K<}1Ey?z_vvbUc4r2yH9)6jC3E%=O{NcEITx5VVXAJS-bZTE_S~Cg?!zr_yz+ z9_&!$iiF&j9DAwsx!05j)Kolt(K*}+;{t^>!d}@~8X@m+g?T-N$Cq3#Hc@0Z^oP9$ z3Z8`wXwL%jRi@~#V`Bag{eJ5j0nnI2Lj~lELc2Jj1f8*8qLTqqclB&%KZNg#xsE@W zZT+rq$|>mrFW&new(#fE7@^H)hnByxfM;xlbs~_?Ln3`GOck5faU+SkxR=A&4m(YC+fM?5MkpIi`68;EHccHk3 zDD=4@UZ|`hpBZay=@a5$sEz`8c24PIz*U)${;jKPXCYsQ0XpR5%RDkJSf)*8gi{+_ z5B;+qMv)C%>)#mf=+{g8eKA2oD4oB<-6G}Kd)mz|rAk?bgcIq)?O~rNFa8>3XQcTwn&R6f@e)T5@^Qb7ER~g(glCJucVSSHn;Yi_06}v z70bia=A-=S(O1H0<-O(mn-+OaMez2OC{||c)sb&5W$P<=Z*^tc(~qpE9^6A+Qf`#V zg~Q#GjixDKTBW~ZsoEa3LQAhuE+~X)wj0$$Q-H{ghVL{*tdxFr!#@G&^R0*S;q8vny(!B%{QPs|lM_3-#y3NPmeH6qZQoXCaA7URXI!&maLxgF& zsZXLvzE4=LUaS2g-PbJ^Vkk{;eHA9}Q8Ny-U>7Mj)}KcBd08ya)$kfpeZT3rWfc&9 z<7Ld~S^^eRIwzZx1YGLUv-|A*HMFzBymGhB|J$cDlDp<$q$=wH$OH85fm1Ti#DO3a zP}ut@nyb~$P314Aq}d=#{QE*0Por0>ZP&FBu$93^srwCFHS-`9TSs)4W^cp{OR5Erm(RXOGbFAJD)qW|8n?TYuu``pFw6l8=^|%$ zdvLzvZYt#Q-~|f;#e`;}0c1JMo-CgXELS`0E*2TU($XPaSWD;cDVKyRnCR-z$x$K< zAuc?QicG{+oQ+kysW01joRb>5hq+*{t<$yk{v+m0YZgeaewv~We?AHrz)Xhu^{l)| z3$dHq(l@7 zsqy6X)EjeU2dzx|p&0Z66mUl@djhRky3YGwnkr!NTTd`DW)sW|VGnKTgDlcrdG$b0o z=L}hx@|P}w%OTbyOGAO8>ENWy!XEi5}|yMa#xoLWui%v0K3jg{&48 zuw>}5jd5$_pxa^c@HH`g$faf_#x;ipsjozqm?KA`B@QvtdFeN`a(@d^2fh$JdYOTI zgdceW8{7&SAD>c;&Q>QEs$XSkI_b%i3>32bIeVi?EC^A|W9E2MDRVhgdNsG2=(T4s zKJ$RDk;nkwyb$h=#BntN8h5(p{KX>$0@-bw+wMZga5KdfBB$xUL{#(GE#J3^N?_$P zEfL03OP|7*Z>Z!;k?-jKwP6=7#;p&USQM>=h3DA0Uw?6;bF)W#slQuptIOAm5eXpt zD(2^b>MVvE?E(1~HKVKi`j_YCvj*orGUkG(C}(L$32@im{Zvib)2-MTs#sNee>dZ6 zTxh5s+^Fzu7^3@XXgPPli&3;c?){gA#`k{1ptD-m=|2Slt#f=G$J+LXFoM%__ko#K zm3uB_Qt)`z#BzB21_P)smG=dF+3r@zCOsz}@we`$_}qlgue_ketZlU*{Kp^ID}Z-W z=Y7ry`Ga?bKQk#NQ!i%SQ@q|B+Ev%qt|3)J6c(`bg)#|X>LBxugC?Hp{T$sn+G-@4 z$uh-lGK#&}np5zz7`Mz4CG^wBaL?; zJ)I+y^j?|!v8rC)Q4IgskB~io5tTP z_8VjY9|_;$L?tkXV?G+~*YXJb$J*u?ZxH0W#X_I;iF$rz>Zv0xY~RD;w#1jYqSk3e zz7^Y+BNI(Mf61B zuwi0jn=i`oHKbzTqegVF6IMb}gNG+PChJoO3MXrg0wQKyM1MzySjUmQx!oH4LF&}& z%~Dq&sJv5L9waW$0=0T`|Q0?R&k4ncTgZV*AFZ`=L;L3L`j1xKeW zI;WQ9B(!8iB{L~h==&LC$Ds}d_D&cDx;PgdS~(%w{}W`h_ZvH&2*mUqqDa{$g6|9L zYkfW2+Jjt`8ia#oS|LoR616VSuzfQ(ZTD5Jv#k!+B%c59-(|yMfQgM!lPTMzN*?+? zMen12Saz&zevi1dh&qH-KCdP2%ql1wZ2X%F1vIHEO?Py2Fz(XHqWLu-?-~T+@UHb zH{+#rkiZxzNWCBu6s)+1Dy>X_yhLoc!$H;biQ-sVy;= zPq}hcS7qm!9-PPcyNX4!`g(BN%||2h3ww`7@q^<*)mAFQetD;F7s->B0Y6H5M);d& z=|U%l5d6LJQW&OzRMH?p&9ANkAKFe?S;HRyrVW9_kl?qcjGfC2IpTxR(*WD1Fg;5q z8u|+DWCpJwTQ)Uqm>jHE!BO?&@$t3U2B~+EDX__a@d{8ALTu zd@X10Zj~qA2LgAcyj!7;3*xMZlsx_bBXDnai{UxZDOoPz=c^Y<&d7Tet?Zb=`5WGm zuqpHaSB|olIYx&tO)ytf^u!KX1l*+xTuU$pg91 zkh#o@DCFXv55W7#8=tPJLUsLb4wu5siiqYr;qx2tp8AqV-oEXQFu5X6IhO^ENWnC9 zMK(xJejTRdY!e9Fx%r_OOfu!$yCjKEAI>0xa%PNKyp7V`A&iF(LP2JxHf__pDB@3n zupSDU9swD)9R{_iXI7}`o(0#VYYWd%y#q>3Ed07*G<2$j+d8&is_|-OrWZYtgH53Z zBf3!uJwR)vAgpPX`5H^uPqR~FXm__{!txKq_L=3iZQ3IlAz+hzvnnn9rx*2uztun= z-71A$Kr2p8D?y8ThaNjA(L5i)8&`fsax;6%O|^V~bBeqjPI300z>mit*~X7ai=|*m z5Z(zX1{GbUy}1|17PxEf#&f=22BRFxv|NEzaCCRt&#xN6j-biD-SyZ)PnrJ)G+b_B z2J0TdH8sZVx88eL@DT}PatrU7O-z5qlYuBi5)R}Yij7{32H-zbJIxG^uTZPF)T8Zl zhol}q;8e%VBUG?WVFMvk@?^Zt_h|tmwe2754I5HU`|8IyV-%D->cMSx{I>(x63T@Z z;Yb6k7ha}5-SGNNtLzeJ`iq5|c%wtN{_zkS zGH&GxWt=notBH3Rx*jH5KKdV3Qt+4?n1cU^roamvNGpEYVsPb=kTS8Ux2^d8FDi~)kc8UDcl1{d!Ayb z3oWb(nSUFWJgdZ01RXPGSt*$lJ+r=(rB4eqqavRD>AFefl_V$Kl1U zG_3MgS3RWWq^+uA?OUvg)Ll9G4WIn6(6y?rxZNKq>q#RthNj$oxjwb<*30i&RqQ}H zF{@Ymu?dT4ODZhxx{S<81vs!wwDQ%FL$ace7(Jln+XXyx-g@VlP%ja7wrWdxcaMb| zSGgiaANygtmLn!tZ4M^{UNf+niTGujocZTjrDWDP#Lcm=C~!>VQ!6vkuSw~u=u&Z? z(o!D@Cs$vOa$1R`n9s)P8-l>sxH>uIX4=}Y%%+EgKSzap3&NzHzJ&>0>h-dFgSQ37 zQub*TYe#fLt%h~Np7XlNvy_m>JHL^U;OWj(yDc~A;%Ve02z+SCyXwOArs6d}Q80cU zf2o}ohsVw;X93c7-6D7AwMRE>Io4Lma1e0yMh)Ge^Ako0^*btzJW%&Dx1;_~nv`v0 z!OYbG(ANW&v%6H{^Zx?=D%%l3XD7UOQ#Po`wJw``Po4Q`ZaR9Ym$aQ@yBP{S(GojK18hS-&01$UI`mXazJ&$hgOaAu zKFxO7ud-Z>l&nMoy(`bs)x_S}FaTk*Z3Z98)pl(Z7hK-wkly}l1m7HQ8v(z^M4k_t z`M;6sSe>duR)o{A+5M*j;#Hw6P5BreP=im%JT1#uCp2`&I_M&PJBl^b?r#^w>~zN? zg*cNynZ5GSOb8xjjLLI8E8r;p-E!Ad)k0Q7U<>!jJiJ9ofK=V?S8 zoa#-X(7>sZmiuU5GO1M~IZVa8IylPK>wZ%8A(JU>*5 z*i{nhp8xHd=~0kl*YSKRCPC_!DaVrR(v&EqRJ8PCccK z9xCC7b-%h`*m_#S6}iof%6&FnY@NPe9u=PBV>5%dS?YoZ!bZ>$C47PHXiQUIz)ndn z`SQurSt|aqoFVVY+^9zx8A%&hy~!hvft#!XSvgm(V1}JF-CY5^fu&a?A8=k-qFZ;s zb6a%#JOoKO%5-nQ?^(Bq=mFD>=D0_~#NJd<;3SbzxR{tih(<}Jfv+G@Mubbxs zgH%Ura}0ZyW89Owg-^6E&}qZDQVn$#)!U)^wcvezD|^vdM=KUAn_IS9&3&wZQ~@=a zO*PJD<@_f1!6SMzY%@;HSB6QC3Qm2%sM2s5V=nu+AtJNGZagxo%;7|fIxkC(l-qDm zqiHi!+oSaBk^F}t2N%n|?y4cK$qp(FI$j?L}tza%N|)56h>`U8d`>&HAdxQf%OS$9gv#W;+sWaL?+(6u2ki zbz1hYlGY~q6Dd_WU}J(ug6;fKMqjK%P&5-s(=I9?*9+ktnLd&!rQc(*T(z!;x&J+2 z+?{ZF&1nuxt+a(~tJ_4E=Ci*~cJ%*hN2f~kZ!eSCvS#5{95j^4+~+}zeINSw_xNp} zU45Iq!)EN)!ft*vT&5$o|3wRN;8u`FD(#!AY5Ox)-r7uG+UjIGR@+>=c8i)QlN4$h z>H@R`WrXz$Gt#QN-?N>A?_6!j(A-P}fhp@eSwiuJbwPl`+x5zu%QZh!%OZQKM0(aQ zv$_u@to^yxv+}9!YVG^j%ytUSmrZ)AM8DSD$-rZ2tK zP8HwBt?GDK%E*m@JA=%PQ0|OQeHl5oI-_^z?soomjs)lWY#~3_Dl>a1DEK@R9hZ&q zx5(*5bhJ2dL0jK;dno{rJuv-51a+_Z4mhHpTZ!6Tru(>2QkC?D)!$na(S6l9sSlY? zAn*sGmJwpLb4R-BmhKdEO7#(y(jFHLlJQJSZVEXulgLF;>%8W2r*((u*Wi~5)of=5 zlhnUHG*cs?fPN^o^MWsDCk`oEhQ@=L;JXeqZ`6j=<1KmeXg`s9$WJe+jc}fp8WBjw zVJjwu;YN~(Sn*6uw-fUHnXN`tJO<no!-v*)Sw-X~_JrnW0sVdLtdlt~O{RK$cjYJ~K=^r@aY;?d>@uO+8EJ zmzes~2a^n(h`+c?1wzwAkon?hVljH>p|bi&fTxG+71eVqaauxNU$Xq^PyG@6^265k zMtvgY_NJlWQHQ!jtOK&ibD=wBE$bD-_@z;*k_ZtMVE4RiSutjc76@hr$u~P0a9`z@OnX1JJoLu z*ZNVxX|R?bk6QKOJ57a3#=8sI?^`vFUm1r!?Y?+4(``Qg){CCUwYlp*Hg;7=iCF>$b=@Ja4$1*s&L}(9kE{$@SJgrQ3H~IyrP% z+KG4Uu!Eh(sIDZ6k|8Pc=4)M&Q zUCVRcS?)G5uiBP|7$?T34(hAC?*?qyipo2P2Oq@y{rf+RvptKlW zJ%Le)0H@1}Iyo~A$+BT^5dcH=Dovp?El01Pnf1VTT>y_1P{i@G>9ESwxGkfwzQap{ zQE6cxIq(aRVayWlY4Tj?)qFY8Kt!)V(0!ep>t$_;kD~IqA*e^r;>ntCIJFa`h zA!r2orL%8V%rh0jn)cxS>b=pgcJo$VI{iD0a%GICJr$=tKGnX~$nw=pEkpdEYOz`J z+BZOqS{K(Oe4<(%Um%axs+oq|k?-8vujA8ROM4D=2&7rtt{H)YTqB-2T@)oET{^ z7=WLU^9RT>39S54v9et&u{_=Xs5jJ#3Rf`i9ADH#{wJfUxUXkZ*AX-lAUE?e4iX%; zWYW?zuv2&z)cO$bvlT`AW}kJ_UD&T9wV z5WYAR^%J5z{Z%mhh7*^XQecY6{??S;l*Z3x`CZfO!WrtbSBMNd_|t6sZ4V}E6c_2G zy$ClOH}Q>T=Lx?Js4gNaO?<(H_OPDVcvl4nfyFI|BmbPk{;5f{{i+42Mt(7R~eQ59LA1(N5Jf zjD|-eAguV}gR#pr{AWJ5X=2KkKgtmolk=6DsyMpL;$huD_UewHdZowrJG?{&9B4iE zCd0(1>gvR@Vq((Y{8N1w+8QN=bpZj$js$n4z}c3CqK!gZqo-fgS>>;57#*gt{2DUS z#m&ctMY`*VDj*QqQ_HLy*3`)kBhrdlz!yl8j~Nx+d&chn>HS_K9mSDj#7V`j%=n7{ zcE=`Ax)wA@vWUvquOh^ACIk|re&}R*b!w$CDIC?q6iWQiKXw(Ya_*K69OUeGtX_^V zZl#Z?CVnG1=!*(P1DZF#37*QDI;0JKDFYt$cSai%j6v$;!6cRtt++oTa@t961fl~< zEQn&8UA4Kuk!r8k`TgIy1G)23+;G3@K8EUiY~C;{_HpFq#8tIDkN2|3lzW$0?9U^i z$6KECEaC>iE=CEyk?+dpn~Qx(a$n!R{o$LJXTw){K zQLTKAHE+0_U#d6}A5XLv81q#yxtqD%jv!JP5bc3$dZwHI>IR-?lhbFDfw(5Mlle!4 z4~AI!5TFtjI~){G{1L%~F)?K^98QNnbZ9D-GFQn>FT8Xz^bX{&d_OKNl7WRBDR0w# z1T@tIwvnt>na=0`ypB|?+k_u&NIRY3w$Y_irv%nB!n>?nD*A2MFMK5&OLr81JqnA| z-7y#+<#PP48?paM%JH{a(d2!AF@gJRTVK$luTWp~DNV31lkswlo13tf!`DaR!JF!E zn%#(__=rYcJFc=+zO397j*_HkUqx|CtWC1x!e45tuLA(yX_3ZX>|OR2#!+;fIv$!G z{Rh7)JQqWaxdr+PPcKvX88dPoa?_6Vz@?oR()BTX=}#P7EqT6p=j!uy{d_GjFbv<* z-k$O1Y>ST*o4W6D1Xp@T!Co?VJdqK0=7|b?FPY3CSw>M!V9NP)%^wcr zKi~Q#TKv&DUPrx_XqWYAKC~O>n)KD1_qojm5?pwYzA7oi>D9b(CZX<~uI_ zV`BH~n!Z)+~8Z2DOp#d}9sjmCW(AM83@#W3X&tAXt+K3nbaFrB(8g&Q>PmE#bvv_c3WgY3g}#{mo6-;bagpXe0EI+5qaA%9WRG4sYj@ z;@!By_22lpX=ny{vB!Hm>@LWB7|3%P%+*M1{>th}i zO|*JgziQDJ&e0}=dy_EtyT^A~1_0`}Djxw&l ztM~6Dv_6|hd~XxP`m>&w{FzzCYkvDtk!$qju&T}I+xS{H{rd-$TJJu|Zpnazqx-h+ zCxp^ReF@)+8v^JCOCAw8!>iblf&H#F^7X~$dX?#sl8g|{XZ8KxQSxIL^K2lX<}JiS zfrA?})c18@%Ys8(T#J*y*oOQqeY#h*uB|u|4|VuGcuN&BbFJ8H`El2VL}A&AO1#9_ z-CTj8^M``xDJpU~;VB{B7MHIO)X6W}_iV_^dFRWQx-DsC@Ksz6CmjOkTYu}Dddny_ zvrE#x_Y35GU$$l}agP>VP%V^6MPIDY9S0BF_JOQ06t*FeQWu<8|kh!h~~}aW_&|>!H8t?`16y$_|YpE6VaG8f2UeT1$)3smJN%gn*qddthzWEn*)~EAmAtV?+i#mV@fUb=!y$=J7x26`mlvuwk1 zFwDCD%~f!amnHsFh&{>yX=ZkkihysUFUdzbeY9-KcO}v&1-ot@T&J(}224dq0s-z- z)LRcb>jbrc7ym2jvRXp^vdJVX1zTH^qmy=eFu2#OZA@;&Rcj!r^I_QEq8HL*4~of4 zv~))lem6$TG)Z2Fv~>dt_s>Q6@|6-f9=GJ?d97__o~4b#4oa)X(n{FR$Cf8*)*R;Q zNItgI1P=9;^p!$a-2vB#QX#v@M=L z*yZg=cK+l@z^Q!0$2ZZdUiQn*nW01eK^y)VGsowKFjiY#ve>7PUS*$4p#qO(PRtD) z-||?4qKQkTpKUv+*ff-rw#ES;5tLCN3Fj9py3@I^#`ZU!3hIJQtqxa!LR??es#T+CfW=u%LC27pVx*R_NTHvs4PqH_)E6G z6**MS2Yuo5mJbf;hh1kW&a26tlRV;7B}k1wSB_W^|ACnKy+@`~$BaR5y95H2Qjyc}O5j|h& zSVwxWCHdMRfutaD6(;{@JUZ_APs035&$k=-7`2_te#W>Mwsj-agyS6uflk%YYl=Fv zY0VC?eHLo$fY3F20bYNNao?PYYN7dOkAAW63N3--9xb2_|Ck8!`+u|@y-vRADX&)f zcbqJ#Df80Hm-|v@o~C`RU+(t1tgDfcS(~<;F!%JjPkChTwb9Uv>M;J*X)vR(zduw|w54y9h=IRgr^7l?59TWgyviSq{SM(2 zT%L*jv&^A@o9u@_2WlV7|3<&M+joay5nFZa$# zHGE6vVX4et_KMPG^eLL&sAz}mH&7~ab_F?p`6H{cPCEu{xQNL?aSC7(L;=h>L2* z$(x&IuvD^+2?|sPBX66qD7JVHYENOlgf+U_MrVe@LR|oyhu){@QZc;hwNxIpms_I@ zf5kzW#OYex{+|VaL;f^@S{L$KTI9ulY~T7Wu}mO}M%Z;iVZ^+(wig4{az`lVavY3D z+WfdkABcqJ4#{rf=#xcG|HKD7d8v z(N${%-Z3*T$Bz$a*YaB7WtAYkD#Jz)LpX;F|Ha~4Ah(n z+mtT*W<37!D3RXhXz9vXRH3&iL+kj=PnQ}p8Yw~L+jSt&DCSx}z#z9L_Dn0tJ*MW{ zF~k?&Vi!5ZC`x!Y^r~~Y3NX7dyI|+t#}Lb_N|dHYx`_bVT=Jn3q4m4;cb9G*dHZ9N z<<8+Y5W9S=cH-M58Xklrj+u?7ucY@l~7K!S;Uz) z_PPJgs9)x^?5HpBQ&sakA+y@-;WNwl20juo@`|fbu}IZkxOdE;BRwS|jW8zN*@3&`Dq?-fTsxrc<{e^9&lldOJ}Mk!(EEq2&MM@ZQt4} z@3)V6VhW-%S>PM`*L$zn$aFA7@0PQxL@kb@5($oEcNxuH!#xw8Q6k-iwQwb-P6IG) zZK>1nZH*IKFv6i)OqaOZ~830WHuZvTjJ#M2= z&EhIXSpHRgSKw$ytE(;>rm6l@epWc@h1Z?@H3{WZf0&#LjnRk=;c(s4NU7_ia&A`G zpLTPtD27f071s2xPYPOZS0>=QAH+f~pDTcDj0i{mg+33t~>&AQO+h^E+uTm5^Mkw~@! z^MI8~YM8?Pj9j9vs&L2r)b7v{jdXKC|3K)XycTLHkK+MWov(6d`1S2AYud?0#9o39 zjs~3?(_}TUtdNyLu$BH2Z?xBVt<^3&2Kw3uJeDIHl?pck*y!oJk`+ z^^*CqlQ5eT&o({VrKdUuLmTKiv(e+faBc}!gtjJ9hutc5RAL$<+IYwbf_`6?SFIHb zP`l}|UF;tdl3+M(W_U+e^{t78yv6(&zurBUgF(cTo&I;yL)I!dD)_C+Z1~CVVuau7 zOuPX9j#0o3fwKpH>I#W5RN#zNr%0++^Yny$KDHc#Ty(^fw#}0`4=+G>`yngr@}9;;JsEjZczskkQpv^f zgsph^ZvmvSmVxVx&<~P960{Dot*}`}Lr-+^Z!~~bK;~D4uCa^yw&Y(f`r~NFBgUt& z|Li_?buy+|y`zy1JNpSCr8eZ|;DA)LxQ=j^*{Ut=?=r2|nR>D$BQ=Ka9 zk$Q=&okIkn3!dA-&}S3aX}dL(hPem#W;EMlzroly5C0&moZs$GA=zAO^BNNu79@mO~XI8Z|YxdD=K!0mv)Kd z4>UH#$%l!?%<$s_W4lc2abi3vl+vAF`pmBRgTfk7?Q|^(U(3wBs1c&wW~=XX7f4k| zzkQpxUACSjRjFA!Gd=Td)7Os`)d<{oNn31G`8@ZV8Dl&)r_bN8X!+qfk!j+0|CE?L zPOzoOT5<44OSKzxs`3qSC}Q6f%Y`2Mom+^@ZYpKaSH>IFcoON9rpVLmiqV@aoQg+L zNul#Xb0wM?dS|Z~H3|8nkj|9Ld6G`_0G0=Ld+`i8*w|=xh<37giBY;OOq)b1!e+wAqW>_0Afbq=_q$q&8{= z%5!f|-ik%yx4g8u)nnK{$s8ryE;zRqMAbj<%3m>l#2<0GO{y272Y{o&@}xT(*{%q) zaxGt!Dw7o}tA!jy<9q$(O76E9A?Lu69|Q%}?9xWPD@R#=)PE2=c4!&IV?6Z)roq>H zYQD{972ehTEl=p^7jT}5^)H2>B|90YxWb;AVIwbmqtzB3-y_S>dqdDQ%b-X2VlW+E zG%J?f`L=*B=NlY!@@d!hTfPyNVy^Hp0+f^o#&jg4bSk})W`uz;rk9q)PHX^4qU1r* z$8Tx#>i3q%nwrPt=vzp}+ir!LD)z6bxF9uwFuIOBW(|cbY(rea1?x=vwxhy1!*)r}B5@ca?hW}=-><&UN3Qy^6|}N| zWsP)S%o#+2wc~a2cVr!avW=hV248r{*uy~7js=jQx@9!W2Wec`?U}#ytYs_qFL~JD zko8sW1EhD{k!hx*Nz6xwNZp1gCTp;$`z*7X-iFFn-h9)+YG_dXEBW_zZ=kg)@viMY zI=bO4PH$Ahzbf$Vx<- zyhgP*md6M6Rtk)jQ|1TT^xo{bD}OLM!)$hoER6UmN&`yqyuF3zIl;-KUEiP<(2!!Q;BUh`N$=IOKLaEYUzM#p zPDh>4Zz&uqpIF)Fb^H|K= zp7%0&OFwrRO3pu+zc!8*vfP__m0L?f4>vaRwbL$lf_8ozZ)-U_+_g3J{8b)YMj0No zHHDH>yR~eb6_izkk5^j14AsnUs~nodhm864qm~7ORLB4O)keJ;2~im`#-*3;Q~7I5 z1qLh$XgGzrOFFUIfSv5uqSveBcdi8PnvFdu&oIw68yGBT&jQQyZxs$|?u?9dMmpyP zIgz;9kM5X@*z1mI9flV#p$+HqrugPpEb?NgaA0GXKhWjK)3UhtTXNyFp(P1c%Xj%Y zx%av0hS%Fvm)o`EH1gUsZO7gw!Vy#m*UtREl%k4yxrnb$mndSEcV0H`11mGvx1An| z&7MeDj=2y(HeQqd{%hVt*`I*{jC9oPI$H0!g=D!Z!WQ{lM@36jixk zqQg7p*qS(QSBe-IPHF?^KC38^qRwD>OC|Pt#QX-TkR6$y9!-Uz6|K z#y3WYGZ-O=bc1w@bWNHmI!0~?N|y{7Da=u$o_&9K z{)PK>-`9O!$9Wv@gX782+FLf8+l481v}RzJU;GyVwr9IH@;VydoNLdKdk}SP)=}A6 z613bLZ9^#w1TO0ui}2vZNfCv~_T^z;bYgDdM=jkYpXMsHMAoEQA?4D%BJ^S;({%bW zBm7<8>;td^lXuS$tEFhpGBl=7<9G+OV#cQQ09m;UFm72hMh9lZYxI&k#IM);wNJ;7 z?$30jQz0LttDxS_4EO`EDk zvEJ=Cl#ue;NU4WCtK`TY{Dpmi>i2uIUClZ4@*gRI$h>pEYta0sa`TluB}uJHFp}SC zmAnE)p;O|46W7K&A{|WNVidN%&L07f@o=%~pWFaEfvQ^))*KFE*xG(HhF2OK#W}H&XLu8sFXMmlX_9Q`7qB?u#-J}c=6?ai*K?g0~ zEk2F4%y7d$=Qi9oG)2af`!v;dQW=vNNSU({@_D0&g7!IzZANnV^)q5Cv2j0Igjk{n zVDGe@qWAjCdAn!fyNP62)`$B|Ioi&Fh3}P};hX~3zPS`2%e1LC!>@gRw~=dV1PicL zp$6^dwaZM#K)?R#Q=j2$SiAoAT z`X~E>t^+MCF2C$bcu=)m>vsktADwPx;xhKd(gZ*JK%50<_Xyi>r#J^Evk|^&1Q{;Y zzgm}Ce{tdgb>wpTupea}^4<_fs}>|6ag5jEX<2{5?s&5KI&ewF|ITuba!xFPm{tEb zBc}^Ze{oWY*%$LH0?AN6Ds=cft5i3c>V5JA<*7BSq(m&t_w4Ho6Q;(d`N;<)QhU56 z{}5PILbC*%TPl6qYBUEURS*0tRr7JZ^PZ<6B;PihwPkxk~Xl?Qfd(dDCR&m0D9viMoo z;7}7an&e3gP$7;Ze2vn1&G(~`@`0x1AB%ntsahHotEsGlK9ct4i3lGimA&LlKv+ z`QBqe<7pWj!TA2ItT6~ATj9Ji>uw1b{C2IMF#(H)M zOSc@q;AMH&l%?40rk?YYnXask|qO<)agz8fGyhSCKvXLM! zL|m66`PTPUEa-)AWY+w<{a5w*(0i^It<8yRL;Ve{vTn~eev0*1FkwZl%x%={8%Ywu zj}XLnIWu`aC-&PXUwQKbf61-$>XPDBOY4w7Xg~tC8>JOVxCyp=9em-uXMe9geThjg zej!$KoU!G{^h}iZkV-!{NSqQ-srh>|Z>P-v_zssj#+>QN)`gy+_19XEwIE zj;LpE5y`lw&qP=Iw;C$$>isA!yv`X47~pH7@uc*9X#x@>dlvMdE;ZQ`L4CmK=*9kI z#*=%AKIWQc_0LmUZTrOg(X;|DlmxyN{1?ycLA@`{5-rN_0`}cX&G8K^1Zia2Hzn+! z2jEl{&qZWBP7TmOGI)wN)H1pc)+(iiSIxrXTc!TF!KYQ{gg^?Nl9V2s4vfL?EP`n` zLXz3q?ighgO2mURYgujB3kh@lG=8FM`&PX$olc?CpN^aC{Wx`uH+_+tZ9ZNzf57v2 zld90KQ~PV<)E|$JjDBvRSrv?k$4>Yoa7tPz{{7DEfcsIu#3Dd$N6PQptru&8j#w>K z>gyxZM-S&32YGNHV|mHlJGBEX_uJ~E)3QhzFRsXp#5=_&pc`AxL#=GiQ2M{_H!&y6 zBbsr3te2DhXdX-vC;?8#e2mp#%Hm_{xW8AgvJ8P^7a z9xly&1NTKrU*y;87J)T3X`WHBPYk&>X|?6M-&dWH{i*;e`yVeUr|b6_?^LTe?{2pe_B}CY8+22(pv}_ zY~hhttx3G=dM8@z06)^it-ef)#-pTxR;SS~W(Do{qZn2-<{jQMDV7`Uu0~=I>FJsg z#LDp9+l^e-6<6hhk+%ZUmi-v@Y zt8Miqw(*L*ku)PSDv74FN7#x8ky3-a%#n*;RX4UIT=n0ynr7q$5ljZG47JX<6^*zh zn#u+!7#Whvyc4+a=s4=c)`k>rC3DnE`>8k5Cayk_jpd94--Og{!KuS>i#CB_`PoA4R(wUCMUs<5e10_4+)m~{Vih$z*~drU3iE)PB4b(k>*Nzn zUH?JW-8yl3h7M}A7g>z0l6a^bDNCIuxU-7c$1BFr&vg<2?K_!{3|hNF3|!-|9nua=oojh@Z>9NDE~IRxYs5B-b~vKg%bmaLPkQQ zq+;O%INb@=$IME$!#e4jX()K{`a?>fg|+|Bxew}cXWzlrt)hy*s_rlNu3g)(TPUGh zQwVNygcZR`vbejdZM_tss*-MX(t^8gyq5>R$cfyGuWTio>vpHJw=CyA@ul@5+RGWn zM^%WMW^)heyqrzd!SFiO_c@DB^f-&D((ttc)o4}ckYD{ob;YNjLlXa?e0Q57k~uuX z>9AA)lpaCSrt1&QR2((2Or2NQ=bUt57^?7{<;yL_5PL?W{$Lm7PlAb&gZj zarU!-w3SbO3JMeIEz3F|Dw9aFU!)nDjPE*sES(c@?a(xH1;qjf)lm-L+Yk%6dZO+$n0|w;uD~y`NE{eGh z`MaFJ#KFG(N95aO+JBucYJ{!VR=rUGUe%_t8^7qrtWP%49h<`b6zW6vh|HH)#DMMk&)MQoUKbHa z(tWSa<;%c?dUaCw8PW5hx)SQnMdFo7oHFhmo9tKAY**jL2M_u2`fHj3tHnKFmIHf8BN(8CC2P7lp}*|f#r%dyk?cA&k5 zQXS~xi-D&wjdE(!JMGY`aX;yejMqa7`gKupQBr9eC7>p{ENe0t&2uqSOz`N#J&h%2i-5Odxi~(?B`zL! zTYGN(RjReHOs+R9V4p8(ow8Q5-SCvj05d;i3L50Ko?r?cX_xMt{0}VK;k3;)uU;#7 zRHqt$PuTwxQ$Hd%IL#PI6{Ni>Mxwn08KY|q(|n1>YX9c{ku2Sz5eHUEeXl8%C;o*C z%f#mR|0uChEK9&6duOcXGHG%j0FmQVJ%mXnr4qU6q5gZEv+s|H+|g|pV{!{#8XP4S z9?@fEc?PY5M~@ljaCo4#2WMl_BueWPP07u^5mhTcaA1!T0Cz{)jY7uXvFAygRFNy2?c8Mlehk~V zA@fS2x#BlSAMW3LMVe}CKb~vlL2$Wh@RaAmR3O@PIeYMdm&C`7u-RLZxDiEjElTz% zrj~3)#B^}8bsSijZpuuO#R3>z!{>q=KuxX0C*D8S@YI%^s$@J>ejwwrjYN_ zb4g+jrOTfO7pL6x;%;(;rK>Eaf)&!7ZOe>k#jR`lQe;&NF4794JzD4@-)$?dz~$h) z$|Y)wA{M&=hbFuJi%cG+)nZ1t?^huWMrmTfibr=!Fun2G{!IL0qbz6ivVR#+~67!i&PJoex_A75}5uS?bYo+${l4Lrt+#DsL609K{%FfPqBXyz*oHDa4m*_DC#Ly7k zHT;;~8c{<8SEZ^f()2ED!Hg+<6PsQHM;={YpC~i(ip7mSo}mC6L#&f^@Yq2jo3l(a z1Bt+a4qOVZ1{7i+RE<9+l*BC*aQ`!Pci|wF>4hXRWCYJW{p=?7v>*6G{%egqdeKhQ zc2{O&LiwmO;1EKRbjou)O!*9Ne46g9Y5P(FdUuK2{R8)Jo#I!a1-F$11p_em+^t`Z zIFu$TPEmD?b3$DfUK+VC&75u3Htzi|!}pf06Z-+EI@>TI*}>GamWtDEw!ZMlm%7OLZO(@OZ6_t(`b3W@g0`yP3la(kzm zhvew%v2PV$<5QNFOkUWD+`Y~tD*>Yb@&2Bm42vtdqA6NWGO3tNm+uu9>s^J!&kj)8 zt=AAjpi3>er>;Snux)hWnBu}WO$lfu>w)8MK+oF}B-ELe{Km{@xx$6IY!IGhH(|TD zK9Kc9%Fz!ItL;0}4bHP}9&UO~+K?qosmA%_{rUTyx8KPau12_+wEuoK-Dx_nh2U;Qm_`*5Ow^}QiMMpjQhuwW07!c_dH?B`hOUYc?;~Q@F z3FJ*pPtOcM{w=U%KIVut{CbUROE!qzoxz?w4j z^@^x%Jiz)HYP+}s#`3x&c?+Ka?(&JgFh)_#dLVi}3#Y|PlVAZVh=Ca9y-aYguVSa4 zHR3I_K9mSe0of@5=tCbD1K;lK-(3|Wju`b7^cYgT5Cbcu_K&}naNJ+nd6zhIS7FX( zpKSj`?40RAOH!J+58p^{y#*2lQ;` zcVa=BN~d=}P)N23ry1dR^My1#@D?~dn>hiCFKmUtp$XQx3mdKXi9!<)fd+%@FdUy}q^%X!=3&z( zS~S*aVsWv77teWme2O;n9oAKOW}|(8&qyYuh7h!oRp0AZdYNIU+Y(J5+K-Fk6|tW5 ztezSkcQgP zLB42(8WHQi3(ip6Xb7L1rb+*Nv2bz1b@WGWPB;Yc=UmSDh^8ZEIWfb*E-Z7a8QQyx z(5oa?5R%0zh1Q{6SD-RX-EZuV0!kR)opu=7v7KZ?jGFrBNbNIBIih| zeTNY=dF*mM7J^MO_g^Zrx;!^Y+u!3+VE>ntvSkd(;}{490dKb5%n0Q)tfba}n;RqJ zKh7ZSnF9hk2IcSHdVF7NMLX9ELBmxa8)7_LghF-Zx9s+DV`zE$IQ2;1pE@tJ z_N)*8@D!%rj~o7oP4~I4e5l)5+;TW8&1kjpD7yDcdx4+BxTSTtZ)TtP3#I^n*!DTM zk_?)5Y9@PJy7j%bYwnYue<1m=4#hW! zTD;)aL}MF9v_){bbYNDUX>U?)QEc$EjLvB81|@)xgINP(Q*@xsh)+)PYiB!cdK#8t z1og1E>`p*(1PT=4gim=vEdq~6M+-eETh6}2Q zf566CT)gl7G+D|JA{%=$rrI{d@0E>Qd9&u1h{0)Up`P??th=t)VQVbXNBnMF)Rn%H7gCQRh89+f|#OKy1CNcKWC+Xg{t40N7!>?~f%uI?H%aO@(iM$&V;GZnjt2wu=bo4+TD2N_aty@H$!v}!Ek{>*GwhAysj<){dWt{FE*FXBB3X@8}3 zR8Tt3>UYD*jwS=g44rP5kF25gS|qtqTIP)6OT6TpZ4DG){V;#pCba%ZsVDxJRN$O! zARNZdI^i@bb5GCQu2;iFmiMuYtgdy>^zjrhXCmcb?wQVUl<-=?{X*+h27Qk*&E?t* zQepyu9dr2e3zYAzU>EVl;#0ki*`(8M7hETZVO5qYf3h(n=J9Y!pcd4wYk{; z6LR3ADiY;f(`irj@l+f4;PCbV?2SnDzp!c3V1;OSQ+pTAL*MM9AeS668$xMGiX0Ma z)j_SM>F}?u^iDW~$JxsYK2idK1Q~F-Ven?8`X^~ey|;faN^N~|v|z*AcF7Ir{@wCEgtk|n?@tM{gl*2u!icSeLX z>*e%#=&s{TyP~k;R1FX8i*9!PL#Hq@&fLFLG_Ga%s}2WwJ07jI~WkxF{kI)v5s z{09bhbNveq@7>x?ye98l?}96Jir{o|On77x+b3Z4K87}f)^h90L6c^pQdZaxAa~Np z8VY1i`p?oENw@Sf@^eFG$SZq=!1dkkI7C;0o6khf4Bwd)3M)K+0B*#6E2;xv8Hynj z&KmJhbq6)flJAXawUpNJ8srYl z%<62bQ4VgcZiMZ+RVu>M7ADoOmC0!75Q{kFhM#H@HG?N5TuRyJOv1&rL{)5fCAxbI zw1ifV2*i8tNQJSpCB>yT>)QSbq&oI1>9N0Acr+x`R`$rs4?w3wiaOwp#ePmI)M;Px z^~5JebVW7ei;X4*S3Ff|`W(QxGHzKXu7vuwZJwLg+UPp>%uK22qIm^;_!d;ORBkgD zME`cDqkujd8!wap>dv}69l%zY-#1;wU@Q%G&H_N!G7q99P!A)WVk3hh)t620MgK;A zxT5U!CE$jB_sC1epR*%?bM$F~X#$;Ylg;y^^df1VD(`Trb8U`LCi(Z?5TmmfYJ)lI z$%2vzvJNZmk@kNy>#ohHbLEDHg z$id#d_LZ)L`2r&*M^yF^P?H^bN%8XNMQEq46-wAp!??~GKrJaFKlwm1fum3d7~g}sk4U4C9|G> z@>ufwBCT>d{foj)4zK&exca8iRLz&Vso=Xh`&NRP>e=ICAj`{+5pnVFbKeEf6qTU(>`* zx<*i(w8IETdSht8XF}rl5<`f!PWNi*cJSU?H9u@&7G3d=f4p)7 z8iattS%4OW9YAMmQ;+^u@wWD6A|8W$iDf!@4=RxhL;nRBqo-{wf_wEnp=mSnsVjUI zZRxbk#Yo-Iq9L&wRz510OAUl97^UI<7|zXCdH}_q;WD^Z_^N8u2i{^ylisle^z@00JyxV zoeEjMO)G=xl9J}CoYzXF6+uXx1)HR+^8Nko>2UD*VK96lG1T3%aBn`@>85V*#kf0* zGu2LB<&7Juyo$XeukM;M0g`M;8999~%FR?*6qCdVsl|W<*7T_%9gbt{HOMb~Ck{_x1W`|f85Yh%Zz*-b=bKDP!5qdmB#O4tnNlNo z#np(O*4(Zx$MFvfpS|Jk(O$HnrH``_g^t+8PKx2s^}?Nm^TpQmFK_T-_P2_L`0aDL zjs+*85o{i|o#>pquV?QL)45JsMcxkEluq097MGc1X{ch&C183q&FzL~7^{9Yz&(HN$veo9WvGOnJA$N~+ zofK-T5s%7OeNF#WtXt=~6<_Lg!SfeN)0ET4-Qk}{Buo*teHVRf;jdNM8K_P}7|Uhw zTOTupc{OVP#nDhZNLG!)b9-(NVCgA2C=0j?BvXSAzO%8Fct{fb1zY9lzm;&?Gu68` z{w4PYQw==)tf*iaA1&is)o_nTx9S(~I4|FRS!QE4apJ$u6*p_zB*vD(jOb`VR)C>Z zXEqZ9E%kXTQ;$`dbVrCGkKcc(hJ6h`HOMizrCGbRI)mM`YDW4Fz;)zM-DXn(rOI%e zp`*MFC_j1!7HvsmTkVb-W?y#U)ODe0!ri27we8=QsVY*8nD!*B+6@(lQN5fi1Nl^& z5vY9Dvj*WcyucdbO3A-qW&if&zBovaQtN+;EgQe=7yz7!8Z`51Y=wkYZWw10af|0n zquOq&uEULyp?8ag&ujm|g*kVmwXz=4ih`;K)W5|iXcat~2%2%qOZ;!E@Iio!6AO1* zbDqD9D9uW0`$p809-W|;D3NP+S6edSH6Vr{K~Lqlh~s_3OAh-sK}V~sAy7!0qR2I4 zEnN8?KnSLNC5iHxA(WUf+kO3hx95oR{vJ@f0X8uhhzAy}c&6eHeEt+j$K91QHdmp({`ixP)->QF3{#M` z_6`1@qwvVq+@Vp1-*wbymsj5knsY>lDkWSa@WHm7eP?Onms3dr1PHiATawusQoKR! zrGAwws<|yw0XrTjkuSC+rfMi+I#z|~qW1k=p z@_K)I@Nf76WX+uwC^GAg;|Rg=_wQ@o8xb)~?Lp5cHmDbj3;76yDhm1{$v>VnQ7=6d z{#j0;D+H#M`bu`8PSzNYre{!b1ACx={oGt+mQ9|ud90v);0}E~bttHJIf$YRsE};4 zxbvX3=Y*B=#FROe%h+A1xP=(Q_$5}667O!R;O~7WNI)-x6UDoZeK=h-G$Q)RnOtUt zl9yF2V}C2m(6&Xu_4`sc#NBeM zw!bksIw<0umaNB)^Y(1}stR;XgPf1b7VVObrRzw1K< zp4+)dp*!4ICZ5sgY46kIPb?=DqRiHQJ_belONFOyzmJ?krE%E2FVl~98xP;`GCEbZ z54$lIsq$}BdOhKOK?Tszngfq>-XZvOl=4&G5KQl{65Abi2G|q1Ap3vSD!1s7pBPP; zK91mNm{e!AZk0A#Gm(V+>ZMmL^S1^eHu51p)K4J*+KC@~&bGDPfhj}{j8h&!b6g`L zk@Y2*l$Lj!hVzGoLWo^PJ$lf!G6IaX&S*wp>ut`hf>U{oH&!T>04i}Ca+V`{hMS>t z6Nnagqg`Zg7Y)~S3Vdo3MSsy6T?z%4U(laXoBCTNCZVk&*Stj5;5TK?JlsopcbjN> zKG~{pGRbb(HYa3_zH3xkl0W=Q`@;U;lhoMaVZS<@aa}L{8i-^LVxM?dX2k zZ`xc*E8S#2&=YLokkAod<+#DW7X46{?@GN`?tI5US|_wd5!Xmt>6@d`dna15t`S{b zvj*;&S3ReH@)KULxk3oZjN2_mt5jI~`Egp}CMH`3$a9wH!T8f+8peOYh*_=C%l30D z5Y*})!hDO;p|m%#;5hv0f4r{Ky{+n|`!(vncQE?kI@*djeR)-?&z11*ZFD zA?Ep|Y{QY}7K0*JUgTmzBv6$;rggGNdeD{6@5I9nkScEz`xlLLu><{?dO0+c(AyV} z@t$(!?)foBs6%9`x7veQ6@K3=+@V8$G;_cgg%NqI*}u^v zM}+)S+jI6KEmqPNX74KA{r98%sDNxfQu#Nl*PwyVit?eYr#s)&8Yxf*T;XMGjzib>Z@N(Q zB<+_nfKkZJy2P_1FFF?B}Hw-?VUlVTTsMKWx(a93>k@;I@g% zj)Pr$KAY6z1RhGbi-z{n@UL<&j_-)dMh1ilu_LcqMD0J5Cy{Q|zqM*x&aHEf`A%6E z$1eifU%yXU6(iMe)7utp>gk;9h-E0pZE`6E@XXt~&1O8!IX||FMcDv>YA?g2biUq8 z+C)9ZBt@I?H7$P#X}my~v=41bw`69hQR^Q#wS)ly*M4`CFh z@}r_*z+>twKlv_Wa}JZPu!)58IiHT4igBEDQ*E*8VxYU5fEXVG(%H#}l=AJ-%1wTu9#)Yiy;B z|LG@Vk()CD3V=i0E4>u&s3rHj|6VkyuW*)p6PqJXRX5~k^pY)*G%F%&#Q%K!4esIU z?)jDJ{K)2mDs2Un4E&p6d%o}dJNg`Z`&mu2Pi;UDD#B@KN_gTh!${TAW>2G0qK#c` zsGw*n`kvIIYD=G?Zu33?O;4R5^&ES!DT;>Jov2KQWXg$yc{M^`&P+wEsFyJp+jLJqxcPt2;r$(jrVdVG_k z^KDjVD8q@r(L?5CG>seN~4W}v-zOpOO5;?^rDl%BU@S2_B2ZTVy0D;`CY|5 zxbNbGf>&`?$oawGh(%bFv!v7j+LAL9KoebhMt#@OH13>Q4$~UA%+h(`Z90z~9(!_$MGn2caY`wAp=7QDTm@u%h$4Q^bbID=uUroU zcBgSXpFqE9VTj!WzFE03<{oRE%AN0nS$Wg+ncl zU4N-WjAk5vPv1V0y}zRnvT*#cr4I+=5WDRVYq*=rX5454>0xKmMp;MY!HTF#S^)xMX?BdfQUBd2zok! zz)|ILqa&(sKiG;qzDr$Zs9ms67clv}V%rgsg+}0-+)bGjS|xyzq4s(#X9WGwutuZ_ zU#ipyLLn<(Nb)hoAv<6H0VV({uW8G+Lq}f)wM&#?dRFxOl-f($hB~-)*XBcl#<;%q z7?1OCv+l4@Y@dOrn6XpO+KVlpZBkNzgwfe>8n8>E^kvqU?#87BrW98Y)SGF4xEE^- z0vg7i1DK@iR)H(4d~lwXcQ1y_xW^R*OK4<9=-@7czR4E7<9_dA{j2ty_Y@V>WFXhH zFTB4sZ1W+Jn)g&4A(;QIN~!M=o;_Hd_^*V#nG<5<`lw0Qq|ZC|d2Af16IV;Y=aCTy z>S)hdvT&G*QlI@%-?w>}kB^4fObaiBm5gyPxsOQ8e*HCbQx$FpQt51!Q?HukZS7}V zpKXx^K!Yb7{x*rzIlYa1wJ2h|ZVETNNhn$6x9jlzk1B!}SA1T(+QiE<0 z5pc#m?sW&CG62#5^y7X!z&X8jb9+LAK z#bX~9z%|az>sNgu-vhOAeXn_M-?X-in92V3=Fk;}VmmFERZtiiP(2K+CE}DTbtv*P zp(-LSIkwX316TNe>kR+`> zRP6dwFe%rx{t@=5_c3o&{AmpdqbOqOJ4oPNxm9e_BrUzmy93|_h7+_z!X+}=${7PZ zM7{;E5U~s&l&9I+;$@Ls&%V+v{tS6m1+#nNbIT8ab;>#zw-E|>nfgnseQ+F0*+UbP zAqxM*Lty0^Zj@-1fR6V?NYLfaQYr7p^2!bZ(HP)0-BD)D2M+JnO|s%5yOjVL{@;MK zLDarSD2?Ain<7gSo7cB(uR><^?&Zpz!r1^i%Xq7{ zptlR+z`IT2RiXTz1r%`5IZ)3@ehdlJ2Ew+Uq(~8RFX(SKALp6<_rxX8S~RSE)3!al zN84H*0Dz=XDXh{kQ_JksAO5JUf9djGkc#N;VN5;d(58RAn8F4=KWzdpp%j6ptneY1 zVbB?94W=ZAC&wV@k=iN123qL`$Q}pUSOtfTGl=h%XDyBSbZ5`pumrF(LYE`o90tFM zHRZ;ChAd=r`b>&+56CfVAK~2H-qjlqgT5b0{*`TAS-S6KWIFB+nOzlDrwOOzcltxc z?vy**jyT9rxgcm#&k0R(F0|$-e-<9rrB!9s&xk*j;{M`>@4_g!#uAI>+(h zhs7H2{$&l4SovvTD{kdLY{zH6nIc0kY$>A5YDHPVy4K`C&3VnHKqz!sE#L<8Qs6R7 z_;w4!s2X>fvk#TwEU0sm|MWUz@9n$q-g!Ls969QKsu?4(+j0{Q7Iz=)C2l<3vPImT zmB&{0H}hUdM+#W#7GXZ{&0qh_#~1P(u~@Sp6!}!hZYTX!9OSF8*8WZ?gi1mGqT1pm+10vRrVlncb-73 z5XFl=BjQxr)O_g-B)BmjV=r`>d2H@|(T{N0(Ly9OeC9gk3cHE|9R-?)d&vyjpr~+G zir5b53a@2brna^64)ZLkYhzu)-sD`A7EHJW{7+Kze;Qa^Ge-+$YUH!H74^_4!+=;V zSx5xS${v*okfsklAUH->fncCWYPJY125KI+(VaIL(S+2y-`=RT#W~#K^w@c(;3ov% z=ZZ)NpgpA^AV=&wwYEop=Iqq)Kt#_7Qp6_g;JbiYWNY|anp!Rg5jBO{fzm6$p#!eJ z^FwdDRE0GycTw=mXBUJOtNdYz(P{JB2=wT$dqBX2Rbev&ns7DS>O7(g;F#dS}oGp>pg(&4QY5rUbKWNg zhKz0LwFlq3p@_`QZnFjf1IAmu@!pUG$yjIR+l<7pv~(=d`17>1K;LfH(TY>;4KX~2^=1Js1NIioNY~d)5ov-e*L!ls|1rG@KWZ&5Jkv5Gc-7(m zIdZ{+f6c^1>^O+<^6{3bC~gj~6@d(#>Z#b_g7A0|zsG^l)>-d)d)&t8=BwFEM7wh~ zj~!rYHe~LpT&Mj0svY=*=A95CJBtDl#Wa7mAN4r6zF~%E?SsvnPPjTW3LLsT_I&Qj zQ!GVlnDnPpTmv!Dp%sV6Y6(dZQqTZnsbRf#^IK#O1S)*Mo&pr+63sQGv2pU92~4%L z`LLT2xpX}*i&_jg97qKm0tdTcbXkjx$R3a=0e=^Zbl$=!z?a)A)OYo^pvQ?2jw zwOU0#OwltfdFt7AYW)hNO)-0V^Ltv)wZFeUCcDfSqT}2f>F%7znNV za|({>sz6Fv@za{#2^IkT{}lJ}FKSr;9_nTJ$OYRY`Y^9VgdF=fU@n4nB3PaxE&w#M zpq20~FPLWzr`L(4KB0Uv`v<_R!xazfaZ(cIBX1sb@seU_?{@XGJ02^R@99n1xYOQR z+WPD()p8>;ayy9+740ArAJE@lK4w5yfZ$wsR{5Yf%G@{Gdp=&zuvJ2)HHMrd zF%gEY10kMDRAkq6Nz6F;T&27L_mf6AZF$i6;KUT>_y_m@BW3OCL20|NDJgxFWCs44 zu<4Pw8b|)i&y|$;YC*p|4msb;1z${74{+NB!s|hy*mvJ^n-=hQ=Ylel(JqNiR(v&H zyt~TzF!)|`#CeWNEkiL;jF%%dhYz`x1Vx5k-}Wv5{VF zq_K4eh+~h=Yi%!HTRsv940(OL)|(CLhI*2UTl;?f#2lnXa}Vjsnv%3hjNq~nW!p@q zL%b2Ll;VD%=cazQlf@hxCEf^8n%0Q;DNUYv=5I%eGS57&*O$3TJ0n;C%Yq5q z$8*{#MEeV0@m$KH!W@_Qp1E@bh}D=GhmIs>TpL@{X&x7r(cXV#y! z6%!8sIYzjpthN3A(p)dNYV~@$nj1r*f56n_{Q(jFKi~SOkQxCk==iv(AW~9>qU`cz z1_A!srY&^;3(bg{cZ(-@-^{||)8VSz99KJ|X>!=uXgK^ zf1-+;EezUN4?#H0pzNJYBv(crn2VUIfdQA;HJ;Pkw)2|#)%$s8!=NOnN~%luyQBS` z{@-&Me_;UI|I#TsU~^N|njYK&bSowbfOlhbI4t3pmFLZnFyU(*nHcxB9%y>ZEx*;s zrA$GqBXQo~nI8g79JRbDCpU9}7Ni(H4*46D6^63HYF5mYLN&|7FJ|fnAHr1gCX$BH(5Z zR-u?T*FnFlSHRn`(%QQGSWa4xdV+WtfSGYMf4dbv9)M5OUl@e&Wa-(Os9xA{*r0W| z@z+nBjplr>^=fS%qp(yn9YoChkn+hLesRK*OA$$DJ4o|EL%NE~(pC!j zE85q#@6jH(Cz4l!!w>ke=Dfo>!wGuF0qrWLW!#hfb z&Oms;otfAe&k#WxS)&}CG=m+{srr zgZiz#mq-QV?M4#7qb)UUW#@FGSVHFcBaPa=hlUP}4%CThN*877!7C{YigaNBzc#dl z(TR{J0q9UKb?q)CuxMn&Jo9PJiivQiv{ z;)7KC`&iBrg>io&3KxCQ(=5@3o&O-wfO-C16uc}AMkhiN$X zxWvJl`R&HuQ}%gan%hD04>LC0F`imGbhcYHOc;P8a-qn3J^*{YV}48HlH&F`ty53j z!))BEc?NEWgw!(%nt3iXeN#5P{D0te;b$U~JohJ0_wV#?s0Z z_sQny6AZ@mk;)6GdRR)sHyMkJ+OKHV=dci` z=JHKV5iLYxxiUG@6XpDu67Ycn=);P|PQBlX5C-aRtPd=%T-@X za}tI!V{_1lb8h5_Ul-7-qziKz$Aj6NesJM8G$jpZvy&R2i5VVb1TfmscL-^eIL^i} zDo@hE>0AI?L5MN_(4Ea8_W-zbUV1&~gjB=(@$h?-;L2f&~ zBv@4EIZBm+zc8LsJlrccDK@qVw+&+9nokEN&Q`s$VpX6Oz*6WxTEgpEI>$NVe>so( zWGLBW&ajz<&w%2WkogAZfDCxGI&~(j4MTajKnL>CDeiv8JYR__ZWi2*V!2DJd zl1e+PXqT@}2Gz)iXWuN1YEp{d=o|d^;pAfozCacK6o$|og7AHnxR|;AhurX`I%F(x z=4dLeY@Nr(~n8w&l6cmLkCW^<@f7;S$AJai`A$7& znM-BkPb$eJN$?BnV70r_Q2GDS^wn=sc3s=o1SK63QbS3HfOHIvlFBWDq>@UCq|^XP zcZzhYbPWxI5<`P@hl7OVNar`c&++{MGe7KO?`y4ft}_HjF18;r90N*NPzwBR^HkPa z-B`CzGc7cC4BICB`O{a4OFIdQPfB!%?+J+wZYOW%X(fa~z6wOI4H>KSSs6~bbY*Mu zrzK`Ir9DP-80?Nl?!jVo;m(S;|R$RbQf!cFK zm?sGCR@eZTjUdcc)b1?KUZ~u+&iG(q;tvS=_Dwp3Qg1#z52*G6^sx}aj$_%>xOCF9^3K9)Q+?qQ!2{Qe7cZM|gF^V=WK!Te{t?tEY1AvKhB}#~ z+$4wzNQ>Tk78hH8si!O4x_OJ{0QvigySW8I5#w(ghvn_o7YI@hx)}H}U_N)0{kO}n%oIHs%LGwahln-ss^((oO_9%BL^Y}J~_|y)jTo_CN+@)+)Rvtyv6%4 zU{e9-8ku$%?8e3q`)J1bTG5ir@~OF4&m#nftRZ*&ep#ITbN@t7d9goV%NTTXLs^3C zu(`s*E(L$pwgTA&K*>`e%1t!4((uB3k%nR)h3SJQ?q^dO45s<^$*I z6P2dHe@b!!nzgBNxscio*qYa;bz!y={hl)nEPd#|nZ2W9!zw43R0e-fRl57SxXBr7 z=e4t76c0m1_Rv7iTMp|(Tjc%#UyT)#~Ek_{&Pu5{Uhu5_RXq0@i4o9%#7U-HCiXPvE+j6F=o;I(G% zcH^Be{p}~6oITZ+#rz&Lez#`JQoaqul<4IIEI$T5m(j#?a65K))8fmKZOQI(=Tz=_ zS2NOcy>nx%0oAB*Fi6#=3mH3TuppAg33P*~>Q;MGV+Oy37ORa|b0#R+vO9SJGCS9_ zaFF(#4I{8n2C6}{0wa`{*5nmgP7Sk8D9)7)lm)5-K)Jwj1|1I*2y){l`dNe&?*L^cho*gNwB)&$JT7QHFtYwlx?%6LoXilE*xt3*E5al zYD~Rr*o@0&@m>j{+WeV!`jQ1_U0t)S8fg84jOl2gct&2jiqt=Ts7AVmiX=Xx6+JZDT)*zz(Iik`k8Jg=4)w~>uc0XiIvkHjA?W^-1h{A-%a{~J*K&jf56 z0gB1%>T`u=mInDwb~OPiwpvM|GY~kr{E>dTnYc+Wg9q1eV#poTDWgBxu#WWc03D)F z>D|O@{$p?<6AkwV39^T9exEtJ<2SvtBxUl)?eY0L&D3F$!gZ^3fS3wV*F|t2PWp4( z4udNM^_79@ZC4$oSEJ|sMhe8vok-7c-gN%~g3{xQ6euPBDmJxgP@zYLb%_v)fsi17 zQcurTG-$HI&4XE`V~eJd((-4@E=vU-J(v_m5r@jQjBtvtltbh&Xd%>AKC%KtMxYm? zc%wilnFL&Tn{Woo0}6ms#ksFEog8zYUgZ!wos%hM;0+E{jaR0R*A4|%Oe$Ea8+tz_ zn9T!STMPK~OyPm{s#iDlP0pxz;`wE{=#U>Jk^2hpaB?Df>}vwSx#Y}AtK$L1ek>Q= zabbDl>mPwL9Ot>DibOrL`F7TCqDbx?Gh!R~ETbv(Ye6+)v=`sfn`dx$M$?M2iHB8z zgIr>jHD>mAkzkme{ef>nAr9If-uEGjbNoANmm^rputU@+!7@9?i5L*@ySQ&Yu6U3x z%)Ui^hW>!h_+7(WP0OAsKT6&{ZP#0}mlN7NLz*r6vLL{!{XyswR0L^lO!O%j!A7Jv zLKX}yhOfZvU*}i1PHZZMkVy+b#9`e&{Tr=so|ZfVT_S&3uL05oy1VnsH=b`%=`S4` zcmp$qdhrJVyG&fHOxp-5S|tGBjg1cZML&e^rVc6s7UJb5R9L89fZo;)3b!77e*rG~ ztXJ3L<3PP4o`F+^Dv6?L1jaVi>3q5QQ0C#@Zy&t$|(x1XXxK=(sj}I?L~jC_P*2?xj%} zk7WsH4o(Uyh&86R?u$}H;^}{jVyW?k}U$kudj~bZDm`I$MRZdJ-rNUx+ul=}RM`wtyN)rN5p_{TZ%N+FpOhsqwrOrb9(Dvr z_p%21ZQz`}Usorg&9gS2+Bzz?T*V$$`q&iEU9YE_IO7EFwJrPYEoDn%UOP}7A~3Ym zc!(Wx?q~Sl3XIUQ*ZTVuC)VTxotublhLol7_E;~vYc@#e=uZyW$?M~vc15!tC*POl zq_zKHjitCJYiaUOY|JAY>UepEb6b#?nt8{G?_n8IOB63vS%c^7>fQeMR}S|v4xaz{ zPgV(@QXF;cTp5Ifk5YwE!V7&oKxS{hRb2lb#fYikHKsq=IJ%}5tgU7GVtk!fC{zPb zAXIAe&GFlCD$s$QU;49ZId2!Fp%N&5M!;l%)ln3KayoW`lO%cVWBI=bF448ts_Gk(0TMy^sEH!aqw$AucC^)nFh#TlHTe=V8{^kF zjrUUoE^WtCHESPeBcjn>35N;M%sU^*@;jccqF8;(J>}0aN$Vu7mv#tujO60lgX_3V zXs9;vJ6QNfC4nNdjw=T$%Bb zf#_?KZ*g#4ii)|IZYGStvAD0Z&-Dw_Qy|*6iTv#Cfvri9;=mS=Uk4*;f$dVY70qvY zQD1i?=I|N>!YHpnW03@2^_!Yz+>dnqNOlFDw zs%kN=loYs>dzgCd-$_{`4&5z@Y0#-uHu6_u?a+uHgNKDx507W1+3*w6q zW32wU))eslB*?9mj~M-_4_Z7KC#(csNr!h1d_j(_n2fI6+M*%!35*o?(J&J844%lwS3ut5y z&^*q%iKiC~z7>g-WB@aDFB#?cfDsiM~ zH*C*jl5Mu-fP9c|tRGD0rew9992b4WQTkygdAKjOy)X2tPRAS*9N;1I%5KhWF$MFI zJ2=8GC8B&2^0N$Q{1SUoZ&otV6h63(9pA@odxZXNdpt>Xj@tCVwsrm^3%Sc_Br~?^ z(qv@NQCIVaAa0!Xh28m!E`77NOxTHG$QRJm;L~^NID4c0<>xVi4DE1C#^qe%Q#zPU zDzz}^**^c((#I32XSx$eKx?0=^wwvkXi=csE5!_Bju0*(vdqvCb09$b&~A`Se4;#3 z&K7eGD|sOlRo7y_REI}T^g%RgS0N+Z?{ZsB*cfa8hn}yN>u$$ujKVfeA11_{AgnKY zwwUApEC;69{W-UeM4)s|2?=m6e*CBBwqF!Rk~ebwr^wG@LYVlt^`0&&xb_%BBvI5=R=z|C z&Z51{p`BSi8iLO<^BYh_^F8Pq0`MRf9UXdE@p@F?z}O9$*B%V!p0(UYVk=?`z=wPs2p zxiOB4%5l$x?cD6rj!>za45$(>843zQvKiWYK~Fp&mhQYhXxC z)){wl)ycpF9`kS55{gzhB`AEk$vxDCf*&A>KAi8SON?eC$MTl9{~$PS4lKA^KV_+x zI%#i5SN!qIxDhn6Ho+9$`q&X(pBxis#ykpU$)#!ZSoURc*9lv4I&@R?{VNoc7JU52 zr*$j>1~)-Sp5r%;-6wSvC&ICxJWWHCtA3AtD*nr!p43`<}s;kWBxu?9-Gbh-XO#7ZB zV<6c}hL#Rxs(wG@cm96t(3Us_1_{ULUvsblo|7MhfI$**_*R4Q+61Xc{tuE8;S54J zqUl;Up(ssg=;`MeQdc~IP)ww!+$!l8eKNwmpT0*(vVciE4EPZ$0g{E{FuCtryWQkM zOmB`*1eT^mYX{AjkgqrtEx(a@3T!bNYL&69j@27`#=stVwb+ z6M7Mdv9k!K;3u}8MJAwCmw0ukq{^tyI+Ao`$_DlPSha~hy?(z{lr{_@aB`N?s4Zrq z;Le<__H0+HkXAvUQ%PZ6j)wD1N0Ys?U8_9Q+?;^{+Y&?L}tfUEnA2hHZ ztiMA&1HK9ptSe!y5)`hvlu2pk@*P{Z`*jg>0-b2LS20hloy6OPcyC4tY$|F17Vu2J zU=p8Wj#8>kf-5d0F68`mtGx+o3g6fJ2l3}}sG}AI!a|gT(Jx+*dF5jnnpD5RUzer! z8kbJZ$PZm2s9J-N5a$k=$5jhsX$D^tA0YW)2@e=#lCIewwe<7si=@WpebhyF4(#n{ zx#kPtU>eyxMNivqKBvLY5qCiXzSbkyHD2CM%T2UL_OzY*rWlTn@@(18dNSqWe+4J( z5%`wznw+|qx{|;gY&$L0-~*8YI*CB&OatUl89OjM=9qPj-j;X6Xo5tdre;0i4~6Gk zor))J$qtA#YTNxEnXg2dUNvZ;Mg=lzWd?V^&r9#SgB&s?^{wz!^wk4K$Wyq36Y>?cGLpI-aqMHmt2kw{~XNL+gH?sE=;%1#MxT&r14s24WH1CU zsZYWF z3sS$gZ0}ywcP~L90GSCeb6qQ5dxfHwFHm7wA!@`&ZuK^7IF&yT`@_$>GbJx}g@sfg zi)WNM?SZbr9r)gtRDn8OY4U>n0S*QdeCW`)J4Io86ZpY9C|R9w*} zuS5+sTX6du0l&2L%}nICTQjZ%8%DDRAN7u42@gV^e@4)0Z(|*2A2f|mi}GGL61-CJsHR-^!|C=y@lVh~qmQTewtRQk zPF~?9v^zz7rh~35;_MzOChxivN46Hw_#CIC@99xV?fk=(e>j5(k^?WJ+u#FDBwQmP zqu3yo6{d|8hHt_nQa-~2w75Bg)cb`*x3M%tdfE)yu)?NK{lR{O~~J!hx7TZvX&;1 zSX9a6eX)`w&HF%BttHLqQ3ex2%IT}Dl2R}Xsdqntt_dCDDPE=33Gq!GEfmNAF99!i zbJbuf+;gSW&4|{GY~Kn;SuJ0W?CUeq4+Ulv2fs61X!T=-kBGbQKwx?$nNbJPVCT*L zG-TQLDisU-{1Ucytacj`l91sGue=MoUZ}T9hruM`JUybB`L|3MI^#vXt>gB(4L3tg zqo40|(<|Q(R&hHZv2Zkf8pk32u@YPLEAGK#gagyjT1#`vlYqxb(ECJ3TDZRH!bVJf z_7xHR5v$)p=Mx&YX5?Sj8F+8AAs&vILz(-7jTm35OU)qjF8AglK@P<_=a>u))IN+! z;jELKR-a&nmxEB`k8RW9EhTW!BXcCNo5=&%c0)#$=z8}Q4hjTspPY6@P~+K$rg_TG zd&UIRf$foE3AK97Ke^>q&9Qhi9*4kSKP0n6`+57b{nrG{o7N7f8o~RUMS;sjla0!y#7J_Fwd^MiR+VU^3EhP$;Jj-CH;R<97k)5>nh` zFp%xrLjQF)MY&wc#=na$`%u?Z#Dv_v6bKeUav9m?_u4|B#GX|S&P8El!zv5^4Zx*s z#ouBOWFipN3k{75^3T7x6vZKVwo_ZT$?TYHwW; z_%c8*3jl}I6kNh4a1({U4Dop3bD|$4ZJ1DnFob+Fk`z72$B6dD^X6o=J1&k}O(C&r zvGwlz8QtgyRL#18iki#yS3r6f+_252Ru5%Xk*y-1TV4}mr#&xr{?@f#BvT!+BNG?` z&mxH?+S{5&cF~KqVo2yOYf_zzac;H>xSO732#$VeXk0c-2&XFKAJN5Fi1Yr*b?}SP zIqEE)$-^G;%e{ws$?eXUBlpxq5(jU@+eOO@ad7XBeyq)v@V%am zPWOT{&OpD70?ujF^? zX1>Y|;Dg-RtC!V+0VkPJ`yHhW2VT#$hPRQ<@^tRC)wt5X`PnI{G+Cx!ZG=^c`~7T# z9-75PA)V=x!JxflZtH|INQL_!D&o%9;YyEh$l|+G{UkQ3023|6%sb2txo;{ld89Bx zIPKM}?tLNv+Oql3*QMv~0YMEejpa5OFcLw~g{>fl`p8?~zrL$)r4g*X-!T*V$^)g< zH5bE#MhH-S;v^iUgU%toH6xyZ@a858GGXvQCAwSzqTJr_0wi2z#ir|SnBwIl5cj~mv^3s)DL?1 zm|N8jM@7>i8m_#Hd>=6fw8XL0yky-`vV0v)10_tJNwa*?u4ZpXwnySS1 zWWv7|k(ubpG*?}ua*568d%yj)8y7nwxduK;F7@(jy1fa+Eydk-SIiD61=eJTWaa8sIX=`-G5_ zwJk9u0`%7>(`3e7Mps!(thf!qqrGIf4Xc9+i)A_q-Zy)0?mA=$Ao_%E9(mW+)(ZJr+4rXYh2CY@n&(b%w$D%&~r!x-Wej08SDXZ;LP9|d{GAzUkx_uC5uUYCb~P{ zjWP+ty>au|-h%(>V$n@C%+}F&K3TXG%ET@NqcoHU5~I(PR*3s8`CC z2~oy{WXCmlh(t5UFUQX5g29?v6(Vvlc!d>VlYwBBRci6Q0Quh4tYH=#4*t*N2{ehw zZGBv*Jxc|mAg>Y!e7|1oS(^RQdY;K~fdOR)S@RRvj;FYA%Mt1NDNNhFo}5joG;^k& zHq>n`(^BtYxz?kA?@0@_e80~eI@x!f;XSI z)@%RloejAd6Zd5LNxOLObSC#O&Dnru+3|5zNe4YKUV%ADvB@t>LvYW}a(Oqdq|%D! zZ>>^7RZRQ?)w|l~_lcM!h_v~^VLHF)=sVzi8}s-xW{z&Dw)I2rKYzr;18lI!UoW_9 z42J~1aJddI*})g5SxW397TDfy&eg{tI5N_t-gpp!%iaJEOb)Vy0Jz?18OvVl>v72> zgh2H{Vo`;GRKMjz)oexo$dLcsN3f&L+AsI!ebyqlJ^xWEL>aY^@cNKwCOCz0{WyIa za=_gzEF0(c{c!Wu0Kj(Oyf586LrWpVx-xQdo6~j))Ruq2hITA(WTktl_m=S}*;6P5 zCsKB|hYMb!?3)W8lsi@HjCPEjhw{I^ zYs|3^+2+eS(IWHLU=jlEy|2qC+3Z<3MhaFF}wPBgKUiGEo}PQb<1di%2Mx$j1W zd9WAGQg#2sh-=1Uh|_I-2qDS;q5Y~Iq68* zqE>LFGq%4m0?vM*4Sh=KeV^rgnMM_{KCfiBYl}x>iVov_GsPbgPCWZiDux@aAwt2f zfUn$zrjaP+PDH(kl!KXDE6wq+6B?Jo^v*fnpm}RXsCZd#i3v@3K!mWGSC)GcJp5=D z<&ZPigtu%i7z(@QFcj1I#R`FDMUUapnmmOP(ku9Y$dk#)y;vnX3oyf%EGJWv9RiikE>syiI77g8;-GGqo zaSi#_N`3r=zk3)RqETm_4I#Nj2W6ZJ=?=G=lXS(M92x2 z=ZKGlkBr)Uf2m|SoGHC7Qfi3pvWyU5P}NW`|IgHeg7!3?y3nRoNm?^0Xp}b}SD-b{ zhwnuhF))!j79S^|=|?kC_$xY7mL(+FKZN)u-8Px?L=}-Fh{1@F_y5zKXfj@k+2io~ z`2;-Z%;bh5h#aDTzJj&=E$*>SKh zzvJ9`ShRx+_*JN5b=Q8~xNcEaJb94E2uaWxTkQ#TKZ%8(Q!;;Kd#<4PQ*bgU>BYzA zral~HW1bWWs>AY9U&8{_Upp0wcakUkCJ4kSCE_SI3};BT88UZfLgK#>6q#hj+dl>^ z@EFpTvrqe-z0@RfB{v@mzM5F%irF<`W%MZj*~0_6ka(_G>lYxI{E&qU!Q^^B>6F3= ze!d9Z`X#BsB6NPPbNq)KkjWEh&;e*X`Kj z3FWARes}1OM5oK=#zX-VSw-zfgh}}!`W7xKajxOH6wxy;4mZh#r=mcH`}|7;I~APodNgB zTI)T2FO!;ZP706*53EJ3pon#sLcEI0iGKE;nlEd#_+j?_lQd>AqY`!RthHMT1ZvEE zD~1f1C`2QRZs}t8%-6F|7_e`CfWOnJ>Mh-*slRU_CK6~D=ve)(6fqH-9M}40BN;4} zQ2s=}U4{u45Xt3KAeH1XLbOOIGtiVyeXP&wFN!Wt3Tg|}2Md%fTPNxCT-b8VzGQaN zUVavP#dEQ6YpD!+`|3gW58n^+B)-?>ShBudFSKmFR47S|wWGV9-?=?xF8Q_(lf7?? z7&PQlF%j`CCUwt;qMl{rr2lu@Puund=X(-D4s*l(K!Om0f$ux$5CgK*^jhQz=DRk6*N@f5Vf zR&nykc(KO}-=hy;txFm_kT$A%_4qg3yK_aJI$IM$Xw*;`|7WxKLN!auXZ^f%EEoYH zn;P*X3!Eu;`rL=xNwpg+DHomb-Hqxe-~p$Q(tG*ZY$X)>;1%U3uY%N}_2n0^z^*Z| z3f5%v(-+4v7jpNpfktNTV`@b#+eC~t7i7e@CTV#cIlg;1b-u~PcV_b#Wv6RPTf6&r zGL|_zbQXY@`^?!MQ^rLuzR%bAOfJlW<=WD`$(JIQ+nqy}B|CJsD`K&f3#USYWK&Z- z;TLM${z?h~ffL46i`%p&j!))FZyg@|4GjHv$mC#Yj!{-7v9w3(mQ!WMHu}yI2UNoN zR3T|fcO%5?8B9szg&^r0StO?A-vr2g*j`yH51Ktd@bkAz_G{dO@G8HIT!>{;A|t7& z)*_lUUZ5a~M2KVe3@PEw$tu4?$Yj1`uFc&UP#4uZ^%cPmQ@~q@d>TwkS~*fZW}cwC zg0jvQ+rw<>`^Dyp_t~_Z{0fs3scKCKAA)s5RmkP*DBy*{!!&T$1o15jX`eR@2_3h` zkQ{8Z#8>~XEq?2ij{&vs+C(1_%F16;74cfqso((^Jvlo`k_@U`GE+Amv88HMmfm&z z>uV>RZK%LwfHmOpr;p#W_&~|UpYTRIm^0NQs0LS1UEi(6K-kcx({YCb=Q@u4h0Fia zoI_6FFC&(v=;I#+>={V)IW+J&DPMUi$#M~Mp_DBhRMpk(d_K;d7&&8d{v9Ph_$%Sj z-QhvU8VZpaDTXOs#$B+RmCVA?&13%Z|7cg(Wbj{D&#Z7oYcPm-Gt{k9V!maW){ju~ zRp8@01t1BF$HmrdMmb9?LB+i8AG*tw&P1kvPxg78ccOqnR+ia;14n3`*#1;mG~PDh zVZi0?b5rR?6POB(*#1{f&y`tek3bFIJ6yt;FGJm8rrR zjW<4>D3ySM#He$H2y>9VcVh(RSiE4+^mPkqQ{Q-(eLebQd;_u;IL52-0U{*t|-Mfr}M7K;6#x*m3+ zj*{X6AuG=0x9|vTN<+LJ1$b~&UM@lp`xu?H6xvIv{jTtR_Nz^jFU$M&EzXS*<$}1J znP=Tu-z2j38K{C(E!QYC)hySlhB67F0siujKZZ0l!mTVtW8x4nA$(XQsK%;FEt`V# z@CE6s1dGxU^YOn!lEf%M!mlc27&W0nl;xjzHd-|grAGAdx8JoHmXXW#e}`r1PQSr8 z7BLT!*6<$%QKwP#BaUg5qE#3U%>Cj#Cml=(9Yb8tm%V(Z+Z|5hAFMZ0l(}A3*U$^vRYJsl`v#W`*Letm>e4wcF=Of*iZHmVY9IF`L^6-%y81==7KWch~H|WoBQdV z0UVdLL%`AScU8PXjg-!8kqZj+){w4!Kb-%g@%13on^p{T@Qu9Q!{H$@EL*Oes7eB; zSW0tiTQ-Ma_wO;(*BCfnsfWtyN&37mnQN0t?A=fB`mGSn6Ovc=MXQ$LwOrUbj#1n@ zw%zdmy#UN?+55OB)}HV8QQt>*|zH$|%V81Q1UZ8Yt zTn!b~XP3qwobx_xGtRzlb&2=bF6Cd~M}JshkR$zUD$9f{B->+%o;3DH&&9OjyH*g| zvXb<~Xlg6|ku<{ww*Y_Yr(Tqvz0L7niACEZ53Iy)w8(n&RM?2`Y>ED19Ws}`657feu{nVD&BYp-zoK32v;K82aj1X z=$$c9ilpbJQQ?Ah;`B*PNx5?8Y@8a*9{=?ldw^0!CGD8dhV=Rl2 zJ0;rwT~>RBUFzt0V87BtT?x;CyyzRfvifAj&g*aklVDFavZ%I!vh=GXa_G~HJQ~>5 z_8_zB(i{($lHyy%3mvDWCl#~M{vXmCnFchG7g9;*ilq{gayezU7YqyWp5AARxmSnF zlBKV>D+L=CYQ9ndm!I$uIqi@0MqNJID=Ksxm%F6+4V`RV_Op!a$I7j0vpoz6a`)Y* ziFOWY_8n1}RGCi*G#yHA=h0{iXsFZcAH}hRPeh3=Wv!JI)~q#g$JfaoABnO&9R7Kq z9t06`VCMHJwL~d-lk5rX=M%N`hS;UMaZXKCg3#;rCP9)OTYSEfHScnvp*c*KJ z)-;p+>C^Ef8>y?%d40x`LpdTQN~};XyQlEeq;}1qWrBMxaOC)|Y7!M6ta2zBz=?3f z>uw~qJAKzutybIG)tZz}hVH~aQ(PapjdAfS@bf|~;AnQ&0$i|dC|$r!c%^arq@hW< zKykT0_u(Q5)aGVbc3+@FnkMM5j?U=M^io*&TAG=svGGDV*^-`QP;|1QlXBLIG9@g> zZLaUD(<5Sn)j_e5GS8WpVbveUu=?u%YB9YWcrWS>>}YhCLtu#pS#^>h^n7a-;29G)b*%nMCTiKn zgWVcbDNih7YZiWGg9*-HQ$gt)Nz6yW*XUs14x;Vy+pU}>HnlLuJg;wh+lsnP$IcuR zQv{yFEC^DS5aawavpWmFyimicX{K(EX0M5Remw)DRfvwW8y9(c_f+clrL6ZbNmM^< zsMG`O>XJTD+NZH7B&*FAICos1s69F{;f9(AskF3WeQ^Ew5o^$`>|MW9%iw`Ti3=FZco&DZbte1>ZVMJsf+g$d<@cd~Da z_3Sg&F3nl%bcEEB5e9nl^@DQ}jGrcZbE0pJ*Ao1$L*~hhC;R3&KxDQUdg3D`Zb^e& zc2$2%JM~UwEB^%nV2#lsE`L~|y9n^x(z4*Yqj_|#POmPV<@a9FT0F!mq48L;|2emt zCpE@KUbFR=K6Gw9FJLZhS)}$=NtWk}<2-VI`yEM*3skeu>=kLEAD?C@ zwO+eNNobl-g0uZ^{j3-m@b=+hY-6PkEhy5BGH|(`ce!4;<|#$J%1E8g2yfe3yqPcV zaL~sfC5r@gmU{nA`K@^S(_M->T!KN$em1F=W%=(^m91jTC*BVq8GtE2kI88k+@>qI zbFXFJ{34+3>R@Gg#G~H@f`=N6plDQW>n@6ZCsso^FMtr8yLO&TGrm=9Wq61lVcx{O z_i|mCt-`00&dQ7U9na93%vk1#x%z@F|8QsaI0=5F@Gmf9`M4qAF$nIBK9pU@Hc`o~2# zZ_uM;iSRY8vrU4WxQ$u+B1{uLdfe@_Q?p9&V6zfhe`?zGj*UKh-gb0l`4N2YjM#(` z76;?XDjbr^;sBnXea|457JZbi$~go)>5*eq{o>zSzg*AYWMM*A$F-Xj{7o2ks>v%| zFWY4}e>`~aZkK-e`)~`^uA&LPA8aNki*#?+zvzi=-X2SD;GGphH}|)HXQlf@wTDl9 z3sbA83V*L*wu4b4vYgyN+NJ7s+hhtTkqd4zwl_JZ`vS=ong(x2m6{lf2H@VRHVLj>)+VV)|HH{{Syc_B z5-XFSV!93oaU7XfowZ2>!B%`Z8GxI!rF#6?v|GnZHdT5kchH=u>r$(a)zp&u`oxk! zs-H2;KaJp(l;}6@F3TuK*tI4D-VgsNN3UpuV}+qQ^QD&A#dEnE8vM5jz})CgP35&~Sjf@fwuF67^Pj zkHIc;%=5E6z6L}gKZdaSOZVENu31#iV;4zEAyrzkd#z^Sa-y*d9#lBfE<;GMG4V1l z8yYXr{JdJ#O(UNIW=ToXQxT}2*bHe10{!550 zHi8w;9lq^lex4letuUMOggfAB>iSdqyEv|_!DtZX_n)}d(%O%mwqTBOnNNaMuul%; zAG5y`DCSA9IJDLhVZ8q3z;@-&h}CK_g%vQ2^=Da^mar^9}u9bEMI-2(s=7BT|;eaJo}3LncY}ne zrxcP)L1%9({kGQP>H@T&QE}JVpNd>P5zAHP3&A|#pP{DZT@g}qgE$SDnFtf|bn)?x zUn=3CHT1^TIkS()da;BVjL#N!ml@ZYSV7*EK8|#8wOzM+DM`q_y2o*f1_p9>@pjo? zt=REe4N0!ZFneS;A$e6J*~f&cMEJDci;*Z{Q$9Mf5!jM6##I@9&VyeJ-I;j_U4@$m ztJd+8`;;C}I?*ZSoU#VNwB{z}mrjsBB`(b(J^#}hWn8Zmv{#&q-B;+t{OoB$&u*Aq zT5YxOBIh5Q#GS=p7_EnM$OB!7wz9t~NXO_1?BT0i!MNA9JvtYx02>!C8mYK{$w{kx7D^AzC2d0%i%f zX^K;7FdibYT*LR#2;c#m!gekN(U9{8BG|2ZS0f|mruE1g%O?-IgDiyB0fs-EJk*rc z)Rf?2lG9`j{1zI9i6KIL3bb{NzrH zmek7&(PZIlB<&u2?M>iMwtBRjqOo4gyztekVNR;AzlrV*HYev2%IGaWLU6IPQBis1{j+QllF+-7Aub^H+kCsvl%9%BJ$UE+0tQR&VMtEc~k+&KC{jB)9 z9u2UC+pJ=zRJ)~r(^4l}ycjs-hm6)e5iq__z%Bl=ZD;PsD;OC68HD>4V#1r&gs9nW z#dgbjwRST1wHH+3DlmZ+iXu^>D79Vhx#me@1i$)Xs+4WbO)c%mm+_M=#y1PU##KeR zUzCI#>^WMEm}=Rz%M}k5eUT#>to~$_rOr1Jf&87Qds(x5*~gt@s`~S0{aH?2*ciTi z5^GV)8XQ!mW`C6TlI&h`{Cc;PGo~ciIp} z>S@~RE?=c8r(Y(lb*m6?&9Y*N{KX3MchM)poN$KKC<^t+zxdY(UW^^e7;HO?~hcKZMOz_R|{q;nY|FmadCxkJ8TWnoOvqho`zdg$= zyv6RvXBNO9e__HVI)}3c%F}pY2k#A|aEk&R3S8kbJI4p`6lw$&?3Em$pC$D{Qw_ep zR1?k0<2HFTD$lHIKkF%52ULQMggptnhutKu@8$YdqradxMA!Vnyc|6j=3Urz6z zsbY}mt~`F+w#ulZvN`&61JOs6W8M*Js{sUI|W6}jdP zjRd3@&a7x43)T1Dn!iy%am<0AdwT^lx^cJbGA|RgS1L-oNue4|RNfx$?GH#d)$O(t z_lRW0;S0!tjW2bZ(JS>8m2ZK{nWv?>#fDQ*e{7rPV!NfL$l1*_4uXH;yq(v&N@|-GN>v_*FlD1&f z@k^H1qAlkUM}q>XZ_#xFXI0u$V~=Dvxj$5Tga`a4@EaAJrj(Ae>4wa`6Ml6TcyiWR z0>Kc`Y-+9dP0BY_mC%$b&Kex_*>Bb?MRptp$EWwC^DAtHOM4z|3fX{g4_7fS{|p!~ zRT)x8NkkiS+*`{n!=28~+t*ns7j zJ`bYqc2UOrXx800-jRWEVPQfxd%01<>TlqS2K!-)=@ypx2BL5+iCbIM^kV!>= zB~l{qtAbHJ*It_EpIDvG60t7a+?|*et)*ny+Ft)tDb;fDGIH49{7}ydug1z9F5sPG;JNCGi=nQ~@OyERxSxQXbgovM>zOSMbwR{H3#A zOpkz}-C@XwXw>C=+dGL6=kkbI7~+uxVF=Gki#YXG#j~#*M`y@v*m4DVDV3?w@Ov0S zZoDdGY!+?A@RDVWU{j;*UF3h~O|i)(3Ydfav}B_2fI~e<+DEla(SX%!EG1#&IgoLT zZffQ?RZ33>&evaHdJ-StAl(+sj5LX}cwm?uP;;~JC4<_YNgTB|Q&r#YPEMmGFZX{m z_*jUOBUFeDonn;bdfWUs?ToQO+c`=86pKrXDF1b*Pc{W|ArdCP&;J5?6!|?f@foU6 z2WpZp_!4^oh|*>j6MWYIDc;55Y~rO}K#P-nzSwAk)tttU)vS}H-CuqPr2LKUsm3^& z?@1e@pgvQau|a=1`TU}$%6b~(l7qW`da7ej-OLlfQEpixPgw%qF0!2<|5W;39Zp^W zHRNYi1eM-j5S-x-TN*EYeKxFMLw{xax}v^y-;-SgbY0-LBsh z<1v<2*yJIKJ2~ka97tteME%DA)_6A}?5Le^^@LEvoe1TbcAg5gtuHKplL-;~@JZb# z8=i*S-cTHx6f?xhEoX_^`~p!t?2ZQTYHen}KWuFy#YSU51x&VCjT!%s8xA2vQyrUwGWxVCfrMuPRB*{Yr8Wq4 z%EVC!s;d3t?Bn_K!ViWI;Fe+;-mm{HwlXAxI0xxuky0cSBr`ulM-56ARs ze*I1k&dQn&Em3v%r>tEXytgf}yiiv?`)-3eXtrM*eYQDd0187r^D$oUwnHZ*`6W&u zY;cU%<#6sXH0#`5S0r>)Z`${nPL#rg45*n$iB&42T-A&dZ{vAr+xFf)?OSt)69g$S zREnMQJ9wz@v|f^6@B1OS(s;(VYtnLjMz~o?1YW>aR(T*kxeN)+J8;%4it4w+=M>0r zz(q)pVHjWSroaouTLV4-do7V3Z#gs^)@ly2lOxHYeiS9P*d@JP89U<=P}TNbWXiT& zEz9aN3j*Y{@)D>PAfoOZ{=Hb{lAhQrdOGP;v-?WrkYzGaM2TiAF+9qE9|y;+^o)0o z^__qV8ynk8dm*4o7Oi>eL1QN_wb7Fra^2-emD0C#yB!a$`u>5$84pKu9^Pdf{RTt( zgIGn)65ON=(&=-ltG%eiWUy;wCCC_c;E=TL;KO#oEH-+)qmWenz5cjk&JE~t`X>jI?P2J66G&@byYb!@?VsoP-5 zO4ojC8`;d3Cfi;Ef#2rK1b3h;V({)kVZ?&qAXQDKXx{;Y+gM`ri_|!GZ-f9zoj@Sb z!s3fSSWVuvn*Uogu0^g9c=+)Zecm;cuX03-I^RLk&-UrZsuF}W~q zA>Vs5oaZAI&6}u7V<_pMQ^n z8mOSm=?ci-k2m~zu;R#i+O0hs;;#-7gnm*Nf*V7VuWub}`M)jrOe*)CgKcYgWxq=v z)%te(Z{sf7roQ=8p*IkU+K*}~GLE`2hKR7dQZJaFEUfx^YwT{$qNWs2$z*Be{YjA^ ztw9A@dN^+DT`4??sy_$D5@S`l@p*-u9UmH>3Z{_~m zBm9OG=F)-+nzO~RsrKQ713i@TEoZep>_un!vfMaM(rDir+*-l3fs}`uKxwyU*>HakpZ<-@II-}Nc|8|H)C7cK@)T`!Tyg%D6$;24x=YnFH5V@LMeDf!e}i!XlBM_-eGz0i;sB4>{0mQEd(7O4IjVVwmF& zllJP(h&FmAOSn7ZjlArILjCg8SxWe?D^78Rg&zSKiU0w%mf9qq#Z(Ky(X66$!10QE zyMTOO74MdnN3tIFNd4a%#|}4hta=HR)?;tbxrbsSz&D)Bl{bqf*7ZqvCv{zrzn%P3 zk*{4*NdHKmIk)_{?nEix08dvrr~4D$UPtVE>gWw}p%sZNzjh6HAe^>uSz%aY@>TYt z@*tnuEVBtD+Cie}jSN#ISN$!68XsW%Lt@pWKWrW5T6=@6}Em;bm*N&t2SZcQq8F??GEqABrsZ z4AUbh=pD9bKQ8D^vL+(YdMk_%Gf!kL+59p)1ssxp9j;<>s6|`TBTeN)g!rL}l)m*y z!rE>zmOzc*jw3=-u7;*N`&qhajpK9IE{?>AzTG!kCR|SQf82W_tt>S!@hf9#*5|2YUVK@Peep9XD0iOA=9BzD9c4+N=II9*KH|w5|a`f~P7yqp+)Gpn0 z3{iaq9Cjtj&@A3v+2%9tWzR2Ab=8~~ZliwZMPLOB1ICtiWD5u|d1>a{oc2$5Sr88^ z)e!ZsY4v?mH@{!P3yfbFR$AHVpCc9xP8eT&xg|k~NO2`xtVN?pY&@y-+Vuvn+9;U9 zKzJa{5w}X$HJf;xHP|7yp0oy&$4>?{k3${^n8GcaI~S93-PGu^5JXF3a3B#z!(qf& zFg|n*8GFNZXs9PEu+~6)X@K&pYfYBH^%T2X&*ajCyFO=)sOjsE_HOaV8zqq1^^<8{ z86w=10-i_wXL&k(pi^M%^7aMDc)~@Fwz)L2Mc8drkKBM7ilV2PBL+(cG z5^rOv`Vei;6&|M#_+ir>SdF#6^ zm(n!1yg0kfflQb0eV)r)SJU;Cm(9NsUlud|-aa0*qA5g2+-vxITQ7N5RzkJCbSkE! z-6wY4;#+)v%1$>&VsbyW2z;k;EcDS#T#OSXK!B*hu3OElqOvduLb9&(0jFjL^crT) zC<`L_xNzI=6*{;+s-rE0G(7uJ44GUD7b`m%?xS$-VT)bG=IFcac#kt-8WbekYGfTGC5H=zw8*0JyTcY5Z8iKvUbjfw~$Qn)M)0S$s=-0*kEK!pT8=^9% zDx8&iTaswOWbV@L^1d%3`CIG6lR`4v5<#P?2{ntmouV%-SDDO>8OHTaFdKqs%Zd%P zWzIx+(UpZ{vuM+4-=dZ*VN8<`hdzRrDHm~h;L?4DWhtH&h>a0B;g$WAF;=GbI6!)* zvF6yvu_~hw?=^C|KQLWuh?pUt3#GJFDo6Wr>4(U=g+;iJ7tg!5@5JDZ)o+%mbX8G$ zoay-7*!KWMIJIBP%QOx(Auzs?J<0T|*6YS(B`Cz1+`JV*?=yz)5{Sc7_Lhzunc(Ft zZ#H4UBma@)HwN(;Mgr*qg~PgnM-Q>%91c$hd>eb2LI%7ad&%YKL=T|9b{v(ok@7AV z>P&lyOhaFhS)~GOfg&@d??IoztX@DhfGW2%-Z_7ZtzOEY4roOjysA*wgE++@Cq~mM zwe3;`&w(xrgKZXcNaR{Rff`ygdt~yIE3WV8uru1g1BRyXB#! zAN|e-=X1T8uK(e51ViF&*Td;|INsW+Xb#h|Ho{Xq0@saT3dG)U6A)+~>teA_13|e+ zx19o}D3|_+dGmx(K9IxQXs1+X6VQba)@=16=C32JpqG6l!ousHD^(#xgl4YpA761j z1C^53oWrH@?E}PH)xX^nZk|yxDTv~;nP%5ltyM4v`m2MQ;jC!@fXrag`Xh-0Q3r!r z1iFeyG5ip5hRYbU!%|7KnQ^u)#v)!36#BbI4FXl-gqK5Z095pX$12l-8YWF+wxw}i zN`uNLQmH(mu?WvgbqSgRD3@Vi73&PBi|5PB@hD?-#hbI%qWWz^DiHgmB=Is&W7Wzs z=KZU8KUs^Vqm3G&O;XwFj`w9YFV#7{d*l}qXjkOsejV{Fbt9Gyrn?ky9BT)jJie}= zOQFD#APRSVU^#16M6$Mw#DN7zP{EvCF%m;0E@B^JD9kut0EJQB-#yw7XCTU5DRUQp z{6)QfGQ{m1zt5+sbGv%N(GOKEJdPheBE$(`UhEY|50BeND?(rdISO95 z68`>S>rFP`e==Ud{3glloE~)e(Mk%o-umSgDe?HbO z8a$h8Dv(7Tm*Cbjb+xll|L2YNzb!RtI@6KVq-X5$q(Aw2F$3!2w zuEEZW;z!|L9ifaUnEPQ?hK4;iy(N1u-EYeW{l+lg%28e3ReWxB=A6KMwo|rrA8w%9 z=yymB;EPYI0By%aXS1n73V2`ZP_k@z`1u0{gw$`L*PErCOn6Q9E4OV>rySVA=N)Wr zQ>&K%J|@Nq_)d@0PWbH=bu>%B!;M$^+~jls8Rp~1d0*V`>NFB^z^i4=S7_t}8bL$} zKDM0LCJXZX9d?8$gc-_#(sweazN6Pe$b9}TO?V}DAE?d+{ z#btxVLmauZ@YqM~Okp-Ag);PX=K=;{YH8EQL z(hwo~HP8Kp<#I*<>0JTCr9R z9LC<*0sUwNei3x>o3LFKg`{~%-Z~kw8<tR^hUv5gDt^FTNS{ zl*$h?puu`isBWx%_Gruh$b9PYvOYqbe5*&Gz5q6%rc@v{`2yzN9!+d)XSSy}*k{SI z=`R9MG{aHmY%`MuHA>%W(z;SUnlXa1_!+Ck65g?=%OEn5XDe+&JFHPYUm_>#r0xoa z5mBhGRSDqxaS`|zOW##|)cug-+9mzmm`5)?=hcRd+Z~zy6?NoLwPa$y`!Ramq}Y!y zjuvCYWgY<5kIE}>9#xyq;ey0Ld9eIKUJmqrpXTODwbl-(Srpy@9}t2#i@qx4 zVg_|tLcUeyq_WP1WQs(Lcrwvy@ui)+t?Wq;7hGEJpoRU5(?b;90-5NKq=RUO#!Pb_ zP&Nkfn`>%n<*-T0&2awTj}4zGR`SNh2%YRAB%_OML)`>m^_)XY~W{PQ1kjGf!ht)p|Yjm)vEfpGsJwHBLr zmWLzBU<=XQHZtjkZ2BQxk3Z!ApDd{kdNDIXEywl2PautR zh-LivO1&_+mZz&l0qq)47^^To6>d0t3~A%y>7vv#1|1Tf^Vzf<$42xOC{+{efT~YaN-o~)PCb*hy1R?f8y6Df=Ra5 zg3oRdHynzU{`6DDm;&Tr6`%e!vnRC73uJgEk36*g`J~U!5m zFcJn^;J-tl_HrwN?v?8I>wIOymHH zUOB#fx^J^V1roB}Fn+^LdIn9bb0oujW-TB&jR{f>Y4QXc^y;FGOyi_E0zPlY#IPcL zd`=hBCF+c#=!x~6)?yQPG)=v=O`qHf;uI9hzwZO7k%d1&E9K8WY<)hjsB2sh z3if}F5Bi31yND_{kweuyDM@gSMP&3sYl6|GX;q&vq9JTo=uD(>9my{S9Eqjh_w$~a zSr<#HBaD!nCgr%0i4n=5PgQ--+%dNg!)FGOdURx zhze>wiwhT$<@ET=5F(l!<71(92liC?zTWNAS}ws$UMdr!TcYBp8v&N{+~AnR8n$e9 z+7{Q0^s>$G7PJC>6d8BQ0wq44byYJfHv_a6%`HGxQ{K{5r~hq$7aaqsT#2UK*VQy^9CJOdlV$urq~ zA`WY84f^IY;N$Uo3&<|Ucmx#VEY|`qHlqBUyAua0gwSMe9JiQt9ktWu;hoO+ z4EFlix}*GB*u~9duoM7dkltzc^alS#lUXlwD{gvj!8G{XhbwbdS4*xI2m!m17sn6!WZ)G!NPb^5a>yOA@%zVm%#a(iu8Hz1-f`PwTAzvM8P#X zZ%_ztf(sOgSKkF0)%)%y3@p(ZLKx^KZ}-$W;-H}pa-ssQ8ybJZ7eK!KJsQT`;`Rue5h`(ruL8rxg( z4hu6Myh}GokpgD%`kd=byTXFhz^sAXn$TXTQl~HT0#b=&UMU=*)LG1 zJ$(qX+n%mvWZ+!i_rvqLutx{y$6cR)D;Y^lzW#rMN*p-qb9ovIX(~SCmHC?=C>+`e zgj9_L{7xJWJO2HJtY*ClZ}yG~Uv9z=-C6%RmX<6LR%ek2li_T2ZE8wjzTYbQDw=X% z-2Kh!9eW49^;Gf<+krj&N(5a&DqG8I!1$Wo0B~PJMwOak&UNfluKl z4vA)_QAkkD$&N*lz)#``a&CQle)y&|vg`}1CNwfAVp~$AZi&cwm=CTO^1&4+#kQ;~ zkUY|IW%Y6a0csJE1#Yf@hMC=z0ds|V&hSy}Bu}^-7Y@z`w*o=<^`s!H0JCzzImTU6 zx57x*vz(CTQtD(rAoo!ov$kc7FH!iLkh+V4luW+A?(21CE&gQ;(U>?~Tw%hY>Y8PJ zCA(_=z+{RH+shyd)QR?g2eNX%U4(JWHy@ybr-8d*eF(?})Yd%gDxMp2^>`<}-jg)A zE}EtD481awY;igmEcMhUz_8;V2~wCGP4Aa{I$J)*54#7O+VBOcGJJBm3>GK~7RGRv z@nHCUDB%l#I+h3hl!$J_6+4(B{^yT(4^kW}P;lm3^kA!WZ#UO=a>WXcvJgz`(3VUJ zUJ)PHXGa;9ipkpiXRu&a6&{3gpV$fWnnDD*Ly_2InMgN9abYap9_^g)n6(7N`j>H1 zQ3Iy?qndH!6&CL?0GMdXHCM6*W3=%sKYVhcG$Flw?Ifs+j?5&DpNGQTKyO^8-07@J zbR>nDRR&g>dF3-opK@qNiqOWxaKj1kC)B+X9*Q59O>d=h1M24mNK63%I$u+`w-F81U%e1;E>8yED3 z@b&w_-nxM>wOU(6q8RCIp}4*?c%hpu0Sm;WK`p>5b+E@_F3WiNt@#MGnuJBnc)vmE z%1#=F2V_%Fs!)1Te!+H;#)i{QA6 z&R#X79&Y;k@H^yd@S|F$((hA0WBu=w=ZIsl$|#0*faqU`WNG}A**CLT>2;g2pW;MT zkUp@(#4VA(cb?uM$ULFPFN7hfhWjX= zRi?dc;&rsB;|@@z>nN^{6%y`0P;6#8-6Exx1u?!}xmRe}lJzWHA?BSj(70)MN7s?Y z+lHj|Of6YHfv0-%hfk|~r)2xI`zjQEWLcxX-=-CH5^TX3L)IgirLI}3t0?YtKWmm5w5IDxvT$6~X zO0sbJ1N|(F{Up{w5`fn7i6!=!(oYkz-LT*P8c-n;=mvfC^Qs`mf5HA`wmNa30_S$j zt9Y_9zZ@2Yf_Iei;*+Cn>11T!$zCq0z0ma$ZFM`9*9Hrx6V*i6;?=}?+KbzPbvj-H z?MppT7i^tpxLF_g6jN5lC=)%=(pmj7>fgrF$la{DA=}y&JP)A_73xx_=1v4MM~67} zGDGRT;F4Wly=zun4*1y@uRbRI!Tbvo|0{)1mXu@=aY5fMA!RNEO{*5iRL;8o+s4c* zx)Xr?bZ7{VKdIkDlF5G9gSaGV#qWuL<9l<(vFhRLCH&N7mkJ}K2s}86Y%baDDt~6y z^5{>}%kI#!t;Ik4$pN4h4GG)vtBQyA(tT7)cF}k~QIbd8_96v4sfK;IGoCv?h$pJ7 zq`?C43rq+-z7Xq%lq6-eQT;ybGzc_7x{~*@QP53>ts~SH-Dt-SqKSy|WtHb^O`*(Ph;~5EH5Deq_TO zx?blKzMe!D_| zWB>Y+jnN~=^{g~#)D3!Dt_H~ayOE}D-s{WNxiPBugu)jBm!iCu+2ki)Qwi>HU{9Pz zIKp9yd*n~_9HpOi1R|Qjh}oI4XH=>Sf8_}^958@ffS7); z6VPi-4YW}`B?7QujA-~`g{gqnkGnW>*{=)&?L?X*RIr^;N)T}*+zR-?v()<*Lh>7m zoBle0|M-20VI=LHQ`UR<&IH$=CEo37zn9A(2OIlrT8>6$ILDX%{-G01K+$*2SUX-- z+2Q8Fb|es(e3<+(qSq*p?=2^Dk<`WU%9EB4sLe3SoEdk_&+Bf*bskc_t1DWr;gI~| znkYGKq8#eUE+(ONtL4Y!@Ks>gukjc}f1Xe9FzGAo6iCz^im@SSg8Pt-!TQc4e1RY= zDVxjq$YiDW4VKm6g=KMh?XYv))`Gm4C$(t)uhEmr{|x3teyioWXcA>!B2&l2Q2DCN z%WxU}yA*adTd7hTnD4Om*R%8E+XXMkEk~+xM%U6?EFxitesm}#B zWv|g>wq88@-s$ul{#ztsq-ehzFu5h5q%IbVR%W{ z>S^+gRptdsPp^X1q*Ng5FsMJQ8&RH&gDdRp|8+$Dn2kAvteQYh`R%Wi*{4-p%V#kx z7uco@2loxbgz8X*~ZaiDh@9c;Cjnik_p7w`X6Zr2PSKCBA z3p&8rMy9bH$KhV$#Ec(h+qREx`c+VY)_U0kDHa|EwQy|RfJ(|#fz^zpA3*Tx1F1gl z-wx@fms#Ng;+%TfZ!Q};`MVchs|fyh(~>>jz@rLKI@J!pse6Cl>>ja^N)`allqDxN z^XWZKt7IYoBhBuR{tPlRH_wT_G;EDBJ7LZwYJJh{maa2W71AnozNvjtv4tP-pZx3+ zOfXi>1@ifEOI`ybj^&e8rkuV?BFyuSYMWc8Ug1tbZl{WAlcFmLHXj;yC&wGBPU@#V z{9Oze6gY-??i~dGWia+VAcvT~!@S3+dSqz4RYPXnd22t`QXtRAM@lb#NrEZ1r=mP9 zMPtb;7BP+Ii>l@!LJhKXn)dH*IhL!nE;v!>bw<@`-D-ydJHjyo2g&9K`2^GO3aX&x5Zhiv1sW-Nztmm zPa8xGn3tzs{cQG5@R{;ptrZBI*_Mc-wSg8CBez$=+Z9sCXdgOvD>m&J`%GtW;|r|3 zZ`BagtG{M5U7qv6UoLs@H8qy|E{jUN*V*0$Agbkc80p^da#{enD-??iWyra>Y=-Y+ zd43BBps2g>mW-!^N)C=ctAVdCV0Rg6233M-StwGqsPO_#1O}Brpq!9u*xffIjsAf1 zgR+dq8slQgR`N?tLWh`Ez?RVeXgLmm1b$RmJR-~H-;V*R9UDDI$xv^$R_5d`)4EC6 zmVQcg`emooQR(7YE2hsIJ%MY<82wHdyvTNG*;Ydk^l?5`>j{35#86&bFxs7go01FrI4>RQ!A=!GB{$*zxNBw4=4x=oy4SY=rG=aUT$ zhTJTam&E_AT=MC|OBmu)>YJJVtcVM&64EH({>GhB>Vbv&jwKpe(DE7uzRn-|>FsQ> z|IIeNNC7DxzW7p<&xxu<>ch1M4o!k?P;5s1u8;NCKgR|@;&28T z)T>l{+wG_VV$8TGYt)HtoL;?W3~h1^gOg@iMgrc<<}@Jk(%F66 z+;_R#!iu9?qj30Fk<{TpSAhVHb|>rRnb=LX#STtojpibD4}1Dk1-NAzDlb?8<*UG- z`^b-x(Jaz=f?$cAhJ8AugN{lgHYyE27*Z&-D$Valf93r^4{CofDXbM`&bEh^T->VX z9ai+&;bx3z8)I$a^ z1CZ-d9c~T))lOtgq(G>ih@Ei4Kp;M~$8yN01`xF_dUHljx~yI)!18et0{qe>_WAPP zH_r8E01B@fXsa?d^7S@%s^6;0$96gvg%Q)Tm|p|F;Va0XuW zo)_pa`A>IR>G@wcm><51oAoY|?~d4qa^GGKjImO@<0SX+pdit?GnR9C#xlk3I|0+% zjGD(ExSEt~_8wSpVPOn*@RB^>)qjSYeZh8$$eB^V5O3_*CI#TxSaNA;O?5cKK(2x3 zR%H*XyUzt%wlFT=W{9ut5)Ub6;N!q*I&q{Y4a9{pcB|gt2>EP%g%!du~7t!X2_qy1CPq<4u(~Tb(iA(%GxS<;!%67 z$pC062ZsS!B!X2M`(N^;7f^UI^W|Sf2E%Tfe1F7bz0c9+L}j&+kD_@Ynb{LlvGut~ z^Zh+hiCrKnr_KeH(yCv@;RG@d`L6Jq8dOyl2!agAR3z~NC^R=Hmh0h7hCwZoE6_BS z-!v@eYV={wvNTc$YPwZPM?j+M@tC(Sqb=2a)`04JjHbM@cPB$Zehomg3tJSXKcp|d zNXG8ndosY}-!zZ>vp#{K{OVY*DZHG$!(w0Whilc(rq5Q7_L}}?g?|Uia=9?C#>?qI zZV1g4Yo7m3!S!^!2+*ku+>!GiJKn{%@~`t%g2OdAAp<8nF007DD@)Gl5@cD-!lZHF za&o=}ASTz>)X+7w&eft>VWFARQuVo5VooeXx&x6LMY=P50EutmoS2mXL<#GUnCM54 zsl~N_KJA&uV$m2l`CELz$v(o3yx;=f9iVszH8afazV8-E-vWc9;@I+1-y2eRZxmK1 zxZ+oJRZ^1UwRnJx{i5Hn-(gw(F3a*35KcC-17eg8j*x-IbDBOaR&G4=NEf`Em-iK~ zI$}jFP`%6YIj0@OSO@AG@V zVoNvA$h+WG7!l%m_9;Q1z3`6VzS~j1wW00d9c_)BYVrU-{Pjdzdi@{}h!|SpL>qR4 zTOA~Ec(0bCq)m(?m+7T;LnKAnpU?hfF;m0+Lgxi=_P%caIG$b9l{3gdd}S8p4D;9E zb+5hOEFH(0cO_mApHBU$-7o@s)bdX}HX>_Aks~s&6Hnaa#I~MC zz9wXsGkB1UjwwLjDxyoH|Pa(Iqt%eV57<%VbEbqi)Y&7RUtOmn6H3>nz#ut z�R(kUl6@U8=S$o7}>W0-;%QG!Ia>1iBx4Uj{#K~%b}O$R9l`(GC-hIk+MF~QHT&x)@N z`L2xpHc8r*`+vLwlwAb5xS9@f1ye_W#)?0KvSj?ioR|7{j6w95vZXZu0@Ne3QInW{ zb2|=ju}kIm;%0wCo7q{LS5_m0`?=+6;^~w`h|d+JFfqDAlTyUPHu&?rrl-oTfD)!I za7a#)1Ge?Jgd z`j{tr+!P0PNdSlZ7XQwv`i*haCiAnO4$xol1qO;oOm*ZWyk%=P4*EQA!%`a57E)4< zTR=SjvE6i50NH)qH5@gQ-bHoGA635Z_#D@Fm@W?nJ+>a|_F8fj-S2{1CP zxfQ9tnvA=StR`a1wLlJwCGH-EEMMR3sVWi@DS7le(v3`}q;_7+tiY57U19)gyci=& zVti}+X293yV)`u~^v`x%Ar~ogY(IEWUvM5Iyaz~KmA($5*5wWl1jINd%IJP)nU^Vs z2rXTAUF5VE0NOR)Qykput*Prv%-3%#0mCbmy}kG7pDUmf1de$GZHsF9&6>dAD90(u zuat9d%E8mNHPZ*Y|FQm|IjXxl$ditz#~}hQ?(l&H5XPVQIB9~3V`lsoGwyMLU6{Y$ z>W00h_Mco0xKd*hK*q(3-LEwj`pPDned8dN4teK#|5-{y$W_r%`b8S{&jD%V1M+!+ zm#cS-Y^#X9_P08kfPop6;gfs&@KtnaxDjzsTM&CJzyIpRU;ev)MC6!q#yOq^qE%*{ zI?B7Q*cp=5#1;az6p4`1xYJeB&OJ}TXN0eB?8kr%;DXce9?xQ}vz*y$*5(h(K$D71 zy(bK8v$ys^bXIJET0V)b{n)UKd0;VC>z-|nw0ZtDNn(c2HU*W1{!?!NxuKBv|Zc%M(rrTv#huZ-k>N`?9cL)$C7jMvfSQPz`oC)DyK&QVlwhnLyC z{+IA`QusCXwWyi%B)i|-2B05~&5VHQ{MemBe-?ZFT`62;76V6{j$CAj)?L2DfrPNK zLl#rNbd?dsVYjL?uvGZ1UbXc6gb5&EY$lNdk`DTl;qq?ma(a^|Nx0jyeBXMlL@u`a z*(J=^r@rR&!T}0D?iUl=ENQ!PEAOgSC}(<-6*==q#NtT@z*ig{^1P#xWcn}j!U68c zI}m^DzwIf2+5)7g0e#0QWwo(QK&dTHC(cVZ0QACvfIW|1u)J4@|5?eq)LR+Q-;!Mg zi2r@#ZQvQ4w->5{?^2?vlLxJJLw%?HuJ!D?A{mGV}F+>6hEn5(iHb7uyvu3-&dsjvt= zg`Yj_?@!6ULyFA&0y0abmhNm*Ps7iFM*769M-r(PYq>rc6Q>U9{8j1e(;w^u|J_)I zgFplm_ZX#ZGWX3R78K?IZc)Bv-zS~Rao*aew+!MUX} z79LwapS$*PB70428AX1zmVWikcC`-3Cy$e4Ik9d{F2fT*iZeWWh2(Eeqihrc_(b$J zpwpt0>U(v%mY}t7$s-^Kd|BNaL1+dxpp>7HPyf%p3 z@e4w9>=HXSyo1aK#Y*a`34F^yeyZE#x0;Ou;DsLJ@l%Lw4EEKpv(H6f8yG?n64>fX zu!hvXcsY#K>^MWME7t%gVNKol?3eIW#RB{ii}ODe+mycEm*y(Kdnzx@L^MF_#K7N2gO`~?aI5b-CS> zd?2XskfHraD*WbNiOCBfx8OA@`MHS@PUgYcTKrFCL#jH%`)I<-*rTFbI{hZG8zcf2 z$}lr_;O1B+EkYZ%>>M`q$u)G!!B|ls*W(%Y0Wk|urs8JQBMkaA&}@-^wIqF&y)s4X z-cXK1L)f&!??A67#UIogd~+@;u=NI-`Q_|?uP6@g;VW0I1Oj9?<6Gt@Sm$>bs_vC_ zR_%LU9a+V^CAQBJ6*4jh@M$_E*Nc5GZB(pfaZ0MP#+&)kZkg9R*OyHumXjIhYJ28=)Ae~%v6{qI#X8W?UT_7d zUcE{2>h4hNje7VesZ8fp{RFD%yuOJckpgsQ<;QN2U;#E_=Lyy!`V4IFF9P5lzYNs( ze!4MMgD^k6AL}~LY6-fQu@BByWb(+V1A^P{faZj{#qsAo{bmLt5jjx@V7u0V1_YaW z0k|dj=MqKEBn{yX(Dox6hzR=#JXn|R*jI&NW{(8Zv>QYH@jO50q&61 zvtN%{G!lKUk9~{(^rsr}1JO`!TH$R16)C=-l*@Zj*C$bYVy0oW=h z*(CaZX7vKA>6@ z0L@0x{1QwzFYS1S?#c?5^#o+QxBae#&ty-opS)p7#zLdOvzwRMN`UI4UenoVaUBK3 zTK=O0P?3@ObbXqBT?^AcPOaJa_0HcuKB6cvsTp1M_}R-3555CD182AddrOxsDmlTR z-13Q8pU}q5pO|C=R1UW8chlXR2~}c9)#U5^B0>pbvDRxqE~@fQ$;!3q#Ukw}HeSjC zwUhW6_RsR0!GMtcx}sPJ+YOUwho)M?!VgSIJgs z20!NU1nFD|oOhFCJGmilG|u;Ef|^NWxbga=UM@I!i37c0ka4+wJ~RW1G~h_T143A4 z^EQlT6+o+m`#I5#whud)@`h{#(-;1AvtI8hafn~i^63v&@{(X8cINC6pOI@iDj#yU5UDdOsae5-|pYWCPcRn3>4 z@(wqhEQaf0Ge{MAZipJopFfo5^r6LEeQ~(Q{^)bL?Jc$CU;C3Pe_|AC$avVO!1cRw zCi2mB(wYhT;6HsSdRTm{BbSFNqVDgL>v%GHhS6`Bo%FxWo*MKzU;FDo3 zcWWNA&O0uude*|uH)}wN&8#Uy?f<0S+`VYl5`c%MLneK(n>6)A^o8>!@&XG6EaC^! zX+xu3ie%lWZ>uBfV!V|7h^?cNQ8jsd&NW`{>8vd6!bEc1#8}Bir!E7_WQ*>{tux(< zwfFWBdycM@+{kHvbO}(`agY6P2~gSq!ir4n1bvcdZnS-QHr^z#d=Vt*^}N>9p-*u*D2ZivjVWv9F=F$jr2kIk znzwrt@gUaqV~72YVoOWjK$#++^x<-JchO@SF?R-Z9+M@m&-M9SRM+fdDRV8+uteE* zY%2lqMyl91QgvXnc#I7!%uvvVqsrn!J|C%gd$4@%ZjF z0Z)xzjZ2&qVoTReA69wkRC>_8$*JVP+2UtQ!(;U?-cQ0tT}iVF-B@!T+6*E`M3afl zqta+@QBt;C4n_GqmE3Em9OX6H3zO;Qr&BmF7-WODDS5$8Pa@7kM0gu3@uZfBgw!8q zKx=A1T~k@+fy}3Q5J*=ZLO(*q58gT6balAyN5DjX_o)NZAe3yGK&7^nM$yP ztdbuwasTo_999%!>Tz(2dNEGdheI%c$I_=f`#a(v+3dmtI4>U^H9>_d-_ssb8q5=c z<@A;GdNN`OJ$7d!GBa<`a6e-R_<1VMN^_*b7}*<@`RAx+-to*=mUPQgb{g(NSSH{o zAaFWvhl%)?*dnk80)Eem<==e~1iOtqyuR4?G~vy#RNBdok}@=Yg^ew&o+iXgO$T`? z_Q$+|Fq|r$@lc?DxZ)T)x84TCvD}%9ka3_Q@oB#V!`I&yDV85%iZ7UfiSDC7R%U96 z|H5sazO~|ni;6a^Io#wRE9*_5%rNUjIa7!2|0(WDFepQVj?|Lm}MAda9c6=ogjW-;fDn(Tt7hAbGMf`q+9?O8!9@UH{9-MUXy9 zL`IPA9Y)zOEW-b`&iHscD+a$mp66p#`@5TvXtQ9cW>jxrPdl_f0chPq3L zquV-0;#ktSAl{You%t}*3O##UgM3^bK{W15EO{Is*h{CIWDcmex<_f0KO!424ZlHC za7b_S?*Ed6rlA0=Cj0)2fa=vW#a1)OYk<)RiU{RJ5MnP}hMLbdmtBSKY}L46M?*O3 zOqcY?EfGFft~*Tb^x~@k)POPS!|1Ws|6FHD=jP)<&MZgzUJ^{N8_YZ~QB+N~K13Bq zr!g$>{q5LfFHp1Frzw$!))XF4f?F4@Q-!ROeuq*`NH*PeVK0dTiGb$flxB@cn?6SRRnNKX(nJp7Qs-y0 zX0GJxF8Kg@L`7#u{8|55`jfs}HRwxbaBVp=iX>0&&LJr?SV#}?V!P}emJmk3dHB7O ziTC28qZKFXEVKt+IRVOaV|bm5)pH@xn;RyNv-%z6VF{~F-i4>jm_A0As?!Dc|JZTu zlUmtlkEWQ|iLJeoWbGEix^|J0Mzt4oSyF-3o9q$kr?(Cw=QTcJ*+9E$Ee6k?j_*yZ zNlSKkH2YS&?)jB`htIij^7{QZ?{(XUwwQ-w@|IpBig%`8ujRHl*>r^MMZv86;{|ds=h80F->R`+()%41k5Q(Mom9LQ#jEi zB))$zX&$FQOm+pM3GW;f5EG~t%@k07jn+6|;_9ifBYm$MD|M7tg806B(&$mZZxnbH zkChPGiWpIbO2WWpN7Epz1Br6OQ!tsMq1zjRdM;J-9>z{WM2BNqtF(Rx^2vZay$%0h z&&?-tlc*&K%4>YYr=aBJTK-%z{i(k1JC$bw!`!!3XJ@9cU#R~}-Shz^E6+th`r0C# zqS7G1w&U87dj=X!f-B(mVck2~6)YSWNj7 zx!XEl@qm!0GG|6bR_s^Ng|E74U<79m+rfvrODLmV;{n*ca^mrfIy z$unK%YA*f2+jMZ969v||-Vs#y@(9?SXD{^tvk%umoi+IdDbC|+ zC3(DgCz02ZtI;!l@_7$-g)mb{i})Hcg4fUiAPc2xVbi3x&Mckss=2p23n0eH`0!sD zUMh1-wMXx|e7@MJ=UgS;o!`944N^YHfJEB4`Y2_tG0GUZLrDxqm3YV#o{bU}y+S55 z)_mY;_b9{0>2F3R1goIS3iA)bO=`jhkb4GhzOG+yt+zE-tvvT7{ZCMXd+KxN{Qd+_I7K!PoTaXYFTa+xV_+!)sM6yI~hVZ)V;3nc5|Cnl4w#r2Yy@oL&_x@N(VH zJR08!Rp0|k?90iA2Fw!wlv^dRCqAYcj~&D19w_-d+#&$6Zun+zHE+8msU!8;#D`YsDZ76b4K8~$Tw?xUp5tb~ zScF3e)GUY&t&3Tu=YnMgAHzPwQ4PlyUDA>&hFtSWeIfMbHzw8Fuc{1|!a`rRYwdd} z2#wFYv8@DDT+^qHU;WfO>gIgmTDC0B_ob>pvmySi}*G*6jvtOHhd9oDvPJ6jWWc|Q} z=aw{CCIpp9VYWK_j<5Qa7|9KL|1m&Is~#N~4!pE7a_5d@Y#if>Wr!MQp`J0q1_|$Y zTYg)E>r9cT5=wSJ3yvf+snM!@in>@E7jvLDmFa}&_^Mhls-ZckA&2MNBlWYW^N}m2 zFUkf{u>p;{Xc|x)TAz*8r`|d=6gQsWw(dbvp#AlB$^c9@WW2r{e{=fqU7z7ZZPk`z zzh^T8zU_a9_v^?g`3#3Vh?Y%QOUUvccR71Re0zw9hl+*D$|zPsn$z)*_L*0 zc4cb}E!))}Hq-wuTSPsW-JQPM-zRD1PW}2nqc$VrGA3n(ha^A-_hLb$OXZeJFp<7A z6S=vjq2oSRT#6_S0h?F)iO}ZWNxMM<8kz#6L!ccCx}jz?zQv2gzvB3U$ZhaFM3w7TF6f5&`7tt(AcjMQ`rh8N*O1= zF?f{{`1gJJhckLFcJBd`ZAKF30W`BqR>+Uc?(ebEu01?fO3V++ zpE_WQZkhhZ_mUe{YA`>0x)mBO_|~n*QR(tu&XL!@n!bug5tVR7Ni(c6hUo@ z+Y_w=_s;93i7?u?IY{6|D?r7d)wD5jz9Wp2m!3EXL6!3tlt-W{JWx-FqU^JHg)p|q zrNb}Dv`w>guE`E=myB#SceUxKD0f`$T+9O<%!or5Vg6nNLGcVlFtYiEu-4}ssU`(|1e?FsK*Iib z6~q*KOSufK`S_Fbe*B>THMv3??KJ5r&Y!ol;|we{a#w-?m~E&t&YSy2uhZ_-{rYFz zWhT^~1&qb-rpc0$?2rn!uk>2qBv1Wj{=?8`6)5X1$t>(-VM}WMMFHmMn={@*%G&}3 z=YR}>*q^}M&YzL#KU=@tp*4uP^j6Z#7K%y*9`lZzQ=EdhfyYd5^IUFxzk-Zbp8;Zn z?x4DbtXq~-Q+DH4C=krc#HaR1{{^yWeN1^CtH-%`d1Vt2jw&xo;|W*f>p4>4;X(t5Ql7heUHY(vAy~$rjA?Pzdvtk>c6Wj zR@R3umzmhowrhPlsD9ss*rdrDm9dZ6>`Px1F7K!>qdI}7)aD17`*&e%0T-wSi=rfC z>V84wl;fw?XSdw7`&us6khIKCV%FHjC5?hjU7H{djLj|^ zF-63}kM@0+8y~83L_tz5hJ9ZskY74t0B(Yc<_=+4NAApNo28aPqOj zXh|3*JUb2MoOloJcbIV38?Bu~k43nLQ}DPPq{FTght=i$T5$Qckj$?@c7bb99}$p2 zHF>w0acfSyP}muhbwFiIj7JNpKEd3Q`b6442RSN{9|p^Pl|tQ0@KVP8?pa9f1wo*p z+eY8rzi96qWOqig7Yyb_ubj(9(8f1o_1AM1VS$1WS!BLLC?N>osq={kdlb#$Ui@CM zSpodVluj0jjL|oE3-PJ?FD6arm?1h#&9KGxg6)-ri_gC>8o3SW@u?5 z=tp~Z?_opfgv=~4$fKZBqIS&K7+&(&9a4G3hRG~(GS%hbq@;gHQ~7AWh4|OBD_>3N z^0kr(hCRrR@{kT#c3gUx-hIAJS5#qlR zG~8=pZkvEZuXF;X$`+DLNmGLuzvh-Qk%Q(mVR~5(1_`xvDxWS&Kck^e*Wg+o1}aKq zXr~11L2O2b1*P3nN5`Cbb!jV^;J-OBOPFmMNK+%_IQ&et8F`5J-syesu;$i<`;{rM zC<4M;mjpO-MPxK{;cYt&!8>7w$dMzMH%B1S{Oam6RE3TJt0;1YU3^k_n&rE6 zYi;A^47dVpG6n0t3ysB7XyzzteAwQX287nAXTpkGUR`-oy+s^$>)kL0R%KIiBQb2C z_UtRhF$xThsOLpSF%%X#hv^GZ1vUhcS(ZTYqVhyuUtFx%cf+@SbA63fa~!(K3N@MCIhX;ft39{nFjO+S7B literal 0 HcmV?d00001 diff --git a/doc/conf.py b/doc/conf.py index e7d4314c..37568fef 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -12,20 +12,22 @@ # import os import sys -import matplotlib -matplotlib.use('agg') + +import matplotlib as mpl + +mpl.use("agg") curdir = os.path.dirname(__file__) -sys.path.append(os.path.abspath(os.path.join(curdir, '..'))) -sys.path.append(os.path.abspath(os.path.join(curdir, '..', 'meegkit'))) +sys.path.append(os.path.abspath(os.path.join(curdir, ".."))) +sys.path.append(os.path.abspath(os.path.join(curdir, "..", "meegkit"))) import meegkit # noqa # -- Project information ----------------------------------------------------- -project = 'MEEGkit' -copyright = '2022, Nicolas Barascud' -author = 'Nicolas Barascud' +project = "MEEGkit" +copyright = "2023, Nicolas Barascud" +author = "Nicolas Barascud" release = meegkit.__version__ version = meegkit.__version__ @@ -35,31 +37,31 @@ # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.autodoc', - 'sphinx.ext.autosummary', - 'sphinx.ext.napoleon', - 'numpydoc', - 'jupyter_sphinx', - 'sphinx_gallery.gen_gallery', - 'sphinxemoji.sphinxemoji', + "sphinx.ext.autodoc", + "sphinx.ext.autosummary", + "sphinx.ext.napoleon", + "numpydoc", + "jupyter_sphinx", + "sphinx_gallery.gen_gallery", + "sphinxemoji.sphinxemoji", ] # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. # This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store', 'config.py'] +exclude_patterns = ["_build", "Thumbs.db", ".DS_Store", "config.py"] # generate autosummary even if no references # autosummary_generate = True autodoc_default_options = { - 'members': True, - 'special-members': '__init__', - 'undoc-members': True, - 'show-inheritance': True, - 'exclude-members': '__weakref__' + "members": True, + "special-members": "__init__", + "undoc-members": True, + "show-inheritance": True, + "exclude-members": "__weakref__" } numpydoc_show_class_members = True @@ -75,15 +77,19 @@ # -- Options for HTML output ------------------------------------------------- # The theme to use for HTML and HTML Help pages -html_theme = 'pydata_sphinx_theme' +html_theme = "pydata_sphinx_theme" # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - +html_static_path = ["_static"] html_theme_options = { + "logo": { + "image_light": "_static/logo.png", + "image_dark": "_static/logo-dark.png", + "text": "meegkit", + }, "show_toc_level": 1, "external_links": [ { @@ -95,12 +101,12 @@ { "name": "GitHub", "url": "https://github.com/nbara/python-meegkit", - "icon": "fab fa-github-square", + "icon": "fa-brands fa-github", }, { "name": "Twitter", "url": "https://twitter.com/lebababa", - "icon": "fab fa-twitter-square", + "icon": "fa-brands fa-twitter", }, ], "use_edit_page_button": True, @@ -116,10 +122,10 @@ # -- Options for Sphinx-gallery HTML ------------------------------------------ sphinx_gallery_conf = { - 'doc_module': ('meegkit',), - 'examples_dirs': '../examples', # path to your example scripts - 'gallery_dirs': 'auto_examples', # path to where to save gallery generated output - 'filename_pattern': '/example_', - 'ignore_pattern': 'config.py', - 'run_stale_examples': False, + "doc_module": ("meegkit",), + "examples_dirs": "../examples", # path to your example scripts + "gallery_dirs": "auto_examples", # path to where to save gallery generated output + "filename_pattern": "/example_", + "ignore_pattern": "config.py", + "run_stale_examples": False, } diff --git a/doc/index.rst b/doc/index.rst index 23f60816..a88c893e 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -10,7 +10,7 @@ Introduction ------------ ``meegkit`` is a collection of EEG and MEG denoising techniques for -**Python 3.6+**. Please feel free to contribute, or suggest new analyses. Keep +**Python 3.8+**. Please feel free to contribute, or suggest new analyses. Keep in mind that this is mostly development code, and as such is likely to change without any notice. Also, while most of the methods have been fairly robustly tested, bugs can (and should!) be expected. diff --git a/examples/config.py b/examples/config.py index fd1a52a2..1c374858 100644 --- a/examples/config.py +++ b/examples/config.py @@ -1,7 +1,8 @@ """Configuration file for examples.""" import matplotlib.pyplot as plt from IPython.display import set_matplotlib_formats -set_matplotlib_formats('pdf', 'png') -plt.rcParams['savefig.dpi'] = 75 -plt.rcParams['figure.autolayout'] = False -plt.rcParams['figure.figsize'] = 10, 6 + +set_matplotlib_formats("pdf", "png") +plt.rcParams["savefig.dpi"] = 75 +plt.rcParams["figure.autolayout"] = False +plt.rcParams["figure.figsize"] = 10, 6 diff --git a/examples/example_asr.py b/examples/example_asr.py index d8634d6c..9d59a562 100644 --- a/examples/example_asr.py +++ b/examples/example_asr.py @@ -7,14 +7,15 @@ Uses meegkit.ASR(). """ import os -import numpy as np + import matplotlib.pyplot as plt +import numpy as np from meegkit.asr import ASR from meegkit.utils.matrix import sliding_window # THIS_FOLDER = os.path.dirname(os.path.abspath(__file__)) -raw = np.load(os.path.join('..', 'tests', 'data', 'eeg_raw.npy')) +raw = np.load(os.path.join("..", "tests", "data", "eeg_raw.npy")) sfreq = 250 ############################################################################### @@ -22,7 +23,7 @@ # ----------------------------------------------------------------------------- # Train on a clean portion of data -asr = ASR(method='euclid') +asr = ASR(method="euclid") train_idx = np.arange(0 * sfreq, 30 * sfreq, dtype=int) _, sample_mask = asr.fit(raw[:, train_idx]) @@ -46,20 +47,20 @@ times = np.arange(raw.shape[-1]) / sfreq f, ax = plt.subplots(8, sharex=True, figsize=(8, 5)) for i in range(8): - ax[i].fill_between(train_idx / sfreq, 0, 1, color='grey', alpha=.3, + ax[i].fill_between(train_idx / sfreq, 0, 1, color="grey", alpha=.3, transform=ax[i].get_xaxis_transform(), - label='calibration window') + label="calibration window") ax[i].fill_between(train_idx / sfreq, 0, 1, where=sample_mask.flat, transform=ax[i].get_xaxis_transform(), - facecolor='none', hatch='...', edgecolor='k', - label='selected window') - ax[i].plot(times, raw[i], lw=.5, label='before ASR') - ax[i].plot(times, clean[i], label='after ASR', lw=.5) + facecolor="none", hatch="...", edgecolor="k", + label="selected window") + ax[i].plot(times, raw[i], lw=.5, label="before ASR") + ax[i].plot(times, clean[i], label="after ASR", lw=.5) ax[i].set_ylim([-50, 50]) - ax[i].set_ylabel(f'ch{i}') + ax[i].set_ylabel(f"ch{i}") ax[i].set_yticks([]) -ax[i].set_xlabel('Time (s)') -ax[0].legend(fontsize='small', bbox_to_anchor=(1.04, 1), borderaxespad=0) +ax[i].set_xlabel("Time (s)") +ax[0].legend(fontsize="small", bbox_to_anchor=(1.04, 1), borderaxespad=0) plt.subplots_adjust(hspace=0, right=0.75) -plt.suptitle('Before/after ASR') +plt.suptitle("Before/after ASR") plt.show() diff --git a/examples/example_dering.py b/examples/example_dering.py index 2a84f3ad..a5fee882 100644 --- a/examples/example_dering.py +++ b/examples/example_dering.py @@ -8,14 +8,11 @@ """ import matplotlib.pyplot as plt import numpy as np - from scipy.signal import butter, lfilter from meegkit.detrend import reduce_ringing -# import config # plotting utils - -np.random.seed(9) +rng = np.random.default_rng(9) ############################################################################### # Detrending @@ -32,11 +29,11 @@ [b, a] = butter(6, 0.2) # Butterworth filter design x = lfilter(b, a, x) * 50 # Filter data using above filter x = np.roll(x, 500) -x = x[:, None] + np.random.randn(1000, 2) +x = x[:, None] + rng.standard_normal((1000, 2)) y = reduce_ringing(x, samples=np.array([500])) plt.figure() -plt.plot(x + np.array([-10, 10]), 'C0', label='before') -plt.plot(y + np.array([-10, 10]), 'C1:', label='after') +plt.plot(x + np.array([-10, 10]), "C0", label="before") +plt.plot(y + np.array([-10, 10]), "C1:", label="after") plt.legend() plt.show() diff --git a/examples/example_detrend.py b/examples/example_detrend.py index feadb091..d1a377cb 100644 --- a/examples/example_detrend.py +++ b/examples/example_detrend.py @@ -17,11 +17,11 @@ import numpy as np from matplotlib.gridspec import GridSpec -from meegkit.detrend import regress, detrend +from meegkit.detrend import detrend, regress # import config # plotting utils -np.random.seed(9) +rng = np.random.default_rng(9) ############################################################################### # Regression @@ -31,15 +31,15 @@ # Simple regression example, no weights # ----------------------------------------------------------------------------- # We first try to fit a simple random walk process. -x = np.cumsum(np.random.randn(1000, 1), axis=0) +x = np.cumsum(rng.standard_normal((1000, 1)), axis=0) r = np.arange(1000.)[:, None] r = np.hstack([r, r ** 2, r ** 3]) b, y = regress(x, r) plt.figure(1) -plt.plot(x, label='data') -plt.plot(y, label='fit') -plt.title('No weights') +plt.plot(x, label="data") +plt.plot(y, label="fit") +plt.title("No weights") plt.legend() plt.show() @@ -49,7 +49,7 @@ # We can also use weights for each time sample. Here we explicitly restrict the # fit to the second half of the data by setting weights to zero for the first # 500 samples. -x = np.cumsum(np.random.randn(1000, 1), axis=0) + 1000 +x = np.cumsum(rng.standard_normal((1000, 1)), axis=0) + 1000 w = np.ones(y.shape[0]) w[:500] = 0 b, y = regress(x, r, w) @@ -57,27 +57,27 @@ f = plt.figure(3) gs = GridSpec(4, 1, figure=f) ax1 = f.add_subplot(gs[:3, 0]) -ax1.plot(x, label='data') -ax1.plot(y, label='fit') -ax1.set_xticklabels('') -ax1.set_title('Split-wise regression') +ax1.plot(x, label="data") +ax1.plot(y, label="fit") +ax1.set_xticklabels("") +ax1.set_title("Split-wise regression") ax1.legend() ax2 = f.add_subplot(gs[3, 0]) -l, = ax2.plot(np.arange(1000), np.zeros(1000)) -ax2.stackplot(np.arange(1000), w, labels=['weights'], color=l.get_color()) +ll, = ax2.plot(np.arange(1000), np.zeros(1000)) +ax2.stackplot(np.arange(1000), w, labels=["weights"], color=ll.get_color()) ax2.legend(loc=2) ############################################################################### # Multichannel regression # ----------------------------------------------------------------------------- -x = np.cumsum(np.random.randn(1000, 2), axis=0) +x = np.cumsum(rng.standard_normal((1000, 2)), axis=0) w = np.ones(y.shape[0]) b, y = regress(x, r, w) plt.figure(4) -plt.plot(x, label='data', color='C0') -plt.plot(y, ls=':', label='fit', color='C1') -plt.title('Channel-wise regression') +plt.plot(x, label="data", color="C0") +plt.plot(y, ls=":", label="fit", color="C1") +plt.title("Channel-wise regression") plt.legend() @@ -89,23 +89,23 @@ # Basic example with a linear trend # ----------------------------------------------------------------------------- x = np.arange(100)[:, None] -x = x + np.random.randn(*x.shape) +x = x + rng.standard_normal(x.shape) y, _, _ = detrend(x, 1) plt.figure(5) -plt.plot(x, label='original') -plt.plot(y, label='detrended') +plt.plot(x, label="original") +plt.plot(y, label="detrended") plt.legend() ############################################################################### # Detrend biased random walk with a third-order polynomial # ----------------------------------------------------------------------------- -x = np.cumsum(np.random.randn(1000, 1) + 0.1) +x = np.cumsum(rng.standard_normal((1000, 1)) + 0.1) y, _, _ = detrend(x, 3) plt.figure(6) -plt.plot(x, label='original') -plt.plot(y, label='detrended') +plt.plot(x, label="original") +plt.plot(y, label="detrended") plt.legend() ############################################################################### @@ -119,7 +119,7 @@ # glitch, leading to a mediocre fit. When downweightining this artifactual # period, the fit is much improved (green trace). x = np.linspace(0, 100, 1000)[:, None] -x = x + 3 * np.random.randn(*x.shape) +x = x + 3 * rng.standard_normal(x.shape) # introduce some strong artifact on the first 100 samples x[:100, :] = 100 @@ -133,8 +133,8 @@ z, _, _ = detrend(x, 3, w) plt.figure(7) -plt.plot(x, label='original') -plt.plot(y, label='detrended - no weights') -plt.plot(z, label='detrended - weights') +plt.plot(x, label="original") +plt.plot(y, label="detrended - no weights") +plt.plot(z, label="detrended - weights") plt.legend() plt.show() diff --git a/examples/example_dss.py b/examples/example_dss.py index bb5de9e3..eb4a3b87 100644 --- a/examples/example_dss.py +++ b/examples/example_dss.py @@ -11,9 +11,9 @@ import numpy as np from meegkit import dss -from meegkit.utils import unfold, rms, fold, tscov +from meegkit.utils import fold, rms, tscov, unfold -# import config +rng = np.random.default_rng(5) ############################################################################### # Create simulated data @@ -30,14 +30,14 @@ np.zeros((n_samples // 3,)), np.sin(2 * np.pi * np.arange(n_samples // 3) / (n_samples / 3)).T, np.zeros((n_samples // 3,))))[np.newaxis].T -s = source * np.random.randn(1, n_chans) # 300 * 30 +s = source * rng.standard_normal((1, n_chans)) # 300 * 30 s = s[:, :, np.newaxis] s = np.tile(s, (1, 1, 100)) # Noise noise = np.dot( - unfold(np.random.randn(n_samples, noise_dim, n_trials)), - np.random.randn(noise_dim, n_chans)) + unfold(rng.standard_normal((n_samples, noise_dim, n_trials))), + rng.standard_normal((noise_dim, n_chans))) noise = fold(noise, n_samples) # Mix signal and noise @@ -66,8 +66,8 @@ # Plot results # ----------------------------------------------------------------------------- f, (ax1, ax2, ax3) = plt.subplots(3, 1) -ax1.plot(source, label='source') -ax2.plot(np.mean(data, 2), label='data') -ax3.plot(best_comp, label='recovered') +ax1.plot(source, label="source") +ax2.plot(np.mean(data, 2), label="data") +ax3.plot(best_comp, label="recovered") plt.legend() plt.show() diff --git a/examples/example_dss_line.py b/examples/example_dss_line.py index cc5f6ab9..b014b0d7 100644 --- a/examples/example_dss_line.py +++ b/examples/example_dss_line.py @@ -18,9 +18,10 @@ import matplotlib.pyplot as plt import numpy as np +from scipy import signal + from meegkit import dss from meegkit.utils import create_line_data, unfold -from scipy import signal ############################################################################### # Line noise removal @@ -48,11 +49,11 @@ ax[0].semilogy(f, Pxx) f, Pxx = signal.welch(out, sfreq, nperseg=500, axis=0, return_onesided=True) ax[1].semilogy(f, Pxx) -ax[0].set_xlabel('frequency [Hz]') -ax[1].set_xlabel('frequency [Hz]') -ax[0].set_ylabel('PSD [V**2/Hz]') -ax[0].set_title('before') -ax[1].set_title('after') +ax[0].set_xlabel("frequency [Hz]") +ax[1].set_xlabel("frequency [Hz]") +ax[0].set_ylabel("PSD [V**2/Hz]") +ax[0].set_title("before") +ax[1].set_title("after") plt.show() @@ -60,7 +61,7 @@ # Remove line noise with dss_line_iter() # ----------------------------------------------------------------------------- # We first load some noisy data to work with -data = np.load(os.path.join('..', 'tests', 'data', 'dss_line_data.npy')) +data = np.load(os.path.join("..", "tests", "data", "dss_line_data.npy")) fline = 50 sfreq = 200 print(data.shape) # n_samples, n_chans, n_trials @@ -72,7 +73,7 @@ # Now try dss_line_iter(). This applies dss_line() repeatedly until the # artifact is gone out2, iterations = dss.dss_line_iter(data, fline, sfreq, nfft=400) -print(f'Removed {iterations} components') +print(f"Removed {iterations} components") ############################################################################### # Plot results with dss_line() vs. dss_line_iter() @@ -83,10 +84,10 @@ f, Pxx = signal.welch(unfold(out2), sfreq, nperseg=200, axis=0, return_onesided=True) ax[1].semilogy(f, Pxx, lw=.5) -ax[0].set_xlabel('frequency [Hz]') -ax[1].set_xlabel('frequency [Hz]') -ax[0].set_ylabel('PSD [V**2/Hz]') -ax[0].set_title('dss_line') -ax[1].set_title('dss_line_iter') +ax[0].set_xlabel("frequency [Hz]") +ax[1].set_xlabel("frequency [Hz]") +ax[0].set_ylabel("PSD [V**2/Hz]") +ax[0].set_title("dss_line") +ax[1].set_title("dss_line_iter") plt.tight_layout() plt.show() diff --git a/examples/example_mcca.py b/examples/example_mcca.py index ab5c8c76..d2f13400 100644 --- a/examples/example_mcca.py +++ b/examples/example_mcca.py @@ -12,7 +12,7 @@ from meegkit import cca -# import config +rng = np.random.default_rng(5) ############################################################################### # First example @@ -22,12 +22,12 @@ ############################################################################### # Build data -x1 = np.random.randn(10000, 10) -x2 = np.random.randn(10000, 10) -x3 = np.random.randn(10000, 10) +x1 = rng.standard_normal((10000, 10)) +x2 = rng.standard_normal((10000, 10)) +x3 = rng.standard_normal((10000, 10)) x = np.hstack((x1, x2, x3)) C = np.dot(x.T, x) -print('Aggregated data covariance shape: {}'.format(C.shape)) +print(f"Aggregated data covariance shape: {C.shape}") ############################################################################### # Apply CCA @@ -37,14 +37,14 @@ ############################################################################### # Plot results f, axes = plt.subplots(1, 3, figsize=(12, 4)) -axes[0].imshow(A, aspect='auto') -axes[0].set_title('mCCA transform matrix') -axes[1].imshow(A.T.dot(C.dot(A)), aspect='auto') -axes[1].set_title('Covariance of\ntransformed data') -axes[2].imshow(x.T.dot((x.dot(A))), aspect='auto') -axes[2].set_title('Cross-correlation between\nraw & transformed data') -axes[2].set_xlabel('transformed') -axes[2].set_ylabel('raw') +axes[0].imshow(A, aspect="auto") +axes[0].set_title("mCCA transform matrix") +axes[1].imshow(A.T.dot(C.dot(A)), aspect="auto") +axes[1].set_title("Covariance of\ntransformed data") +axes[2].imshow(x.T.dot(x.dot(A)), aspect="auto") +axes[2].set_title("Cross-correlation between\nraw & transformed data") +axes[2].set_xlabel("transformed") +axes[2].set_ylabel("raw") plt.plot(np.mean(z ** 2, axis=0)) plt.show() @@ -55,13 +55,13 @@ ############################################################################### # Build data -x1 = np.random.randn(10000, 5) -x2 = np.random.randn(10000, 5) -x3 = np.random.randn(10000, 5) -x4 = np.random.randn(10000, 5) +x1 = rng.standard_normal((10000, 5)) +x2 = rng.standard_normal((10000, 5)) +x3 = rng.standard_normal((10000, 5)) +x4 = rng.standard_normal((10000, 5)) x = np.hstack((x2, x1, x3, x1, x4, x1)) C = np.dot(x.T, x) -print('Aggregated data covariance shape: {}'.format(C.shape)) +print(f"Aggregated data covariance shape: {C.shape}") ############################################################################### # Apply mCCA @@ -70,14 +70,14 @@ ############################################################################### # Plot results f, axes = plt.subplots(1, 3, figsize=(12, 4)) -axes[0].imshow(A, aspect='auto') -axes[0].set_title('mCCA transform matrix') -axes[1].imshow(A.T.dot(C.dot(A)), aspect='auto') -axes[1].set_title('Covariance of\ntransformed data') -axes[2].imshow(x.T.dot((x.dot(A))), aspect='auto') -axes[2].set_title('Cross-correlation between\nraw & transformed data') -axes[2].set_xlabel('transformed') -axes[2].set_ylabel('raw') +axes[0].imshow(A, aspect="auto") +axes[0].set_title("mCCA transform matrix") +axes[1].imshow(A.T.dot(C.dot(A)), aspect="auto") +axes[1].set_title("Covariance of\ntransformed data") +axes[2].imshow(x.T.dot(x.dot(A)), aspect="auto") +axes[2].set_title("Cross-correlation between\nraw & transformed data") +axes[2].set_xlabel("transformed") +axes[2].set_ylabel("raw") plt.show() ############################################################################### @@ -90,10 +90,10 @@ ############################################################################### # Build data -x1 = np.random.randn(10000, 10) +x1 = rng.standard_normal((10000, 10)) x = np.hstack((x1, x1, x1)) C = np.dot(x.T, x) -print('Aggregated data covariance shape: {}'.format(C.shape)) +print(f"Aggregated data covariance shape: {C.shape}") ############################################################################### # Compute mCCA @@ -102,12 +102,12 @@ ############################################################################### # Plot results f, axes = plt.subplots(1, 3, figsize=(12, 4)) -axes[0].imshow(A, aspect='auto') -axes[0].set_title('mCCA transform matrix') -axes[1].imshow(A.T.dot(C.dot(A)), aspect='auto') -axes[1].set_title('Covariance of\ntransformed data') -axes[2].imshow(x.T.dot((x.dot(A))), aspect='auto') -axes[2].set_title('Cross-correlation between\nraw & transformed data') -axes[2].set_xlabel('transformed') -axes[2].set_ylabel('raw') +axes[0].imshow(A, aspect="auto") +axes[0].set_title("mCCA transform matrix") +axes[1].imshow(A.T.dot(C.dot(A)), aspect="auto") +axes[1].set_title("Covariance of\ntransformed data") +axes[2].imshow(x.T.dot(x.dot(A)), aspect="auto") +axes[2].set_title("Cross-correlation between\nraw & transformed data") +axes[2].set_xlabel("transformed") +axes[2].set_ylabel("raw") plt.show() diff --git a/examples/example_ress.py b/examples/example_ress.py index 903de7e5..b328c4c7 100644 --- a/examples/example_ress.py +++ b/examples/example_ress.py @@ -12,12 +12,13 @@ import matplotlib.pyplot as plt import numpy as np import scipy.signal as ss + from meegkit import ress from meegkit.utils import fold, matmul3d, rms, snr_spectrum, unfold # import config -np.random.seed(1) +rng = np.random.default_rng(9) ############################################################################### # Create synthetic data @@ -34,7 +35,7 @@ # source source = np.sin(2 * np.pi * target * np.arange(n_times - t0) / sfreq)[None].T -s = source * np.random.randn(1, n_chans) +s = source * rng.standard_normal((1, n_chans)) s = s[:, :, np.newaxis] s = np.tile(s, (1, 1, n_trials)) signal = np.zeros((n_times, n_chans, n_trials)) @@ -42,8 +43,8 @@ # noise noise = np.dot( - unfold(np.random.randn(n_times, noise_dim, n_trials)), - np.random.randn(noise_dim, n_chans)) + unfold(rng.standard_normal((n_times, noise_dim, n_trials))), + rng.standard_normal((noise_dim, n_chans))) noise = fold(noise, n_times) # mix signal and noise @@ -53,9 +54,9 @@ # Plot f, ax = plt.subplots(3) -ax[0].plot(signal[:, 0, 0], c='C0', label='source') -ax[1].plot(noise[:, 1, 0], c='C1', label='noise') -ax[2].plot(data[:, 1, 0], c='C2', label='mixture') +ax[0].plot(signal[:, 0, 0], c="C0", label="source") +ax[1].plot(noise[:, 1, 0], c="C1", label="noise") +ax[2].plot(data[:, 1, 0], c="C2", label="mixture") ax[0].legend() ax[1].legend() ax[2].legend() @@ -76,12 +77,12 @@ snr = snr_spectrum(psd, bins, skipbins=2, n_avg=2) f, ax = plt.subplots(1) -ax.plot(bins, snr, 'o', label='SNR') -ax.plot(bins[bins == target], snr[bins == target], 'ro', label='Target SNR') -ax.axhline(1, ls=':', c='grey', zorder=0) -ax.axvline(target, ls=':', c='grey', zorder=0) -ax.set_ylabel('SNR (a.u.)') -ax.set_xlabel('Frequency (Hz)') +ax.plot(bins, snr, "o", label="SNR") +ax.plot(bins[bins == target], snr[bins == target], "ro", label="Target SNR") +ax.axhline(1, ls=":", c="grey", zorder=0) +ax.axvline(target, ls=":", c="grey", zorder=0) +ax.set_ylabel("SNR (a.u.)") +ax.set_xlabel("Frequency (Hz)") ax.set_xlim([0, 40]) ############################################################################### @@ -89,15 +90,15 @@ # average SSVEP. proj = matmul3d(out, maps) -f, ax = plt.subplots(n_chans, 2, sharey='col') +f, ax = plt.subplots(n_chans, 2, sharey="col") for c in range(n_chans): ax[c, 0].plot(data[:, c].mean(-1), lw=.5) ax[c, 1].plot(proj[:, c].mean(-1), lw=.5) - ax[c, 0].set_ylabel(f'ch{c}') + ax[c, 0].set_ylabel(f"ch{c}") if c < n_chans: ax[c, 0].set_xticks([]) ax[c, 1].set_xticks([]) -ax[0, 0].set_title('Trial average (before)') -ax[0, 1].set_title('Trial average (after)') +ax[0, 0].set_title("Trial average (before)") +ax[0, 1].set_title("Trial average (after)") plt.show() diff --git a/examples/example_star.py b/examples/example_star.py index 694a79c8..9255630a 100644 --- a/examples/example_star.py +++ b/examples/example_star.py @@ -12,7 +12,7 @@ from meegkit import star from meegkit.utils import demean, normcol -# import config +rng = np.random.default_rng(9) ############################################################################### # Create simulated data @@ -26,12 +26,12 @@ f = 2 target = np.sin(np.arange(n_samples) / n_samples * 2 * np.pi * f) target = target[:, np.newaxis] -noise = np.random.randn(n_samples, nchans - 3) +noise = rng.standard_normal((n_samples, nchans - 3)) # Create artifact signal SNR = np.sqrt(1) -x0 = (normcol(np.dot(noise, np.random.randn(noise.shape[1], nchans))) + - SNR * target * np.random.randn(1, nchans)) +x0 = normcol(np.dot(noise, rng.standard_normal((noise.shape[1], nchans)))) + \ + SNR * target * rng.standard_normal((1, nchans)) x0 = demean(x0) artifact = np.zeros(x0.shape) for k in np.arange(nchans): @@ -54,10 +54,10 @@ # ----------------------------------------------------------------------------- f, (ax1, ax2, ax3) = plt.subplots(3, 1) ax1.plot(x, lw=.5) -ax1.set_title('Signal + Artifacts (SNR = {})'.format(SNR)) +ax1.set_title(f"Signal + Artifacts (SNR = {SNR})") ax2.plot(y, lw=.5) -ax2.set_title('Denoised') +ax2.set_title("Denoised") ax3.plot(demean(y) - x0, lw=.5) -ax3.set_title('Residual') +ax3.set_title("Residual") f.set_tight_layout(True) plt.show() diff --git a/examples/example_star_dss.py b/examples/example_star_dss.py index c4af48a5..66eb7956 100644 --- a/examples/example_star_dss.py +++ b/examples/example_star_dss.py @@ -16,15 +16,14 @@ """ import matplotlib.pyplot as plt import numpy as np - from scipy.optimize import leastsq -from meegkit import star, dss +from meegkit import dss, star from meegkit.utils import demean, normcol, tscov # import config # noqa -np.random.seed(9) +rng = np.random.default_rng(9) ############################################################################### # Create simulated data @@ -37,12 +36,12 @@ f = 2 target = np.sin(np.arange(n_samples) / n_samples * 2 * np.pi * f) target = target[:, np.newaxis] -noise = np.random.randn(n_samples, n_chans - 3) +noise = rng.standard_normal((n_samples, n_chans - 3)) # Create artifact signal SNR = np.sqrt(1) -x0 = (normcol(np.dot(noise, np.random.randn(noise.shape[1], n_chans))) + - SNR * target * np.random.randn(1, n_chans)) +x0 = normcol(np.dot(noise, rng.standard_normal((noise.shape[1], n_chans)))) + \ + SNR * target * rng.standard_normal((1, n_chans)) x0 = demean(x0) artifact = np.zeros(x0.shape) for k in np.arange(n_chans): @@ -95,18 +94,18 @@ def func(y): # ----------------------------------------------------------------------------- f, (ax0, ax1, ax2, ax3) = plt.subplots(4, 1, figsize=(7, 9)) ax0.plot(target, lw=.5) -ax0.set_title('Target') +ax0.set_title("Target") ax1.plot(x, lw=.5) -ax1.set_title('Signal + Artifacts (SNR = {})'.format(SNR)) +ax1.set_title(f"Signal + Artifacts (SNR = {SNR})") -ax2.plot(z1[:, 0], lw=.5, label='Best DSS component') -ax2.set_title('DSS') -ax2.legend(loc='lower right') +ax2.plot(z1[:, 0], lw=.5, label="Best DSS component") +ax2.set_title("DSS") +ax2.legend(loc="lower right") -ax3.plot(z2[:, 0], lw=.5, label='Best DSS component') -ax3.set_title('STAR + DSS') -ax3.legend(loc='lower right') +ax3.plot(z2[:, 0], lw=.5, label="Best DSS component") +ax3.set_title("STAR + DSS") +ax3.legend(loc="lower right") f.set_tight_layout(True) plt.show() diff --git a/examples/example_trca.py b/examples/example_trca.py index 0d227b07..b36f2bb6 100644 --- a/examples/example_trca.py +++ b/examples/example_trca.py @@ -11,8 +11,8 @@ Uses `meegkit.trca.TRCA()`. -References: - +References +---------- .. [1] M. Nakanishi, Y. Wang, X. Chen, Y.-T. Wang, X. Gao, and T.-P. Jung, "Enhancing detection of SSVEPs for a high-speed brain speller using task-related component analysis", IEEE Trans. Biomed. Eng, 65(1): 104-112, @@ -33,6 +33,7 @@ import matplotlib.pyplot as plt import numpy as np import scipy.io + from meegkit.trca import TRCA from meegkit.utils.trca import itr, normfit, round_half_up @@ -65,7 +66,7 @@ ############################################################################### # Load data # ----------------------------------------------------------------------------- -path = os.path.join('..', 'tests', 'data', 'trcadata.mat') +path = os.path.join("..", "tests", "data", "trcadata.mat") eeg = scipy.io.loadmat(path)["eeg"] n_trials, n_chans, n_samples, n_blocks = eeg.shape @@ -98,27 +99,27 @@ [(54, 90), (48, 100)]] f, ax = plt.subplots(1, figsize=(7, 4)) -for i, band in enumerate(filterbank): +for i, _band in enumerate(filterbank): ax.axvspan(ymin=i / len(filterbank) + .02, ymax=(i + 1) / len(filterbank) - .02, xmin=filterbank[i][1][0], xmax=filterbank[i][1][1], - alpha=0.2, facecolor=f'C{i}') + alpha=0.2, facecolor=f"C{i}") ax.axvspan(ymin=i / len(filterbank) + .02, ymax=(i + 1) / len(filterbank) - .02, xmin=filterbank[i][0][0], xmax=filterbank[i][0][1], - alpha=0.5, label=f'sub-band{i}', facecolor=f'C{i}') + alpha=0.5, label=f"sub-band{i}", facecolor=f"C{i}") for f in list_freqs.flat: colors = np.ones((9, 4)) colors[:, :3] = np.linspace(0, .5, 9)[:, None] ax.scatter(f * np.arange(1, 10), [f] * 9, c=colors, s=8, zorder=100) -ax.set_ylabel('Stimulus frequency (Hz)') -ax.set_xlabel('EEG response frequency (Hz)') +ax.set_ylabel("Stimulus frequency (Hz)") +ax.set_xlabel("EEG response frequency (Hz)") ax.set_xlim([0, 102]) ax.set_xticks(np.arange(0, 100, 10)) -ax.grid(True, ls=':', axis='x') -ax.legend(bbox_to_anchor=(1.05, .5), fontsize='small') +ax.grid(True, ls=":", axis="x") +ax.legend(bbox_to_anchor=(1.05, .5), fontsize="small") plt.tight_layout() plt.show() @@ -126,7 +127,7 @@ # Now perform the TRCA-based SSVEP detection algorithm trca = TRCA(sfreq, filterbank, is_ensemble) -print('Results of the ensemble TRCA-based method:\n') +print("Results of the ensemble TRCA-based method:\n") accs = np.zeros(n_blocks) itrs = np.zeros(n_blocks) for i in range(n_blocks): @@ -159,8 +160,8 @@ mu, _, muci, _ = normfit(itrs, alpha_ci) print(f"Mean ITR = {mu:.1f}\t({ci:.0f}% CI: {muci[0]:.1f}-{muci[1]:.1f})") if is_ensemble: - ensemble = 'ensemble TRCA-based method' + ensemble = "ensemble TRCA-based method" else: - ensemble = 'TRCA-based method' + ensemble = "TRCA-based method" print(f"\nElapsed time: {time.time()-t:.1f} seconds") diff --git a/meegkit/__init__.py b/meegkit/__init__.py index 0aec3dee..a68935b6 100644 --- a/meegkit/__init__.py +++ b/meegkit/__init__.py @@ -1,7 +1,7 @@ """M/EEG denoising utilities in python.""" -__version__ = '0.1.3' +__version__ = "0.1.4" -from . import asr, cca, detrend, dss, lof, sns, star, ress, trca, tspca, utils +from . import asr, cca, detrend, dss, lof, ress, sns, star, trca, tspca, utils -__all__ = ['asr', 'cca', 'detrend', 'dss', 'lof', 'ress', 'sns', 'star', 'trca', - 'tspca', 'utils'] +__all__ = ["asr", "cca", "detrend", "dss", "lof", "ress", "sns", "star", "trca", + "tspca", "utils"] diff --git a/meegkit/asr.py b/meegkit/asr.py index 2674e376..b22295fc 100755 --- a/meegkit/asr.py +++ b/meegkit/asr.py @@ -6,8 +6,7 @@ from statsmodels.robust.scale import mad from .utils import block_covariance, nonlinear_eigenspace -from .utils.asr import (geometric_median, fit_eeg_distribution, yulewalk, - yulewalk_filter) +from .utils.asr import fit_eeg_distribution, geometric_median, yulewalk, yulewalk_filter try: import pyriemann @@ -101,12 +100,12 @@ class ASR(): def __init__(self, sfreq=250, cutoff=5, blocksize=100, win_len=0.5, win_overlap=0.66, max_dropout_fraction=0.1, - min_clean_fraction=0.25, name='asrfilter', method='euclid', - estimator='scm', **kwargs): + min_clean_fraction=0.25, name="asrfilter", method="euclid", + estimator="scm", **kwargs): - if pyriemann is None and method == 'riemann': - logging.warning('Need pyriemann to use riemannian ASR flavor.') - method = 'euclid' + if pyriemann is None and method == "riemann": + logging.warning("Need pyriemann to use riemannian ASR flavor.") + method = "euclid" self.cutoff = cutoff self.blocksize = blocksize @@ -224,10 +223,10 @@ def transform(self, X, y=None, **kwargs): X, sfreq=self.sfreq, ab=self.ab_, zi=self.zi_) if not self._fitted: - logging.warning('ASR is not fitted ! Returning unfiltered data.') + logging.warning("ASR is not fitted ! Returning unfiltered data.") return X - if self.estimator == 'scm': + if self.estimator == "scm": cov = 1 / X.shape[-1] * X_filt @ X_filt.T else: cov = pyriemann.estimation.covariances(X_filt[None, ...], @@ -331,7 +330,7 @@ def clean_windows(X, sfreq, max_bad_chans=0.2, zthresholds=[-3.5, 5], N = int(win_len * sfreq) offsets = np.round(np.arange(0, ns - N, (N * (1 - win_overlap)))) offsets = offsets.astype(int) - logging.debug('[ASR] Determining channel-wise rejection thresholds') + logging.debug("[ASR] Determining channel-wise rejection thresholds") wz = np.zeros((nc, len(offsets))) for ichan in range(nc): @@ -391,18 +390,18 @@ def clean_windows(X, sfreq, max_bad_chans=0.2, zthresholds=[-3.5, 5], for i in range(nc): ax[i].fill_between(times, 0, 1, where=sample_mask.flat, transform=ax[i].get_xaxis_transform(), - facecolor='none', hatch='...', edgecolor='k', - label='selected window') - ax[i].plot(times, X[i], lw=.5, label='EEG') + facecolor="none", hatch="...", edgecolor="k", + label="selected window") + ax[i].plot(times, X[i], lw=.5, label="EEG") ax[i].set_ylim([-50, 50]) # ax[i].set_ylabel(raw.ch_names[i]) ax[i].set_yticks([]) - ax[i].set_xlabel('Time (s)') - ax[i].set_ylabel(f'ch{i}') - ax[0].legend(fontsize='small', bbox_to_anchor=(1.04, 1), + ax[i].set_xlabel("Time (s)") + ax[i].set_ylabel(f"ch{i}") + ax[0].legend(fontsize="small", bbox_to_anchor=(1.04, 1), borderaxespad=0) plt.subplots_adjust(hspace=0, right=0.75) - plt.suptitle('Clean windows') + plt.suptitle("Clean windows") plt.show() return clean, sample_mask @@ -410,7 +409,7 @@ def clean_windows(X, sfreq, max_bad_chans=0.2, zthresholds=[-3.5, 5], def asr_calibrate(X, sfreq, cutoff=5, blocksize=100, win_len=0.5, win_overlap=0.66, max_dropout_fraction=0.1, - min_clean_fraction=0.25, method='euclid', estimator='scm'): + min_clean_fraction=0.25, method="euclid", estimator="scm"): """Calibration function for the Artifact Subspace Reconstruction method. The input to this data is a multi-channel time series of calibration data. @@ -478,7 +477,7 @@ def asr_calibrate(X, sfreq, cutoff=5, blocksize=100, win_len=0.5, Threshold matrix. """ - logging.debug('[ASR] Calibrating...') + logging.debug("[ASR] Calibrating...") # set number of channels and number of samples [nc, ns] = X.shape @@ -491,11 +490,11 @@ def asr_calibrate(X, sfreq, cutoff=5, blocksize=100, win_len=0.5, U = block_covariance(X, window=blocksize, overlap=win_overlap, estimator=estimator) - if method == 'euclid': + if method == "euclid": Uavg = geometric_median(U.reshape((-1, nc * nc))) Uavg = Uavg.reshape((nc, nc)) else: # method == 'riemann' - Uavg = pyriemann.utils.mean.mean_covariance(U, metric='riemann') + Uavg = pyriemann.utils.mean.mean_covariance(U, metric="riemann") # get the mixing matrix M M = linalg.sqrtm(np.real(Uavg)) @@ -520,11 +519,11 @@ def asr_calibrate(X, sfreq, cutoff=5, blocksize=100, win_len=0.5, Y, min_clean_fraction, max_dropout_fraction) T = np.dot(np.diag(mu + cutoff * sig), V.T) - logging.debug('[ASR] Calibration done.') + logging.debug("[ASR] Calibration done.") return M, T -def asr_process(X, X_filt, state, cov=None, detrend=False, method='riemann', +def asr_process(X, X_filt, state, cov=None, detrend=False, method="riemann", sample_weight=None): """Apply Artifact Subspace Reconstruction method. @@ -567,14 +566,14 @@ def asr_process(X, X_filt, state, cov=None, detrend=False, method='riemann', if cov is None: if detrend: - X_filt = signal.detrend(X_filt, axis=1, type='constant') + X_filt = signal.detrend(X_filt, axis=1, type="constant") cov = block_covariance(X_filt, window=nc ** 2) cov = cov.squeeze() if cov.ndim == 3: - if method == 'riemann': + if method == "riemann": cov = pyriemann.utils.mean.mean_covariance( - cov, metric='riemann', sample_weight=sample_weight) + cov, metric="riemann", sample_weight=sample_weight) else: cov = geometric_median(cov.reshape((-1, nc * nc))) cov = cov.reshape((nc, nc)) @@ -582,7 +581,7 @@ def asr_process(X, X_filt, state, cov=None, detrend=False, method='riemann', maxdims = int(np.fix(0.66 * nc)) # constant TODO make param # do a PCA to find potential artifacts - if method == 'riemann': + if method == "riemann": D, Vtmp = nonlinear_eigenspace(cov, nc) # TODO else: D, Vtmp = linalg.eigh(cov) @@ -604,14 +603,14 @@ def asr_process(X, X_filt, state, cov=None, detrend=False, method='riemann', demux = VT * keep[:, None] R = np.dot(np.dot(M, linalg.pinv(demux)), V.T) - if state['R'] is not None: + if state["R"] is not None: # apply the reconstruction to intermediate samples (using raised-cosine # blending) blend = (1 - np.cos(np.pi * np.arange(ns) / ns)) / 2 - clean = blend * R.dot(X) + (1 - blend) * state['R'].dot(X) + clean = blend * R.dot(X) + (1 - blend) * state["R"].dot(X) else: clean = R.dot(X) - state['R'] = R + state["R"] = R return clean, state diff --git a/meegkit/cca.py b/meegkit/cca.py index ebba7d32..efdcb604 100644 --- a/meegkit/cca.py +++ b/meegkit/cca.py @@ -3,7 +3,7 @@ from scipy import linalg from .utils import cov_lags, pca -from .utils.matrix import _check_shifts, normcol, relshift, _times_to_delays +from .utils.matrix import _check_shifts, _times_to_delays, normcol, relshift try: from tqdm import tqdm @@ -11,7 +11,7 @@ def tqdm(*args, **kwargs): # noqa if args: return args[0] - return kwargs.get('iterable', None) + return kwargs.get("iterable", None) def mcca(C, n_channels, n_keep=[]): @@ -45,9 +45,9 @@ def mcca(C, n_channels, n_keep=[]): """ if C.shape[0] != C.shape[1]: - raise ValueError('Covariance must be square !') + raise ValueError("Covariance must be square !") if np.mod(C.shape[0], n_channels) != 0: - raise ValueError('!') + raise ValueError("!") # Whiten covariance by blocks n_blocks = C.shape[0] // n_channels @@ -78,8 +78,7 @@ def mcca(C, n_channels, n_keep=[]): return A, scores, AA -def cca_crossvalidate(xx, yy, shifts=None, sfreq=1, surrogate=False, - plot=False): +def cca_crossvalidate(xx, yy, shifts=None, sfreq=1, surrogate=False, plot=False): """CCA with cross-validation. Parameters @@ -119,8 +118,8 @@ def cca_crossvalidate(xx, yy, shifts=None, sfreq=1, surrogate=False, xx = [xx[..., t] for t in np.arange(xx.shape[-1])] yy = [yy[..., t] for t in np.arange(yy.shape[-1])] else: - raise AttributeError('xx and yy both must be lists of same length, ' - 'or arrays os same n_trials.') + raise AttributeError("xx and yy both must be lists of same length, " + "or arrays os same n_trials.") shifts = _times_to_delays(shifts, sfreq) shifts, n_shifts = _check_shifts(shifts) @@ -128,13 +127,13 @@ def cca_crossvalidate(xx, yy, shifts=None, sfreq=1, surrogate=False, n_feats = xx[0].shape[1] + yy[0].shape[1] # sum of channels # Calculate covariance matrices - print('Calculate all covariances...') + print("Calculate all covariances...") C = np.zeros((n_feats, n_feats, n_shifts, n_trials)).squeeze() for t in tqdm(np.arange(n_trials)): C[..., t], _, _ = cov_lags(xx[t], yy[t], shifts) # Calculate leave-one-out CCAs - print('Calculate CCAs...') + print("Calculate CCAs...") AA = [] BB = [] for t in tqdm(np.arange(n_trials)): @@ -152,7 +151,7 @@ def cca_crossvalidate(xx, yy, shifts=None, sfreq=1, surrogate=False, del C, CC # Calculate leave-one-out correlation coefficients - print('Calculate cross-correlations...') + print("Calculate cross-correlations...") n_comps = AA[0].shape[1] r = np.zeros((n_comps, n_shifts)) RR = np.zeros((n_comps, n_shifts, n_trials)) @@ -191,23 +190,23 @@ def cca_crossvalidate(xx, yy, shifts=None, sfreq=1, surrogate=False, import matplotlib.pyplot as plt f, (ax1) = plt.subplots(1, 1) for k in range(RR.shape[0]): - ax1.plot(shifts, np.mean(RR[k, :, :], 1).T, label='CC{}'.format(k)) - ax1.set_title('correlation for each CC') - ax1.set_xlabel('shift') - ax1.set_ylabel('correlation') + ax1.plot(shifts, np.mean(RR[k, :, :], 1).T, label=f"CC{k}") + ax1.set_title("correlation for each CC") + ax1.set_xlabel("shift") + ax1.set_ylabel("correlation") ax1.legend() # if surrogate: # ax1.plot(SD.T, ':') f2, axes = plt.subplots(min(4, RR.shape[0]), 1) - for k, ax in zip(np.arange(min(4, RR.shape[0])), axes): + for k, ax in zip(np.arange(min(4, RR.shape[0])), axes, strict=True): idx = np.argmax(np.mean(RR[k, :, :], 1)) [x, y] = relshift(xx[0], yy[0], shifts[idx]) - ax.plot(np.dot(x, AA[0][:, k, idx]).T, label='CC{}'.format(k)) - ax.plot(np.dot(y, BB[0][:, k, idx]).T, ':') + ax.plot(np.dot(x, AA[0][:, k, idx]).T, label=f"CC{k}") + ax.plot(np.dot(y, BB[0][:, k, idx]).T, ":") ax.legend() - ax.set_xlabel('sample') + ax.set_xlabel("sample") f2.set_tight_layout(True) plt.show() @@ -268,7 +267,7 @@ def nt_cca(X=None, Y=None, lags=None, C=None, m=None, thresh=1e-12, sfreq=1): """ if (X is None and Y is not None) or (Y is None and X is not None): - raise AttributeError('Either *both* X and Y should be defined, or C!') + raise AttributeError("Either *both* X and Y should be defined, or C!") if X is not None: lags = _times_to_delays(lags, sfreq) @@ -278,15 +277,15 @@ def nt_cca(X=None, Y=None, lags=None, C=None, m=None, thresh=1e-12, sfreq=1): return A, B, R if C is None: - raise RuntimeError('covariance matrix should be defined') + raise RuntimeError("covariance matrix should be defined") if m is None: - raise RuntimeError('m should be defined') + raise RuntimeError("m should be defined") if C.shape[0] != C.shape[1]: - raise RuntimeError('covariance matrix should be square') + raise RuntimeError("covariance matrix should be square") if any((X, Y, lags)): - raise RuntimeError('only covariance should be defined at this point') + raise RuntimeError("only covariance should be defined at this point") if C.ndim > 3: - raise RuntimeError('covariance should be 3D at most') + raise RuntimeError("covariance should be 3D at most") if C.ndim == 3: # covariance is 3D: do a separate CCA for each page n_chans, _, n_lags = C.shape diff --git a/meegkit/detrend.py b/meegkit/detrend.py index 34de9f74..43cde6ae 100644 --- a/meegkit/detrend.py +++ b/meegkit/detrend.py @@ -1,6 +1,5 @@ """Robust detrending.""" import numpy as np - from scipy.signal import lfilter from .utils import demean, mrdivide, pca, unfold @@ -8,7 +7,7 @@ from .utils.sig import stmcb -def detrend(x, order, w=None, basis='polynomials', threshold=3, n_iter=4, +def detrend(x, order, w=None, basis="polynomials", threshold=3, n_iter=4, show=False): """Robustly remove trend. @@ -59,7 +58,7 @@ def detrend(x, order, w=None, basis='polynomials', threshold=3, n_iter=4, """ if threshold == 0: - raise ValueError('thresh=0 is not what you want...') + raise ValueError("thresh=0 is not what you want...") # check/fix sizes dims = x.shape @@ -73,22 +72,22 @@ def detrend(x, order, w=None, basis='polynomials', threshold=3, n_iter=4, r = basis else: lin = np.linspace(-1, 1, n_times) - if basis == 'polynomials' or basis is None: + if basis == "polynomials" or basis is None: r = np.zeros((n_times, order)) for i, o in enumerate(range(1, order + 1)): r[:, i] = lin ** o - elif basis == 'sinusoids': + elif basis == "sinusoids": r = np.zeros((n_times, order * 2)) for i, o in enumerate(range(1, order + 1)): r[:, 2 * i] = np.sin(2 * np.pi * o * lin / 2) r[:, 2 * i + 1] = np.cos(2 * np.pi * o * lin / 2) else: - raise ValueError('!') + raise ValueError("!") # iteratively remove trends # the tricky bit is to ensure that weighted means are removed before # calculating the regression (see regress()). - for i in range(n_iter): + for _ in range(n_iter): # weighted regression on basis _, y = regress(x, r, w) @@ -150,7 +149,7 @@ def regress(x, r, w=None, threshold=1e-7, return_mean=False): r = unfold(r) x = unfold(x) if r.shape[0] != x.shape[0]: - raise ValueError('r and x have incompatible shapes!') + raise ValueError("r and x have incompatible shapes!") # save weighted mean mn = x - demean(x, w) @@ -171,11 +170,11 @@ def regress(x, r, w=None, threshold=1e-7, return_mean=False): else: # weighted regression if w.shape[0] != n_times: - raise ValueError('!') + raise ValueError("!") if w.shape[1] == 1: # same weight for all channels if sum(w.flatten()) == 0: - print('weights all zero') + print("weights all zero") b = 0 else: yy = demean(x, w) * w @@ -189,12 +188,12 @@ def regress(x, r, w=None, threshold=1e-7, return_mean=False): else: # each channel has own weight if w.shape[1] != x.shape[1]: - raise ValueError('!') + raise ValueError("!") z = np.zeros(x.shape) b = np.zeros((n_chans, n_regs)) for i in range(n_chans): if not np.any(w[:, i]): - print(f'weights are all zero for channel {i}') + print(f"weights are all zero for channel {i}") else: wc = w[:, i][:, None] # channel-specific weight xx = demean(x[:, i], wc) * wc @@ -245,7 +244,7 @@ def reduce_ringing(X, samples, order=10, n_samples=100, extra=50, threshold=3, samples = samples[samples < X.shape[0] - n_samples] y = X.copy() - for i, s in enumerate(samples): + for _i, s in enumerate(samples): for c in range(X.shape[1]): # select portion to fit filter response, remove polynomial trend response = X[s - extra:s + n_samples, c] @@ -282,22 +281,22 @@ def _plot_detrend(x, y, w): f = plt.figure() gs = GridSpec(4, 1, figure=f) ax1 = f.add_subplot(gs[:3, 0]) - lines = ax1.plot(x, label='original', color='C0') + lines = ax1.plot(x, label="original", color="C0") plt.setp(lines[1:], label="_") - lines = ax1.plot(y, label='detrended', color='C1') + lines = ax1.plot(y, label="detrended", color="C1") plt.setp(lines[1:], label="_") ax1.set_xlim(0, n_times) - ax1.set_xticklabels('') - ax1.set_title('Robust detrending') - ax1.legend(fontsize='smaller') + ax1.set_xticklabels("") + ax1.set_title("Robust detrending") + ax1.legend(fontsize="smaller") ax2 = f.add_subplot(gs[3, 0]) - ax2.pcolormesh(w.T, cmap='Greys') + ax2.pcolormesh(w.T, cmap="Greys") ax2.set_yticks(np.arange(0, n_chans) + 0.5) - ax2.set_yticklabels(['ch{}'.format(i) for i in np.arange(n_chans)]) + ax2.set_yticklabels([f"ch{i}" for i in np.arange(n_chans)]) ax2.set_xlim(0, n_times) - ax2.set_ylabel('ch. weights') - ax2.set_xlabel('samples') + ax2.set_ylabel("ch. weights") + ax2.set_xlabel("samples") plt.show() @@ -334,7 +333,7 @@ def create_masked_weight(x, events, tmin, tmax, sfreq): """ if x.ndim != 2: - raise ValueError('The shape of x must be (n_times, n_channels)') + raise ValueError("The shape of x must be (n_times, n_channels)") weights = np.ones(x.shape) for e in events: diff --git a/meegkit/dss.py b/meegkit/dss.py index f4841ba3..f2017cb9 100644 --- a/meegkit/dss.py +++ b/meegkit/dss.py @@ -2,14 +2,22 @@ # Authors: Nicolas Barascud # Maciej Szul import numpy as np +from numpy.lib.stride_tricks import sliding_window_view from scipy import linalg from scipy.signal import welch from .tspca import tsr -from .utils import (demean, gaussfilt, matmul3d, mean_over_trials, pca, smooth, - theshapeof, tscov, wpwr) - -from numpy.lib.stride_tricks import sliding_window_view +from .utils import ( + demean, + gaussfilt, + matmul3d, + mean_over_trials, + pca, + smooth, + theshapeof, + tscov, + wpwr, +) def dss1(X, weights=None, keep1=None, keep2=1e-12): @@ -94,15 +102,15 @@ def dss0(c0, c1, keep1=None, keep2=1e-9): """ if c0 is None or c1 is None: - raise AttributeError('dss0 needs at least two arguments') + raise AttributeError("dss0 needs at least two arguments") if c0.shape != c1.shape: - raise AttributeError('c0 and c1 should have same size') + raise AttributeError("c0 and c1 should have same size") if c0.shape[0] != c0.shape[1]: - raise AttributeError('c0 should be square') + raise AttributeError("c0 should be square") if np.any(np.isnan(c0)) or np.any(np.isinf(c0)): - raise ValueError('NaN or INF in c0') + raise ValueError("NaN or INF in c0") if np.any(np.isnan(c1)) or np.any(np.isinf(c1)): - raise ValueError('NaN or INF in c1') + raise ValueError("NaN or INF in c1") # derive PCA and whitening matrix from unbiased covariance eigvec0, eigval0 = pca(c0, max_comps=keep1, thresh=keep2) @@ -190,7 +198,7 @@ def dss_line(X, fline, sfreq, nremove=1, nfft=1024, nkeep=None, blocksize=None, """ if X.shape[0] < nfft: - print('Reducing nfft to {}'.format(X.shape[0])) + print(f"Reducing nfft to {X.shape[0]}") nfft = X.shape[0] n_samples, n_chans, _ = theshapeof(X) if blocksize is None: @@ -233,10 +241,10 @@ def dss_line(X, fline, sfreq, nremove=1, nfft=1024, nkeep=None, blocksize=None, if show: import matplotlib.pyplot as plt - plt.plot(pwr1 / pwr0, '.-') - plt.xlabel('component') - plt.ylabel('score') - plt.title('DSS to enhance line frequencies') + plt.plot(pwr1 / pwr0, ".-") + plt.xlabel("component") + plt.ylabel("score") + plt.title("DSS to enhance line frequencies") plt.show() # Remove line components from X_noise @@ -249,7 +257,7 @@ def dss_line(X, fline, sfreq, nremove=1, nfft=1024, nkeep=None, blocksize=None, # Power of components p = wpwr(X - y)[0] / wpwr(X)[0] - print('Power of components removed by DSS: {:.2f}'.format(p)) + print(f"Power of components removed by DSS: {p:.2f}") # return the reconstructed clean signal, and the artifact return y, X - y @@ -334,7 +342,7 @@ def nan_basic_interp(array): mean_score = np.mean(residuals[freq_sp_ix]) aggr_resid.append(mean_score) - print("Iteration {} score: {}".format(iterations, mean_score)) + print(f"Iteration {iterations} score: {mean_score}") if show: import matplotlib.pyplot as plt @@ -362,7 +370,7 @@ def nan_basic_interp(array): ax.flat[2].scatter(residuals[tf_ix], freq_used[tf_ix], c=color) ax.flat[2].set_title("Residuals") - ax.flat[3].plot(np.arange(iterations + 1), aggr_resid, marker='o') + ax.flat[3].plot(np.arange(iterations + 1), aggr_resid, marker="o") ax.flat[3].set_title("Iterations") f.set_tight_layout(True) @@ -375,7 +383,7 @@ def nan_basic_interp(array): iterations += 1 if iterations == n_iter_max: - raise RuntimeError('Could not converge. Consider increasing the ' - 'maximum number of iterations') + raise RuntimeError("Could not converge. Consider increasing the " + "maximum number of iterations") return data, iterations diff --git a/meegkit/lof.py b/meegkit/lof.py index 9f9db51c..3974bf7c 100644 --- a/meegkit/lof.py +++ b/meegkit/lof.py @@ -3,6 +3,7 @@ # License: BSD-3-Clause import logging + from sklearn.neighbors import LocalOutlierFactor @@ -42,7 +43,7 @@ class LOF(): """ - def __init__(self, n_neighbors=20, metric='euclidean', + def __init__(self, n_neighbors=20, metric="euclidean", threshold=1.5, **kwargs): self.n_neighbors = n_neighbors @@ -63,21 +64,21 @@ def predict(self, X): """ if X.ndim == 3: # in case the input data is epoched - logging.warning('Expected input data with shape ' - '(n_channels, n_samples)') + logging.warning("Expected input data with shape " + "(n_channels, n_samples)") return [] if self.n_neighbors >= X.shape[0]: - logging.warning('Number of neighbours cannot be greater than the ' - 'number of channels') + logging.warning("Number of neighbours cannot be greater than the " + "number of channels") return [] if self.threshold < 1.0: - logging.warning('Invalid threshold. Try a positive integer >= 1.0') + logging.warning("Invalid threshold. Try a positive integer >= 1.0") return [] clf = LocalOutlierFactor(self.n_neighbors) - logging.debug('[LOF] Predicting bad channels') + logging.debug("[LOF] Predicting bad channels") clf.fit_predict(X) lof_scores = clf.negative_outlier_factor_ bad_channel_indices = -lof_scores >= self.threshold diff --git a/meegkit/ress.py b/meegkit/ress.py index dbb33a84..b47fd7b5 100644 --- a/meegkit/ress.py +++ b/meegkit/ress.py @@ -2,7 +2,7 @@ import numpy as np from scipy import linalg -from .utils import demean, gaussfilt, theshapeof, tscov, mrdivide +from .utils import demean, gaussfilt, mrdivide, theshapeof, tscov def RESS(X, sfreq: int, peak_freq: float, neig_freq: float = 1, diff --git a/meegkit/sns.py b/meegkit/sns.py index 9ad0fe38..cd068c87 100644 --- a/meegkit/sns.py +++ b/meegkit/sns.py @@ -5,8 +5,10 @@ from .utils import demean, fold, pca, theshapeof, tscov, unfold from .utils.matrix import _check_weights +DEFAULT_WEIGHTS = np.array([]) -def sns(X, n_neighbors=0, skip=0, weights=np.array([])): + +def sns(X, n_neighbors=0, skip=0, weights=DEFAULT_WEIGHTS): """Sensor Noise Suppression. This algorithm will replace the data from each channel by its regression on @@ -61,7 +63,7 @@ def sns(X, n_neighbors=0, skip=0, weights=np.array([])): return y, r -def sns0(c, n_neighbors=0, skip=0, wc=np.array([])): +def sns0(c, n_neighbors=0, skip=0, wc=DEFAULT_WEIGHTS): """Sensor Noise Suppression from data covariance. Parameters @@ -124,7 +126,7 @@ def sns0(c, n_neighbors=0, skip=0, wc=np.array([])): r[k, idx] = np.dot(eigvec, np.dot(wc[k][idx], eigvec)) if r[k, k] != 0: - raise RuntimeError('SNS operator should be zero along diagonal') + raise RuntimeError("SNS operator should be zero along diagonal") return r.T diff --git a/meegkit/star.py b/meegkit/star.py index f4b178d4..462b0f53 100644 --- a/meegkit/star.py +++ b/meegkit/star.py @@ -2,8 +2,7 @@ import numpy as np from scipy.signal import filtfilt -from .utils import (demean, fold, mrdivide, normcol, pca, theshapeof, tscov, - unfold, wpwr) +from .utils import demean, fold, mrdivide, normcol, pca, theshapeof, tscov, unfold, wpwr def star(X, thresh=1, closest=[], depth=1, pca_thresh=1e-15, n_smooth=10, @@ -48,7 +47,9 @@ def star(X, thresh=1, closest=[], depth=1, pca_thresh=1e-15, n_smooth=10, if thresh is None: thresh = 1 if len(closest) > 0 and closest.shape[0] != X.shape[1]: - raise ValueError('`closest` should have as many rows as n_chans') + raise ValueError("`closest` should have as many rows as n_chans") + + rng = np.random.default_rng() ndims = X.ndim n_samples, n_chans, n_trials = theshapeof(X) @@ -64,9 +65,9 @@ def star(X, thresh=1, closest=[], depth=1, pca_thresh=1e-15, n_smooth=10, idx_nan = np.all(np.isnan(X), axis=0) idx_zero = np.all(X == 0, axis=0) if idx_nan.any(): - X[:, idx_nan] = np.random.randn(X.shape[0], np.sum(idx_nan)) + X[:, idx_nan] = rng.standard_normal((X.shape[0], np.sum(idx_nan))) if idx_zero.any(): - X[:, idx_zero] = np.random.randn(X.shape[0], np.sum(idx_zero)) + X[:, idx_zero] = rng.standard_normal((X.shape[0], np.sum(idx_zero))) # initial covariance estimate X = demean(X) @@ -98,12 +99,12 @@ def star(X, thresh=1, closest=[], depth=1, pca_thresh=1e-15, n_smooth=10, artifact_free = np.mean(w, axis=0) if verbose: - print('proportion artifact free: {:.2f}'.format(artifact_free)) + print(f"proportion artifact free: {artifact_free:.2f}") if iter == n_iter and artifact_free < min_prop: thresh = thresh * 1.1 if verbose: - print('Warning: increasing threshold to {:.2f}'.format(thresh)) + print(f"Warning: increasing threshold to {thresh:.2f}") w = np.ones(w.shape) else: iter = iter - 1 @@ -153,10 +154,10 @@ def star(X, thresh=1, closest=[], depth=1, pca_thresh=1e-15, n_smooth=10, y[bad_samples, ch] = z.squeeze() # fix if verbose: - print('depth: {}'.format(i_depth + 1)) - print('fixed channels: {}'.format(i_fixed)) - print('fixed samples: {}'.format(n_fixed)) - print('ratio: {:.2f}'.format(wpwr(X)[0] / p00)) + print(f"depth: {i_depth + 1}") + print(f"fixed channels: {i_fixed}") + print(f"fixed samples: {n_fixed}") + print(f"ratio: {wpwr(X)[0] / p00:.2f}") y = demean(y) y *= norm @@ -169,9 +170,9 @@ def star(X, thresh=1, closest=[], depth=1, pca_thresh=1e-15, n_smooth=10, y[:, idx_zero] = 0 if verbose: - print('power ratio: {:.2f}'.format(wpwr(y)[0] / p0)) + print(f"power ratio: {wpwr(y)[0] / p0:.2f}") - if verbose == 'debug': + if verbose == "debug": _diagnostics(X * norm + intercept, y, d, thresh) if ndims == 3: # fold back into trials @@ -250,24 +251,24 @@ def _diagnostics(X, y, d, thresh): f, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1) ax1.plot(X, lw=.5) - ax1.set_title('Signal + Artifacts') + ax1.set_title("Signal + Artifacts") ax1.set_xticklabels([]) ax2.plot(demean(y), lw=.5) - ax2.set_title('Denoised') + ax2.set_title("Denoised") ax2.set_xticklabels([]) ax3.plot(X - demean(y), lw=.5) - ax3.set_title('Residual') + ax3.set_title("Residual") ax3.set_xticklabels([]) ax4.plot(d, lw=.5, alpha=.3) d[d < thresh] = None ax4.plot(d, lw=1) - ax4.axhline(thresh, lw=2, color='k', ls=':') + ax4.axhline(thresh, lw=2, color="k", ls=":") ax4.set_ylim([0, thresh + 1]) - ax4.set_title('Eccentricity') - ax4.set_xlabel('samples') + ax4.set_title("Eccentricity") + ax4.set_xlabel("samples") - f.set_tight_layout(True) + f.set_layout_engine("tight") plt.show() diff --git a/meegkit/trca.py b/meegkit/trca.py index 9c410805..892948dc 100644 --- a/meegkit/trca.py +++ b/meegkit/trca.py @@ -3,11 +3,11 @@ # Ludovic Darmet import numpy as np import scipy.linalg as linalg -from pyriemann.utils.mean import mean_covariance from pyriemann.estimation import Covariances +from pyriemann.utils.mean import mean_covariance -from .utils.trca import bandpass, schaefer_strimmer_cov from .utils import theshapeof +from .utils.trca import bandpass, schaefer_strimmer_cov class TRCA: @@ -66,15 +66,15 @@ class TRCA: """ - def __init__(self, sfreq, filterbank, ensemble=False, method='original', - estimator='scm'): + def __init__(self, sfreq, filterbank, ensemble=False, method="original", + estimator="scm"): self.sfreq = sfreq self.ensemble = ensemble self.filterbank = filterbank self.n_bands = len(self.filterbank) self.coef_ = None self.method = method - if estimator == 'schaefer': + if estimator == "schaefer": self.estimator = schaefer_strimmer_cov else: self.estimator = estimator @@ -112,12 +112,12 @@ def fit(self, X, y): trains[class_i, fb_i] = eeg_tmp # Find the spatial filter for the corresponding filtered signal # and label - if self.method == 'original': + if self.method == "original": w_best = trca(eeg_tmp) - elif self.method == 'riemann': + elif self.method == "riemann": w_best = trca_regul(eeg_tmp, self.estimator) else: - raise ValueError('Invalid `method` option.') + raise ValueError("Invalid `method` option.") W[fb_i, class_i, :] = w_best # Store the spatial filter @@ -144,14 +144,14 @@ def predict(self, X): """ if self.coef_ is None: - raise RuntimeError('TRCA is not fitted') + raise RuntimeError("TRCA is not fitted") # Alpha coefficients for the fusion of filterbank analysis fb_coefs = [(x + 1)**(-1.25) + 0.25 for x in range(self.n_bands)] _, _, n_trials = theshapeof(X) r = np.zeros((self.n_bands, len(self.classes))) - pred = np.zeros((n_trials), 'int') # To store predictions + pred = np.zeros((n_trials), "int") # To store predictions for trial in range(n_trials): test_tmp = X[..., trial] # pick a trial to be analysed @@ -318,9 +318,9 @@ def trca_regul(X, method): # If the number of samples is too big, we compute an approximate of # riemannian mean to speed up the computation if n_trials < 30: - S = mean_covariance(S, metric='riemann') + S = mean_covariance(S, metric="riemann") else: - S = mean_covariance(S, metric='logeuclid') + S = mean_covariance(S, metric="logeuclid") # 3. Compute eigenvalues and vectors # ------------------------------------------------------------------------- diff --git a/meegkit/tspca.py b/meegkit/tspca.py index 0efbac21..bb0622c3 100644 --- a/meegkit/tspca.py +++ b/meegkit/tspca.py @@ -1,8 +1,19 @@ """Time-shift PCA.""" import numpy as np -from .utils import (demean, fold, multishift, normcol, pca, regcov, tscov, - tsxcov, unfold, theshapeof, unsqueeze) +from .utils import ( + demean, + fold, + multishift, + normcol, + pca, + regcov, + theshapeof, + tscov, + tsxcov, + unfold, + unsqueeze, +) from .utils.matrix import _check_shifts, _check_weights diff --git a/meegkit/utils/__init__.py b/meegkit/utils/__init__.py index 766cc140..28b1cc6b 100644 --- a/meegkit/utils/__init__.py +++ b/meegkit/utils/__init__.py @@ -1,16 +1,53 @@ """Utility functions.""" -from .auditory import (AuditoryFilterbank, GammatoneFilterbank, erb2hz, - erbspace, hz2erb) +from .auditory import AuditoryFilterbank, GammatoneFilterbank, erb2hz, erbspace, hz2erb from .base import mldivide, mrdivide -from .covariances import (block_covariance, convmtx, cov_lags, - nonlinear_eigenspace, pca, regcov, tscov, tsxcov) -from .denoise import (demean, find_outlier_samples, find_outlier_trials, - mean_over_trials, wpwr) -from .matrix import (fold, matmul3d, multishift, multismooth, normcol, - relshift, shift, shiftnd, sliding_window, theshapeof, - unfold, unsqueeze, widen_mask) -from .sig import (gaussfilt, hilbert_envelope, slope_sum, smooth, - spectral_envelope, teager_kaiser) -from .stats import (bootstrap_ci, bootstrap_snr, cronbach, rms, robust_mean, - rolling_corr, snr_spectrum) +from .covariances import ( + block_covariance, + convmtx, + cov_lags, + nonlinear_eigenspace, + pca, + regcov, + tscov, + tsxcov, +) +from .denoise import ( + demean, + find_outlier_samples, + find_outlier_trials, + mean_over_trials, + wpwr, +) +from .matrix import ( + fold, + matmul3d, + multishift, + multismooth, + normcol, + relshift, + shift, + shiftnd, + sliding_window, + theshapeof, + unfold, + unsqueeze, + widen_mask, +) +from .sig import ( + gaussfilt, + hilbert_envelope, + slope_sum, + smooth, + spectral_envelope, + teager_kaiser, +) +from .stats import ( + bootstrap_ci, + bootstrap_snr, + cronbach, + rms, + robust_mean, + rolling_corr, + snr_spectrum, +) from .testing import create_line_data diff --git a/meegkit/utils/asr.py b/meegkit/utils/asr.py index 3a15120d..dd0fa6b5 100755 --- a/meegkit/utils/asr.py +++ b/meegkit/utils/asr.py @@ -6,11 +6,12 @@ from scipy.spatial.distance import cdist, euclidean from scipy.special import gamma, gammaincinv +SHAPE_RANGE = np.linspace(1.7, 3.5, 13) + def fit_eeg_distribution(X, min_clean_fraction=0.25, max_dropout_fraction=0.1, - fit_quantiles=[0.022, 0.6], - step_sizes=[0.0220, 0.6000], - shape_range=np.linspace(1.7, 3.5, 13)): + fit_quantiles=[0.022, 0.6], step_sizes=[0.0220, 0.6000], + shape_range=SHAPE_RANGE): """Estimate the mean and SD of clean EEG from contaminated data. This function estimates the mean and standard deviation of clean EEG from a @@ -39,14 +40,14 @@ def fit_eeg_distribution(X, min_clean_fraction=0.25, max_dropout_fraction=0.1, ---------- X : array, shape=(n_channels, n_samples) EEG data, possibly containing artifacts. - max_dropout_fraction : float - Maximum fraction that can have dropouts. This is the maximum fraction - of time windows that may have arbitrarily low amplitude (e.g., due to - the sensors being unplugged) (default=0.25). min_clean_fraction : float Minimum fraction that needs to be clean. This is the minimum fraction of time windows that need to contain essentially uncontaminated EEG (default=0.1). + max_dropout_fraction : float + Maximum fraction that can have dropouts. This is the maximum fraction + of time windows that may have arbitrarily low amplitude (e.g., due to + the sensors being unplugged) (default=0.25). fit_quantiles : 2-tuple Quantile range [lower,upper] of the truncated generalized Gaussian distribution that shall be fit to the EEG contents (default=[0.022 @@ -56,7 +57,7 @@ def fit_eeg_distribution(X, min_clean_fraction=0.25, max_dropout_fraction=0.1, lower bound (which essentially steps over any dropout samples), and the second value is the stepping over possible scales (i.e., clean-data quantiles) (default=[0.01, 0.01]). - beta : array + shape_range : array Range that the clean EEG distribution's shape parameter beta may take. Returns diff --git a/meegkit/utils/auditory.py b/meegkit/utils/auditory.py index bc193190..49492770 100644 --- a/meegkit/utils/auditory.py +++ b/meegkit/utils/auditory.py @@ -224,5 +224,5 @@ def __init__(self, sfreq, b=1.019, order=1, q=9.26449, min_bw=24.7): 30, 800, 1000, 1250, 1600, 2000, 2500, 3150, 4000, 5000, 6300, 8000]) - super(AuditoryFilterbank, self).__init__( + super().__init__( sfreq=sfreq, cf=cf, b=b, order=order, q=q, min_bw=min_bw) diff --git a/meegkit/utils/base.py b/meegkit/utils/base.py index 46cdff6d..be4ff314 100644 --- a/meegkit/utils/base.py +++ b/meegkit/utils/base.py @@ -39,11 +39,12 @@ def mldivide(A, B): try: # Note: we must use overwrite_a=False in order to be able to # use the fall-back solution below in case a LinAlgError is raised - return linalg.solve(A, B, assume_a='pos', overwrite_a=False) + return linalg.solve(A, B, assume_a="pos", overwrite_a=False) except linalg.LinAlgError: # Singular matrix in solving dual problem. Using least-squares # solution instead. - return linalg.lstsq(A, B, lapack_driver='gelsy')[0] - except linalg.LinAlgError: - print('Solution not stable. Model not updated!') - return None + try: + return linalg.lstsq(A, B, lapack_driver="gelsy")[0] + except linalg.LinAlgError: + print("Solution not stable. Model not updated!") + return None diff --git a/meegkit/utils/covariances.py b/meegkit/utils/covariances.py index dd496a4a..383a5f28 100644 --- a/meegkit/utils/covariances.py +++ b/meegkit/utils/covariances.py @@ -3,12 +3,19 @@ from scipy import linalg from .base import mldivide -from .matrix import (_check_shifts, _check_weights, multishift, relshift, - theshapeof, unsqueeze) +from .matrix import ( + _check_shifts, + _check_weights, + multishift, + relshift, + theshapeof, + unsqueeze, +) +rng = np.random.default_rng() -def block_covariance(data, window=128, overlap=0.5, padding=True, - estimator='cov'): + +def block_covariance(data, window=128, overlap=0.5, padding=True, estimator="cov"): """Compute blockwise covariance. Parameters @@ -78,11 +85,11 @@ def cov_lags(X, Y, shifts=None): n_samples2, n_chans2, n_trials2 = theshapeof(Y) if n_samples != n_samples2: - raise AttributeError('X and Y must have same n_times') + raise AttributeError("X and Y must have same n_times") if n_trials != n_trials2: - raise AttributeError('X and Y must have same n_trials') + raise AttributeError("X and Y must have same n_trials") if n_samples <= max(shifts): - raise AttributeError('shifts should be no larger than n_samples') + raise AttributeError("shifts should be no larger than n_samples") n_cov = n_chans + n_chans2 # sum of channels of X and Y C = np.zeros((n_cov, n_cov, n_shifts)) @@ -142,7 +149,7 @@ def tsxcov(X, Y, shifts=None, weights=None, assume_centered=True): # Apply weights if any if weights.any(): - X = np.einsum('ijk,ilk->ijk', X, weights) # element-wise mult + X = np.einsum("ijk,ilk->ijk", X, weights) # element-wise mult weights = weights[:n_times2, :, :] # cross covariance @@ -208,7 +215,7 @@ def tscov(X, shifts=None, weights=None, assume_centered=True): X = X - X.mean(0, keepdims=1) if weights.any(): # weights - X = np.einsum('ijk,ilk->ijk', X, weights) # element-wise mult + X = np.einsum("ijk,ilk->ijk", X, weights) # element-wise mult tw = np.sum(weights[:]) else: # no weights N = 0 @@ -287,7 +294,7 @@ def convmtx(V, n): [nr, nc] = V.shape V = V.flatten() - c = np.hstack((V, np.zeros((n - 1)))) + c = np.hstack((V, np.zeros(n - 1))) r = np.zeros(n) m = len(c) x_left = r[n:0:-1] # reverse order from n to 2 in original code @@ -336,7 +343,7 @@ def pca(cov, max_comps=None, thresh=0): """ if thresh is not None and (thresh > 1 or thresh < 0): - raise ValueError('Threshold must be between 0 and 1 (or None).') + raise ValueError("Threshold must be between 0 and 1 (or None).") d, V = linalg.eigh(cov) d = d.real @@ -365,13 +372,13 @@ def pca(cov, max_comps=None, thresh=0): var = 100 * d.sum() / p0 if var < 99: - print('[PCA] Explained variance of selected components : {:.2f}%'. + print("[PCA] Explained variance of selected components : {:.2f}%". format(var)) return V, d -def regcov(Cxy, Cyy, keep=np.array([]), threshold=np.array([])): +def regcov(Cxy, Cyy, keep=None, threshold=0): """Compute regression matrix from cross covariance. Parameters @@ -381,9 +388,10 @@ def regcov(Cxy, Cyy, keep=np.array([]), threshold=np.array([])): Cyy : array Covariance matrix of regressor. keep : array - Number of regressor PCs to keep (default=all). + Number of regressor PCs to keep (default=None, which keeps all). threshold : float - Eigenvalue threshold for discarding regressor PCs (default=0). + Eigenvalue threshold for discarding regressor PCs (default=0, which keeps all + components). Returns ------- @@ -447,7 +455,7 @@ def nonlinear_eigenspace(L, k, alpha=1): from pymanopt.optimizers import TrustRegions n = L.shape[0] - assert L.shape[1] == n, 'L must be square.' + assert L.shape[1] == n, "L must be square." # Grassmann manifold description manifold = Grassmann(n, k) @@ -483,7 +491,7 @@ def ehess(X, U): # Initialization as suggested in above referenced paper. # randomly generate starting point for svd - x = np.random.randn(n, k) + x = rng.standard_normal((n, k)) [U, S, V] = linalg.svd(x, full_matrices=False) x = U.dot(V.T) S0, U0 = linalg.eig( diff --git a/meegkit/utils/denoise.py b/meegkit/utils/denoise.py index 92ed6321..4bb91de2 100644 --- a/meegkit/utils/denoise.py +++ b/meegkit/utils/denoise.py @@ -1,10 +1,9 @@ """Denoising utilities.""" import matplotlib.pyplot as plt import numpy as np - from matplotlib import gridspec -from .matrix import fold, theshapeof, unfold, _check_weights +from .matrix import _check_weights, fold, theshapeof, unfold def demean(X, weights=None, return_mean=False, inplace=False): @@ -40,15 +39,15 @@ def demean(X, weights=None, return_mean=False, inplace=False): weights = unfold(weights) if weights.shape[0] != X.shape[0]: - raise ValueError('X and weights arrays should have same ' + - 'number of samples (rows).') + raise ValueError("X and weights arrays should have same " + + "number of samples (rows).") if weights.shape[1] == 1 or weights.shape[1] == n_chans: mn = (np.sum(X * weights, axis=0) / np.sum(weights, axis=0))[None, :] else: - raise ValueError('Weight array should have either the same ' + - 'number of columns as X array, or 1 column.') + raise ValueError("Weight array should have either the same " + + "number of columns as X array, or 1 column.") else: mn = np.mean(X, axis=0, keepdims=True) @@ -92,7 +91,7 @@ def mean_over_trials(X, weights=None): weights = fold(weights, n_samples) # Take weighted average - with np.errstate(divide='ignore', invalid='ignore'): + with np.errstate(divide="ignore", invalid="ignore"): y = np.sum(X, -1) / np.sum(weights, -1) tw = np.mean(weights, -1) y = np.nan_to_num(y) @@ -179,7 +178,7 @@ def find_outlier_trials(X, thresh=None, show=True): thresh = [thresh] if X.ndim > 3: - raise ValueError('X should be 2D or 3D') + raise ValueError("X should be 2D or 3D") elif X.ndim == 3: n_samples, n_chans, n_trials = theshapeof(X) X = np.reshape(X, (n_samples * n_chans, n_trials)) @@ -196,27 +195,27 @@ def find_outlier_trials(X, thresh=None, show=True): if show: plt.figure(figsize=(7, 4)) gs = gridspec.GridSpec(1, 2) - plt.suptitle('Outlier trial detection') + plt.suptitle("Outlier trial detection") # Before ax1 = plt.subplot(gs[0, 0]) - ax1.plot(d, ls='-') + ax1.plot(d, ls="-") ax1.plot(np.setdiff1d(np.arange(n_trials), idx), - d[np.setdiff1d(np.arange(n_trials), idx)], color='r', ls=' ', - marker='.') - ax1.axhline(y=thresh[0], color='grey', linestyle=':') - ax1.set_xlabel('Trial #') - ax1.set_ylabel('Normalized deviation from mean') - ax1.set_title('Before, ' + str(len(d)), fontsize=10) + d[np.setdiff1d(np.arange(n_trials), idx)], color="r", ls=" ", + marker=".") + ax1.axhline(y=thresh[0], color="grey", linestyle=":") + ax1.set_xlabel("Trial #") + ax1.set_ylabel("Normalized deviation from mean") + ax1.set_title("Before, " + str(len(d)), fontsize=10) ax1.set_xlim(0, len(d) + 1) plt.draw() # After ax2 = plt.subplot(gs[0, 1]) _, dd = find_outlier_trials(X[:, idx], None, False) - ax2.plot(dd, ls='-') - ax2.set_xlabel('Trial #') - ax2.set_title('After, ' + str(len(idx)), fontsize=10) + ax2.plot(dd, ls="-") + ax2.set_xlabel("Trial #") + ax2.set_title("After, " + str(len(idx)), fontsize=10) ax2.yaxis.tick_right() ax2.set_xlim(0, len(idx) + 1) plt.show() diff --git a/meegkit/utils/matrix.py b/meegkit/utils/matrix.py index e186b095..4c4c733e 100644 --- a/meegkit/utils/matrix.py +++ b/meegkit/utils/matrix.py @@ -100,7 +100,7 @@ def widen_mask(mask, widen=4, axis=0): dtype = mask.dtype if axis > dims - 1: - raise AttributeError('Invalid `axis` value.') + raise AttributeError("Invalid `axis` value.") if widen < 0: # This places the desired axis at the front of the shape tuple, then @@ -188,7 +188,7 @@ def relshift(X, ref, shifts, fill_value=0, axis=0): ref = _check_data(ref) if X.shape[0] != ref.shape[0]: - raise AttributeError('X and ref must have same n_times') + raise AttributeError("X and ref must have same n_times") # First we delay X y = multishift(X, shifts=shifts, axis=axis, fill_value=fill_value) @@ -209,7 +209,7 @@ def relshift(X, ref, shifts, fill_value=0, axis=0): def multishift(X, shifts, fill_value=0, axis=0, keep_dims=False, - reshape=False, solution='full'): + reshape=False, solution="full"): """Apply several shifts along specified axis. If `shifts` has multiple values, the output will contain one shift per @@ -268,7 +268,7 @@ def multishift(X, shifts, fill_value=0, axis=0, keep_dims=False, if n_shifts == 1 and not keep_dims: y = np.squeeze(y, axis=-1) - if solution == 'valid': + if solution == "valid": max_neg_shift = np.abs(np.min(np.min(shifts), 0)) max_pos_shift = np.max((np.max(shifts), 0)) y = y[max_pos_shift:-max_neg_shift, ...] @@ -349,7 +349,7 @@ def shift(X, shift, fill_value=0, axis=0): """ if not np.equal(np.mod(shift, 1), 0): - raise AttributeError('shift must be a single int') + raise AttributeError("shift must be a single int") # reallocate empty array and assign slice. y = np.empty_like(X) @@ -382,7 +382,7 @@ def shift(X, shift, fill_value=0, axis=0): y[..., :shift] = X[..., -shift:] else: - raise NotImplementedError('Axis must be 0, 1 or -1.') + raise NotImplementedError("Axis must be 0, 1 or -1.") return y @@ -499,7 +499,7 @@ def fold(X, epoch_size): if X.ndim == 1: X = X[:, np.newaxis] if X.ndim > 2: - raise AttributeError('X must be 2D at most') + raise AttributeError("X must be 2D at most") nt = X.shape[0] // epoch_size nc = X.shape[1] @@ -579,7 +579,7 @@ def normcol(X, weights=None, return_norm=False): n_samples, n_chans, n_trials = theshapeof(X) weights = _check_weights(weights, X) if not weights.any(): - with np.errstate(divide='ignore'): + with np.errstate(divide="ignore"): N = ((np.sum(X ** 2, axis=0) / n_samples) ** -0.5)[np.newaxis] N[np.isinf(N)] = 0 @@ -588,12 +588,12 @@ def normcol(X, weights=None, return_norm=False): else: if weights.shape[0] != X.shape[0]: - raise ValueError('Weight array should have same number of ' + - 'columns as X') + raise ValueError("Weight array should have same number of " + + "columns as X") if weights.shape[1] == 1: weights = np.tile(weights, (1, n_chans)) if weights.shape != X.shape: - raise ValueError('Weight array should have be same shape as X') + raise ValueError("Weight array should have be same shape as X") N = (np.sum(X ** 2 * weights, axis=0) / np.sum(weights, axis=0)) ** -0.5 @@ -623,14 +623,14 @@ def matmul3d(X, mixin): Projection. """ - assert mixin.ndim == 2, 'mixing matrix must be 2D' + assert mixin.ndim == 2, "mixing matrix must be 2D" if X.ndim == 2: return X @ mixin elif X.ndim == 3: - return np.einsum('sct,ck->skt', X, mixin) + return np.einsum("sct,ck->skt", X, mixin) else: - raise RuntimeError('X must be (n_samples, n_chans, n_trials)') + raise RuntimeError("X must be (n_samples, n_chans, n_trials)") def _check_shifts(shifts, allow_floats=False): @@ -639,7 +639,7 @@ def _check_shifts(shifts, allow_floats=False): if allow_floats: types += (float, np.float_) if not isinstance(shifts, (np.ndarray, list, type(None)) + types): - raise AttributeError('shifts should be a list, an array or an int') + raise AttributeError("shifts should be a list, an array or an int") if isinstance(shifts, (list, ) + types): shifts = np.array(shifts).flatten() if shifts is None or len(shifts) == 0: @@ -653,12 +653,12 @@ def _check_shifts(shifts, allow_floats=False): def _check_data(X): """Check data is numpy array and has the proper dimensions.""" if not isinstance(X, (np.ndarray, list)): - raise AttributeError('data should be a list or a numpy array') + raise AttributeError("data should be a list or a numpy array") dtype = np.complex128 if np.any(np.iscomplex(X)) else np.float64 X = np.asanyarray(X, dtype=dtype) if X.ndim > 3: - raise ValueError('Data must be 3D at most') + raise ValueError("Data must be 3D at most") return X @@ -667,7 +667,7 @@ def _check_weights(weights, X): """Check weights dimensions against X.""" if not isinstance(weights, (np.ndarray, list)): if weights is not None: - warnings.warn('weights should be a list or a numpy array.') + warnings.warn("weights should be a list or a numpy array.") weights = np.array([]) weights = np.asanyarray(weights) @@ -675,7 +675,7 @@ def _check_weights(weights, X): dtype = np.complex128 if np.any(np.iscomplex(weights)) else np.float64 weights = np.asanyarray(weights, dtype=dtype) if weights.ndim > 3: - raise ValueError('Weights must be 3D at most') + raise ValueError("Weights must be 3D at most") if weights.shape[0] != X.shape[0]: raise ValueError("Weights should be the same n_times as X.") @@ -695,7 +695,7 @@ def _check_weights(weights, X): raise ValueError("Weights array should have a single column.") if np.any(np.abs(weights) > 1.): - warnings.warn('weights should be between 0 and 1.') + warnings.warn("weights should be between 0 and 1.") weights[np.abs(weights) > 1.] = 1. return weights @@ -706,18 +706,18 @@ def _times_to_delays(lags, sfreq): if lags is None: return np.array([0]) if not isinstance(sfreq, (int, float, np.int_)): - raise ValueError('`sfreq` must be an integer or float') + raise ValueError("`sfreq` must be an integer or float") sfreq = float(sfreq) if not all([isinstance(ii, (int, float, np.int_)) for ii in lags]): - raise ValueError('lags must be an integer or float') + raise ValueError("lags must be an integer or float") if len(lags) == 2 and sfreq != 1: tmin = lags[0] tmax = lags[1] if not tmin <= tmax: - raise ValueError('tmin must be <= tmax') + raise ValueError("tmin must be <= tmax") # Convert seconds to samples delays = np.arange(int(np.round(tmin * sfreq)), diff --git a/meegkit/utils/sig.py b/meegkit/utils/sig.py index ada58d5d..03824517 100644 --- a/meegkit/utils/sig.py +++ b/meegkit/utils/sig.py @@ -8,7 +8,7 @@ def modulation_index(phase, amp, n_bins=18): - u"""Compute the Modulation Index (MI) between two signals. + """Compute the Modulation Index (MI) between two signals. MI is a measure of the amount of phase-amplitude coupling. Phase angles are expected to be in radians [1]_. MI is derived from the Kullbach-Leibner @@ -36,7 +36,7 @@ def modulation_index(phase, amp, n_bins=18): Examples -------- >> phas = np.random.rand(100, 1) * 2 * np.pi - np.pi - >> ampl = np.random.randn(100, 1) * 30 + 100 + >> ampl = rng.standard_normal((100, 1) * 30 + 100 >> MI, KL = modulation_index(phas, ampl) Notes @@ -78,7 +78,7 @@ def modulation_index(phase, amp, n_bins=18): phase = phase.squeeze() amp = amp.squeeze() if phase.shape != amp.shape or phase.ndims > 1 or amp.ndims: - raise AttributeError('Inputs must be 1D vectors of same length.') + raise AttributeError("Inputs must be 1D vectors of same length.") # Convert phase to degrees phasedeg = np.degrees(phase) @@ -111,7 +111,7 @@ def modulation_index(phase, amp, n_bins=18): return MI, KL -def smooth(x, window_len, window='square', axis=0, align='left'): +def smooth(x, window_len, window="square", axis=0, align="left"): """Smooth a signal using a window with requested size along a given axis. This method is based on the convolution of a scaled window with the signal. @@ -160,35 +160,35 @@ def smooth(x, window_len, window='square', axis=0, align='left'): """ if x.shape[axis] < window_len: - raise ValueError('Input vector needs to be bigger than window size.') - if window not in ['square', 'hanning', 'hamming', 'bartlett', 'blackman']: - raise ValueError('Unknown window type.') + raise ValueError("Input vector needs to be bigger than window size.") + if window not in ["square", "hanning", "hamming", "bartlett", "blackman"]: + raise ValueError("Unknown window type.") if window_len == 0: - raise ValueError('Smoothing kernel must be at least 1 sample wide') + raise ValueError("Smoothing kernel must be at least 1 sample wide") if window_len == 1: return x - def _smooth1d(x, n, align='left'): + def _smooth1d(x, n, align="left"): if x.ndim != 1: - raise ValueError('Smooth only accepts 1D arrays') + raise ValueError("Smooth only accepts 1D arrays") frac, n = np.modf(n) n = int(n) - if window == 'square': # moving average - w = np.ones(n, 'd') + if window == "square": # moving average + w = np.ones(n, "d") w = np.r_[w, frac] else: - w = eval('np.' + window + '(n)') + w = eval("np." + window + "(n)") - if align == 'center': + if align == "center": a = x[n - 1:0:-1] b = x[-2:-n - 1:-1] s = np.r_[a, x, b] - out = np.convolve(w / w.sum(), s, mode='same') + out = np.convolve(w / w.sum(), s, mode="same") return out[len(a):-len(b)] - elif align == 'left': + elif align == "left": out = ss.lfilter(w / w.sum(), 1, x) return out @@ -219,7 +219,7 @@ def lowpass_env_filtering(x, cutoff=150., n=1, sfreq=22050): Low-pass filtered signal. """ - b, a = ss.butter(N=n, Wn=cutoff * 2. / sfreq, btype='lowpass') + b, a = ss.butter(N=n, Wn=cutoff * 2. / sfreq, btype="lowpass") return ss.lfilter(b, a, x) @@ -261,7 +261,7 @@ def spectral_envelope(x, sfreq, lowpass=32): """ x = np.squeeze(x) if x.ndim > 1: - raise AttributeError('x must be 1D') + raise AttributeError("x must be 1D") if lowpass is None: lowpass = sfreq / 2 @@ -272,7 +272,7 @@ def spectral_envelope(x, sfreq, lowpass=32): s = np.r_[a, x, b] # Convolve squared signal with a square window and take cubic root - y = np.convolve(s ** 2, np.ones((win,)) / win, mode='same') ** (1 / 3) + y = np.convolve(s ** 2, np.ones((win,)) / win, mode="same") ** (1 / 3) return y[len(a):-len(b)] @@ -314,16 +314,16 @@ def gaussfilt(data, srate, f, fwhm, n_harm=1, shift=0, return_empvals=False, """ # input check assert (data.shape[1] <= data.shape[0] - ), 'n_channels must be less than n_samples' - assert ((f - fwhm) >= 0), 'increase frequency or decrease FWHM' - assert (fwhm >= 0), 'FWHM must be greater than 0' + ), "n_channels must be less than n_samples" + assert ((f - fwhm) >= 0), "increase frequency or decrease FWHM" + assert (fwhm >= 0), "FWHM must be greater than 0" # frequencies hz = np.fft.fftfreq(data.shape[0], 1. / srate) empVals = np.zeros((2,)) # compute empirical frequency and standard deviation - idx_p = np.searchsorted(hz[hz >= 0], f, 'left') + idx_p = np.searchsorted(hz[hz >= 0], f, "left") # create Gaussian fx = np.zeros_like(hz) @@ -363,15 +363,15 @@ def gaussfilt(data, srate, f, fwhm, n_harm=1, shift=0, return_empvals=False, # inspect the Gaussian (turned off by default) import matplotlib.pyplot as plt plt.figure(1) - plt.plot(hz, fx, 'o-') + plt.plot(hz, fx, "o-") plt.xlim([0, None]) - title = 'Requested: {}, {} Hz\nEmpirical: {}, {} Hz'.format( + title = "Requested: {}, {} Hz\nEmpirical: {}, {} Hz".format( f, fwhm, empVals[0], empVals[1] ) plt.title(title) - plt.xlabel('Frequency (Hz)') - plt.ylabel('Amplitude gain') + plt.xlabel("Frequency (Hz)") + plt.ylabel("Amplitude gain") plt.show() if return_empvals: @@ -524,7 +524,7 @@ def stmcb(x, u_in=None, q=None, p=None, niter=5, a_in=None): a = a_in N = len(x) - for i in range(niter): + for _i in range(niter): u = lfilter([1], a, x) v = lfilter([1], a, u_in) C1 = convmtx(u, (p + 1)).T diff --git a/meegkit/utils/stats.py b/meegkit/utils/stats.py index ba9cdfad..830c6571 100644 --- a/meegkit/utils/stats.py +++ b/meegkit/utils/stats.py @@ -1,5 +1,4 @@ """Statistics utilities.""" -from __future__ import division, print_function import numpy as np @@ -10,6 +9,8 @@ except ImportError: mne = None +rng = np.random.default_rng() + def rms(X, axis=0): """Root-mean-square along given axis.""" @@ -62,11 +63,11 @@ def rolling_corr(X, y, window=None, sfreq=1, step=1, axis=0): if y.ndim == 3: y = np.squeeze(y) if X.ndim > 3: - raise AttributeError('Data must be 2D or 3D.') + raise AttributeError("Data must be 2D or 3D.") if y.shape[0] != X.shape[0]: - raise AttributeError('X and y must share the same time axis.') + raise AttributeError("X and y must share the same time axis.") if y.ndim > 2: - raise AttributeError('y must be at most 2D.') + raise AttributeError("y must be at most 2D.") n_times, n_chans, n_epochs = theshapeof(X) timebins = np.arange(n_times - window, 0, -step)[::-1] @@ -116,15 +117,13 @@ def bootstrap_ci(X, n_bootstrap=2000, ci=(5, 95), axis=-1): Confidence intervals. """ - n_samples, n_chans, n_trials = theshapeof(X) idx = np.arange(X.shape[axis], dtype=int) - shape = list(X.shape) shape.pop(axis) - bootstraps = np.nan * np.ones(((n_bootstrap,) + tuple(shape))) + bootstraps = np.nan * np.ones((n_bootstrap,) + tuple(shape)) for i in range(n_bootstrap): - temp_idx = np.random.choice(idx, replace=True, size=len(idx)) + temp_idx = rng.choice(idx, replace=True, size=len(idx)) bootstraps[i] = np.mean(np.take(X, temp_idx, axis=axis), axis=axis) ci_low, ci_up = np.percentile(bootstraps, ci, axis=0) @@ -179,14 +178,14 @@ def bootstrap_snr(epochs, n_bootstrap=2000, baseline=None, window=None): gfp_bs = np.empty((n_bootstrap, n_chans, len(epochs.times))) for i in range(n_bootstrap): - bs_indices = np.random.choice(indices, replace=True, size=len(indices)) + bs_indices = rng.choice(indices, replace=True, size=len(indices)) erp_bs[i] = np.mean(epochs._data[bs_indices, ...], 0) # Baseline correct mean waveform if baseline: erp_bs[i] = mne.baseline.rescale(erp_bs[i], epochs.times, baseline=baseline, - verbose='ERROR') + verbose="ERROR") # Rectify waveform gfp_bs[i] = np.sqrt(erp_bs[i] ** 2) @@ -271,7 +270,7 @@ def cronbach(epochs, K=None, n_bootstrap=2000, tmin=None, tmax=None): alpha = np.empty((n_bootstrap, n_chans)) for b in np.arange(n_bootstrap): # take K trials randomly - idx = np.random.choice(range(n_trials), K) + idx = rng.choice(range(n_trials), K) X = erp[idx, :, tmin:tmax] sigmaY = X.var(axis=2).sum(0) # var over time sigmaX = X.sum(axis=0).var(-1) # var of average @@ -329,8 +328,8 @@ def snr_spectrum(X, freqs, n_avg=1, n_harm=1, skipbins=1): n_freqs = X.shape[0] n_chans = X.shape[1] else: - raise ValueError('Data must have shape (n_freqs, n_chans, [n_trials,])' - f', got {X.shape}') + raise ValueError("Data must have shape (n_freqs, n_chans, [n_trials,])" + f", got {X.shape}") # Number of points to get desired resolution X = np.reshape(X, (n_freqs, n_chans * n_trials)) @@ -385,7 +384,7 @@ def snr_spectrum(X, freqs, n_avg=1, n_harm=1, skipbins=1): B[h] = np.mean(X[bin_noise[h], i_trial].flatten() ** 2) # Ratio - with np.errstate(divide='ignore', invalid='ignore'): + with np.errstate(divide="ignore", invalid="ignore"): SNR[i_bin, i_trial] = np.sqrt(A) / np.sqrt(B) del A diff --git a/meegkit/utils/testing.py b/meegkit/utils/testing.py index 008f616c..e715028e 100644 --- a/meegkit/utils/testing.py +++ b/meegkit/utils/testing.py @@ -1,8 +1,8 @@ """Synthetic test data.""" +import matplotlib.pyplot as plt import numpy as np -from meegkit.utils import fold, rms, unfold -import matplotlib.pyplot as plt +from meegkit.utils import fold, rms, unfold def create_line_data(n_samples=100 * 3, n_chans=30, n_trials=100, noise_dim=20, @@ -63,9 +63,9 @@ def create_line_data(n_samples=100 * 3, n_chans=30, n_trials=100, noise_dim=20, if show: f, ax = plt.subplots(3) - ax[0].plot(source.mean(-1), label='source') - ax[1].plot(noise[:, 1].mean(-1), label='noise (avg over trials)') - ax[2].plot(data[:, 1].mean(-1), label='mixture (avg over trials)') + ax[0].plot(source.mean(-1), label="source") + ax[1].plot(noise[:, 1].mean(-1), label="noise (avg over trials)") + ax[2].plot(data[:, 1].mean(-1), label="mixture (avg over trials)") ax[0].legend() ax[1].legend() ax[2].legend() diff --git a/meegkit/utils/trca.py b/meegkit/utils/trca.py index cb25adde..849a98ab 100644 --- a/meegkit/utils/trca.py +++ b/meegkit/utils/trca.py @@ -1,8 +1,7 @@ """TRCA utils.""" import numpy as np - -from scipy.signal import filtfilt, cheb1ord, cheby1 from scipy import stats +from scipy.signal import cheb1ord, cheby1, filtfilt def round_half_up(num, decimals=0): @@ -91,10 +90,10 @@ def itr(n, p, t): itr = 0 if (p < 0 or 1 < p): - raise ValueError('Accuracy need to be between 0 and 1.') + raise ValueError("Accuracy need to be between 0 and 1.") elif (p < 1 / n): itr = 0 - raise ValueError('ITR might be incorrect because accuracy < chance') + raise ValueError("ITR might be incorrect because accuracy < chance") elif (p == 1): itr = np.log2(n) * 60 / t else: @@ -137,7 +136,7 @@ def bandpass(eeg, sfreq, Wp, Ws): # the arguments 'axis=0, padtype='odd', padlen=3*(max(len(B),len(A))-1)' # correspond to Matlab filtfilt : https://dsp.stackexchange.com/a/47945 - y = filtfilt(B, A, eeg, axis=0, padtype='odd', + y = filtfilt(B, A, eeg, axis=0, padtype="odd", padlen=3 * (max(len(B), len(A)) - 1)) return y diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..0301fb52 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,137 @@ +# As per https://github.com/pypa/setuptools/blob/main/docs/userguide/quickstart.rst +################################## +# Project # +################################## + +[project] +name = "meegkit" +authors = [ + {name = "Nicolas Barascud", email = "nicolas.barascud@gmail.com"}, +] +license = {text = "BSD (3-clause)"} +dynamic = ["version", "dependencies"] +description = "M/EEG denoising in Python" +readme = {file = "README.md", content-type = "text/markdown"} +requires-python = ">=3.8" + +[project.urls] +repository = "https://github.com/nbara/python-meegkit" +documentation = "https://nbara.github.io/python-meegkit/" +tracker = "https://github.com/nbara/python-meegkit/issues/" + +[project.optional-dependencies] +extra = ["pymanopt"] +docs = ["sphinx", "sphinx-gallery", "sphinx-bootstrap_theme", "sphinx-copybutton", + "sphinxemoji", "numpydoc", "pydata-sphinx-theme", "pillow", "jupyter-sphinx", + "ghp-import", "meegkit[extra]"] +tests = ["pytest", "pytest-cov", "codecov", "codespell", "ruff", "meegkit[extra]"] + +################################## +# Package building # +################################## + +[build-system] +requires = ["setuptools>=62.0.0", "wheel", "pybind11~=2.10.3"] +build-backend = "setuptools.build_meta" + +[tool.setuptools] +zip-safe = false +include-package-data = true + +[tool.setuptools.dynamic] +version = {attr = "meegkit.__version__"} +dependencies = {file = ["requirements.txt"]} + +[tool.setuptools.packages.find] +exclude = ["tests*", "examples*", "doc*"] + +################################## +# Codespell # +################################## + +[tool.codespell] +skip = """*.html,*.fif,*.eve,*.gz,*.tgz,*.zip,*.mat,*.stc, + *.label,*.w,*.bz2,*.annot,*.sulc,*.log,*.local-copy, + *.orig_avg,*.inflated_avg,*.gii,*.pyc,*.doctree,*.pickle, + *.inv,*.png,*.edf,*.touch,*.thickness,*.nofix,*.volume, + *.defect_borders,*.mgh,lh.*,rh.*,COR-*,*.examples,.xdebug_mris_calc + ,bad.segments,BadChannels,*.hist,empty_file,*.orig,*.js,*.map,*.pdf, + *.ipynb,searchindex.dat,*.c""" +ignore-words-list = "hist,dof,datas,mot" +quiet-level = 3 +interactive = 0 +write-changes = false + +################################## +# Linter configuration # +################################## +[tool.ruff] +select = ["D", "E", "F", "B", "Q", "NPY", "I", "ICN", "UP"] +line-length = 90 +target-version = "py310" +ignore-init-module-imports = true +ignore = ["E731", "B006", "B028", "UP038", "D100", "D105", "D212"] + +[tool.ruff.per-file-ignores] +"__init__.py" = ["F401"] +"test_*.py" = ["D101", "D102", "D103", "D"] +"example_*.py" = ["D205", "D400", "D212"] + +[tool.ruff.pydocstyle] +convention = "numpy" + +################################## +# Pytest, Coverage # +################################## + +[tool.pytest.ini_options] +timeout = 1200 +testpaths = ["tests/"] +filterwarnings = [ + "ignore:Call to deprecated create function FieldDescriptor", + "ignore:Call to deprecated create function Descriptor", + "ignore:Call to deprecated create function EnumDescriptor", + "ignore:Call to deprecated create function EnumValueDescriptor", + "ignore:Call to deprecated create function FileDescriptor", + "ignore:Call to deprecated create function OneofDescriptor" +] +addopts = """ + --color=yes + --durations 10 + """ + +[tool.coverage.run] +branch = true +data_file = "build/reports/coverage/.meegkit" +omit = [ + "*/python?.?/*", + "*/site-packages/pytest/*", + "*/setup.py", + "*/tests/*", + "*/examples/*", +] + +[tool.coverage.report] +skip_covered = true +skip_empty = true +exclude_lines = [ + "pragma: no cover", + "def __repr__", + "raise AssertionError", + "raise NotImplementedError", + "if __name__ == .__main__.:" +] + +[tool.coverage.html] +directory = "build/reports/coverage/html" + +[tool.coverage.xml] +output = "build/reports/coverage/meegkit.xml" + +################################## +# Documentation # +################################## +[tool.sphinx.build] +source-dir = "doc/" +build-dir = "doc/_build" +all_files = 1 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 748a351d..00000000 --- a/setup.cfg +++ /dev/null @@ -1,24 +0,0 @@ -[flake8] -exclude = __init__.py,*externals*,constants.py,fixes.py -ignore = E241,E305,W504 - -[pydocstyle] -convention = pep257 -match_dir = ^(?!\.|doc|tutorials|tests|examples).*$ -match = (?!test_|fixes).*\.py -add-ignore = D100,D107,D413 -add-select = D214,D215,D404,D405,D406,D407,D408,D409,D410,D411 -ignore-decorators = ^(copy_.*_doc_to_|on_trait_change|cached_property|deprecated|property|.*setter).* - -[build_sphinx] -source-dir = doc/ -build-dir = doc/_build -all_files = 1 - -[upload_sphinx] -upload-dir = doc/_build/html - -[options.extras_require] -extra = pymanopt -docs = sphinx;sphinx-gallery;sphinx-bootstrap_theme;sphinx-copybutton;sphinxemoji;numpydoc;pydata-sphinx-theme;pillow;jupyter-sphinx;ghp-import;meegkit[extra] -tests = pytest;pytest-cov;codecov;codespell;flake8;pydocstyle;meegkit[extra] diff --git a/setup.py b/setup.py index 66737f48..8782e952 100644 --- a/setup.py +++ b/setup.py @@ -1,28 +1,5 @@ #! /usr/bin/env python # -from setuptools import setup, find_packages +from setuptools import setup -with open("README.md", "r", encoding="utf8") as fid: - long_description = fid.read() - -setup( - name='meegkit', - description='M/EEG denoising in Python', - long_description=long_description, - long_description_content_type="text/markdown", - url='http://github.com/nbara/python-meegkit/', - author='Nicolas Barascud', - author_email='nicolas.barascud@gmail.com', - license='BSD (3-clause)', - version='0.1.3', - packages=find_packages(exclude=['doc', 'tests']), - project_urls={ - "Documentation": "https://nbara.github.io/python-meegkit/", - "Source": "https://github.com/nbara/python-meegkit/", - "Tracker": "https://github.com/nbara/python-meegkit/issues/", - }, - platforms="any", - python_requires=">=3.8", - install_requires=["numpy", "scipy", "scikit-learn", "joblib", "pandas", - "matplotlib", "tqdm", "pyriemann", "statsmodels"], - zip_safe=False) +setup() diff --git a/tests/conftest.py b/tests/conftest.py index 0b54abf0..0ab9b351 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,6 +1,5 @@ -import pytest - import matplotlib.pyplot as plt +import pytest def pytest_addoption(parser): @@ -22,7 +21,7 @@ def pytest_addoption(parser): def pytest_collection_modifyitems(config, items): """Do not skip slow test if option provided.""" if config.getoption("--noplots"): - plt.switch_backend('agg') + plt.switch_backend("agg") if config.getoption("--runslow"): # --runslow given in cli: do not skip slow tests diff --git a/tests/test_asr.py b/tests/test_asr.py index d698cad6..f213939d 100644 --- a/tests/test_asr.py +++ b/tests/test_asr.py @@ -4,10 +4,11 @@ import matplotlib.pyplot as plt import numpy as np import pytest +from scipy import signal + from meegkit.asr import ASR, asr_calibrate, asr_process, clean_windows from meegkit.utils.asr import yulewalk, yulewalk_filter from meegkit.utils.matrix import sliding_window -from scipy import signal # Data files THIS_FOLDER = os.path.dirname(os.path.abspath(__file__)) @@ -18,9 +19,10 @@ # raw.crop(0, 60) # keep 60s only # raw.pick_types(eeg=True, misc=False) # raw = raw._data +rng = np.random.default_rng(9) -@pytest.mark.parametrize(argnames='sfreq', argvalues=(125, 250, 256, 2048)) +@pytest.mark.parametrize(argnames="sfreq", argvalues=(125, 250, 256, 2048)) def test_yulewalk(sfreq, show=False): """Test that my version of yulewelk works just like MATLAB's.""" # Temp fix, values are computed in matlab using yulewalk.m @@ -53,7 +55,7 @@ def test_yulewalk(sfreq, show=False): -132.920238664871, 158.567177443427, -121.909488069062, 58.9853908881204, -16.4212688404351, 2.01391570212326] else: - raise AttributeError('Currently sfreq must be 250, 256 or 2048...') + raise AttributeError("Currently sfreq must be 250, 256 or 2048...") # Theoretical values w0, h0 = signal.freqz(b, a, sfreq) @@ -68,12 +70,12 @@ def test_yulewalk(sfreq, show=False): if show: fig = plt.figure() ax = fig.add_subplot(111) - ax.plot(w0 / np.pi, np.abs(h0), label='matlab') - ax.plot(w1 / np.pi, np.abs(h1), ':', label='mine') - ax.set_title('Filter frequency response') - ax.set_xlabel('Frequency [radians / second]') - ax.set_ylabel('Amplitude [dB]') - ax.grid(which='both', axis='both') + ax.plot(w0 / np.pi, np.abs(h0), label="matlab") + ax.plot(w1 / np.pi, np.abs(h1), ":", label="mine") + ax.set_title("Filter frequency response") + ax.set_xlabel("Frequency [radians / second]") + ax.set_ylabel("Amplitude [dB]") + ax.grid(which="both", axis="both") ax.legend() # plt.show() @@ -86,48 +88,48 @@ def test_yulewalk(sfreq, show=False): if show: plt.figure() - plt.plot(f, m, label='ideal') - plt.plot(w / np.pi, np.abs(h), '--', label='yw designed') + plt.plot(f, m, label="ideal") + plt.plot(w / np.pi, np.abs(h), "--", label="yw designed") plt.legend() - plt.title('Comparison of Frequency Response Magnitudes') + plt.title("Comparison of Frequency Response Magnitudes") plt.legend() plt.show() -@pytest.mark.parametrize(argnames='n_chans', argvalues=(4, 8, 12)) +@pytest.mark.parametrize(argnames="n_chans", argvalues=(4, 8, 12)) def test_yulewalk_filter(n_chans, show=False): """Test yulewalk filter.""" - raw = np.load(os.path.join(THIS_FOLDER, 'data', 'eeg_raw.npy')) + raw = np.load(os.path.join(THIS_FOLDER, "data", "eeg_raw.npy")) sfreq = 250 n_chan_orig = raw.shape[0] - raw = np.random.randn(n_chans, n_chan_orig) @ raw + raw = rng.standard_normal((n_chans, n_chan_orig)) @ raw raw_filt, iirstate = yulewalk_filter(raw, sfreq) if show: f, ax = plt.subplots(n_chans, sharex=True, figsize=(8, 5)) for i in range(n_chans): - ax[i].plot(raw[i], lw=.5, label='before') - ax[i].plot(raw_filt[i], label='after', lw=.5) + ax[i].plot(raw[i], lw=.5, label="before") + ax[i].plot(raw_filt[i], label="after", lw=.5) ax[i].set_ylim([-50, 50]) if i < n_chans - 1: ax[i].set_yticks([]) - ax[i].set_xlabel('Time (s)') - ax[i].set_ylabel(f'ch{i}') - ax[0].legend(fontsize='small', bbox_to_anchor=(1.04, 1), + ax[i].set_xlabel("Time (s)") + ax[i].set_ylabel(f"ch{i}") + ax[0].legend(fontsize="small", bbox_to_anchor=(1.04, 1), borderaxespad=0) plt.subplots_adjust(hspace=0, right=0.75) - plt.suptitle('Before/after filter') + plt.suptitle("Before/after filter") plt.show() -def test_asr_functions(show=False, method='riemann'): +def test_asr_functions(show=False, method="riemann"): """Test ASR functions (offline use). Note: this will not be optimal since the filter parameters will be estimated only once and not updated online as is intended. """ - raw = np.load(os.path.join(THIS_FOLDER, 'data', 'eeg_raw.npy')) + raw = np.load(os.path.join(THIS_FOLDER, "data", "eeg_raw.npy")) sfreq = 250 raw_filt = raw.copy() raw_filt, iirstate = yulewalk_filter(raw_filt, sfreq) @@ -147,34 +149,33 @@ def test_asr_functions(show=False, method='riemann'): if show: f, ax = plt.subplots(8, sharex=True, figsize=(8, 5)) for i in range(8): - ax[i].fill_between(train_idx, 0, 1, color='grey', alpha=.3, + ax[i].fill_between(train_idx, 0, 1, color="grey", alpha=.3, transform=ax[i].get_xaxis_transform(), - label='calibration window') + label="calibration window") ax[i].fill_between(train_idx, 0, 1, where=sample_mask.flat, transform=ax[i].get_xaxis_transform(), - facecolor='none', hatch='...', edgecolor='k', - label='selected window') - ax[i].plot(raw[i], lw=.5, label='before ASR') - ax[i].plot(clean[i], label='after ASR', lw=.5) + facecolor="none", hatch="...", edgecolor="k", + label="selected window") + ax[i].plot(raw[i], lw=.5, label="before ASR") + ax[i].plot(clean[i], label="after ASR", lw=.5) # ax[i].set_xlim([10, 50]) ax[i].set_ylim([-50, 50]) # ax[i].set_ylabel(raw.ch_names[i]) if i < 7: ax[i].set_yticks([]) - ax[i].set_xlabel('Time (s)') - ax[0].legend(fontsize='small', bbox_to_anchor=(1.04, 1), + ax[i].set_xlabel("Time (s)") + ax[0].legend(fontsize="small", bbox_to_anchor=(1.04, 1), borderaxespad=0) plt.subplots_adjust(hspace=0, right=0.75) - plt.suptitle('Before/after ASR') + plt.suptitle("Before/after ASR") plt.show() -@pytest.mark.parametrize(argnames='method', argvalues=('riemann', 'euclid')) -@pytest.mark.parametrize(argnames='reref', argvalues=(False, True)) +@pytest.mark.parametrize(argnames="method", argvalues=("riemann", "euclid")) +@pytest.mark.parametrize(argnames="reref", argvalues=(False, True)) def test_asr_class(method, reref, show=False): """Test ASR class (simulate online use).""" - np.random.default_rng(9) - raw = np.load(os.path.join(THIS_FOLDER, 'data', 'eeg_raw.npy')) + raw = np.load(os.path.join(THIS_FOLDER, "data", "eeg_raw.npy")) sfreq = 250 # Train on a clean portion of data train_idx = np.arange(5 * sfreq, 45 * sfreq, dtype=int) @@ -187,15 +188,15 @@ def test_asr_class(method, reref, show=False): raw2 = raw.copy() if reref: - if method == 'riemann': - with pytest.raises(ValueError, match='Add regularization'): - blah = ASR(method=method, estimator='scm') + if method == "riemann": + with pytest.raises(ValueError, match="Add regularization"): + blah = ASR(method=method, estimator="scm") blah.fit(raw2[:, train_idx]) - asr = ASR(method=method, estimator='lwf') + asr = ASR(method=method, estimator="lwf") asr.fit(raw2[:, train_idx]) else: - asr = ASR(method=method, estimator='scm') + asr = ASR(method=method, estimator="scm") asr.fit(raw2[:, train_idx]) # Split into small windows @@ -219,27 +220,27 @@ def test_asr_class(method, reref, show=False): if show: f, ax = plt.subplots(8, sharex=True, figsize=(8, 5)) for i in range(8): - ax[i].plot(times, X[i], lw=.5, label='before ASR') - ax[i].plot(times, Y[i], label='after ASR', lw=.5) + ax[i].plot(times, X[i], lw=.5, label="before ASR") + ax[i].plot(times, Y[i], label="after ASR", lw=.5) ax[i].set_ylim([-50, 50]) - ax[i].set_ylabel(f'ch{i}') + ax[i].set_ylabel(f"ch{i}") if i < 7: ax[i].set_yticks([]) - ax[i].set_xlabel('Time (s)') - ax[0].legend(fontsize='small', bbox_to_anchor=(1.04, 1), + ax[i].set_xlabel("Time (s)") + ax[0].legend(fontsize="small", bbox_to_anchor=(1.04, 1), borderaxespad=0) plt.subplots_adjust(hspace=0, right=0.75) - plt.suptitle('Before/after ASR') + plt.suptitle("Before/after ASR") f, ax = plt.subplots(8, sharex=True, figsize=(8, 5)) for i in range(8): - ax[i].plot(times, Y[i], label='incremental', lw=.5) - ax[i].plot(times, Y2[i], label='bulk', lw=.5) - ax[i].plot(times, Y[i] - Y2[i], label='difference', lw=.5) + ax[i].plot(times, Y[i], label="incremental", lw=.5) + ax[i].plot(times, Y2[i], label="bulk", lw=.5) + ax[i].plot(times, Y[i] - Y2[i], label="difference", lw=.5) if i < 7: ax[i].set_yticks([]) - ax[i].set_xlabel('Time (s)') - plt.suptitle('incremental vs. bulk difference ') + ax[i].set_xlabel("Time (s)") + plt.suptitle("incremental vs. bulk difference ") plt.show() # TODO: the transform() process is stochastic, so Y and Y2 are not going to diff --git a/tests/test_cca.py b/tests/test_cca.py index 0c469f40..39c684c0 100644 --- a/tests/test_cca.py +++ b/tests/test_cca.py @@ -3,7 +3,7 @@ from scipy.io import loadmat from sklearn.cross_decomposition import CCA -from meegkit.cca import cca_crossvalidate, nt_cca, mcca +from meegkit.cca import cca_crossvalidate, mcca, nt_cca from meegkit.utils import multishift, tscov @@ -14,11 +14,11 @@ def test_cca(): # y = rng.randn(1000, 9) # x = demean(x).squeeze() # y = demean(y).squeeze() - mat = loadmat('./tests/data/ccadata.mat') - x = mat['x'] - y = mat['y'] - A2 = mat['A2'] - B2 = mat['B2'] + mat = loadmat("./tests/data/ccadata.mat") + x = mat["x"] + y = mat["y"] + A2 = mat["A2"] + B2 = mat["B2"] A1, B1, R = nt_cca(x, y) # if mean(A1(:).*A2(:))<0; A2=-A2; end X1 = np.dot(x, A1) @@ -80,9 +80,9 @@ def test_cca2(): def test_cca_scaling(): """Test CCA with MEG data.""" - data = np.load('./tests/data/ccadata_meg_2trials.npz') - raw = data['arr_0'] - env = data['arr_1'] + data = np.load("./tests/data/ccadata_meg_2trials.npz") + raw = data["arr_0"] + env = data["arr_1"] # Test with scaling (unit: fT) A0, B0, R0 = nt_cca(raw * 1e15, env) @@ -138,9 +138,9 @@ def test_correlated(): def test_cca_lags(): """Test multiple lags.""" - mat = loadmat('./tests/data/ccadata.mat') - x = mat['x'] - y = mat['y'] + mat = loadmat("./tests/data/ccadata.mat") + x = mat["x"] + y = mat["y"] y[:, :3] = x[:, :3] lags = np.arange(-10, 11, 1) A1, B1, R1 = nt_cca(x, y, lags) @@ -165,10 +165,10 @@ def test_cca_crossvalidate(): # xx = [x, x, x] # yy = [x[:, :9], y, y] - mat = loadmat('./tests/data/ccadata2.mat') - xx = mat['x'] - yy = mat['y'] - R1 = mat['R'] # no shifts + mat = loadmat("./tests/data/ccadata2.mat") + xx = mat["x"] + yy = mat["y"] + R1 = mat["R"] # no shifts # Test with no shifts A, B, R = cca_crossvalidate(xx, yy) @@ -201,8 +201,8 @@ def test_cca_crossvalidate_shifts(): # uncorrelated y[:, 6:8, :] = rng.randn(n_times, 2, n_trials) - xx = multishift(x, -np.arange(1, 4), reshape=True, solution='valid') - yy = multishift(y, -np.arange(1, 4), reshape=True, solution='valid') + xx = multishift(x, -np.arange(1, 4), reshape=True, solution="valid") + yy = multishift(y, -np.arange(1, 4), reshape=True, solution="valid") # Test with shifts A, B, R = cca_crossvalidate(xx, yy, shifts=[-3, -2, -1, 0, 1, 2, 3]) @@ -217,10 +217,10 @@ def test_cca_crossvalidate_shifts(): def test_cca_crossvalidate_shifts2(): """Test CCA crossvalidation with shifts.""" - mat = loadmat('./tests/data/ccacrossdata.mat') - xx = mat['xx2'] - yy = mat['yy2'] - R2 = mat['R'][:, ::-1, :] # shifts go in reverse direction in noisetools + mat = loadmat("./tests/data/ccacrossdata.mat") + xx = mat["xx2"] + yy = mat["yy2"] + R2 = mat["R"][:, ::-1, :] # shifts go in reverse direction in noisetools # Test with shifts A, B, R = cca_crossvalidate(xx, yy, shifts=[-3, -2, -1, 0, 1, 2, 3]) @@ -261,18 +261,18 @@ def test_mcca(show=False): if show: import matplotlib.pyplot as plt f, axes = plt.subplots(2, 3, figsize=(10, 6)) - axes[0, 0].imshow(A, aspect='auto') - axes[0, 0].set_title('mCCA transform matrix') - axes[0, 1].imshow(A.T @ C @ A, aspect='auto') - axes[0, 1].set_title('Covariance of\ntransformed data') - axes[0, 2].imshow(x.T @ x @ A, aspect='auto') - axes[0, 2].set_title('Cross-correlation between\nraw & transformed data') - axes[0, 2].set_xlabel('transformed') - axes[0, 2].set_ylabel('raw') + axes[0, 0].imshow(A, aspect="auto") + axes[0, 0].set_title("mCCA transform matrix") + axes[0, 1].imshow(A.T @ C @ A, aspect="auto") + axes[0, 1].set_title("Covariance of\ntransformed data") + axes[0, 2].imshow(x.T @ x @ A, aspect="auto") + axes[0, 2].set_title("Cross-correlation between\nraw & transformed data") + axes[0, 2].set_xlabel("transformed") + axes[0, 2].set_ylabel("raw") ax = plt.subplot2grid((2, 3), (1, 0), colspan=3) - ax.plot(np.mean(z ** 2, axis=0), ':o') - ax.set_ylabel('Power') - ax.set_xlabel('CC') + ax.plot(np.mean(z ** 2, axis=0), ":o") + ax.set_ylabel("Power") + ax.set_xlabel("CC") plt.tight_layout() plt.show() @@ -296,18 +296,18 @@ def test_mcca(show=False): if show: f, axes = plt.subplots(2, 3, figsize=(10, 6)) - axes[0, 0].imshow(A, aspect='auto') - axes[0, 0].set_title('mCCA transform matrix') - axes[0, 1].imshow(A.T.dot(C.dot(A)), aspect='auto') - axes[0, 1].set_title('Covariance of\ntransformed data') - axes[0, 2].imshow(x.T.dot((x.dot(A))), aspect='auto') - axes[0, 2].set_title('Cross-correlation between\nraw & transformed data') - axes[0, 2].set_xlabel('transformed') - axes[0, 2].set_ylabel('raw') + axes[0, 0].imshow(A, aspect="auto") + axes[0, 0].set_title("mCCA transform matrix") + axes[0, 1].imshow(A.T.dot(C.dot(A)), aspect="auto") + axes[0, 1].set_title("Covariance of\ntransformed data") + axes[0, 2].imshow(x.T.dot(x.dot(A)), aspect="auto") + axes[0, 2].set_title("Cross-correlation between\nraw & transformed data") + axes[0, 2].set_xlabel("transformed") + axes[0, 2].set_ylabel("raw") ax = plt.subplot2grid((2, 3), (1, 0), colspan=3) - ax.plot(np.mean(z ** 2, axis=0), ':o') - ax.set_ylabel('Power') - ax.set_xlabel('CC') + ax.plot(np.mean(z ** 2, axis=0), ":o") + ax.set_ylabel("Power") + ax.set_xlabel("CC") plt.tight_layout() plt.show() @@ -330,20 +330,20 @@ def test_mcca(show=False): # Plot results if show: f, axes = plt.subplots(2, 3, figsize=(10, 6)) - axes[0, 0].imshow(A, aspect='auto') - axes[0, 0].set_title('mCCA transform matrix') + axes[0, 0].imshow(A, aspect="auto") + axes[0, 0].set_title("mCCA transform matrix") - axes[0, 1].imshow(A.T @ C @ A, aspect='auto') - axes[0, 1].set_title('Covariance of\ntransformed data') + axes[0, 1].imshow(A.T @ C @ A, aspect="auto") + axes[0, 1].set_title("Covariance of\ntransformed data") - axes[0, 2].imshow(x.T @ x @ A, aspect='auto') - axes[0, 2].set_title('Cross-correlation between\nraw & transformed data') - axes[0, 2].set_xlabel('transformed') - axes[0, 2].set_ylabel('raw') + axes[0, 2].imshow(x.T @ x @ A, aspect="auto") + axes[0, 2].set_title("Cross-correlation between\nraw & transformed data") + axes[0, 2].set_xlabel("transformed") + axes[0, 2].set_ylabel("raw") ax = plt.subplot2grid((2, 3), (1, 0), colspan=3) - ax.plot(np.mean(z ** 2, axis=0), ':o') - ax.set_ylabel('Power') - ax.set_xlabel('CC') + ax.plot(np.mean(z ** 2, axis=0), ":o") + ax.set_ylabel("Power") + ax.set_xlabel("CC") plt.tight_layout() plt.show() @@ -352,7 +352,7 @@ def test_mcca(show=False): assert np.all(diagonal[:10] > 1), diagonal[:10] assert np.all(diagonal[10:] < .01) -if __name__ == '__main__': +if __name__ == "__main__": import pytest pytest.main([__file__]) # test_mcca(False) diff --git a/tests/test_cov.py b/tests/test_cov.py index f45c8c7e..ce69b470 100644 --- a/tests/test_cov.py +++ b/tests/test_cov.py @@ -1,12 +1,13 @@ import numpy as np from numpy.testing import assert_almost_equal -from meegkit.utils import tscov, tsxcov, convmtx +from meegkit.utils import convmtx, tscov, tsxcov +rng = np.random.default_rng(10) def test_tscov(): """Test time-shift covariance.""" - x = 2 * np.eye(3) + 0.1 * np.random.rand(3) + x = 2 * np.eye(3) + 0.1 * rng.random(3) x = x - np.mean(x, 0) # Compare 0-lag case with numpy.cov() @@ -87,7 +88,7 @@ def test_convmtx(): ]) ) -if __name__ == '__main__': +if __name__ == "__main__": # import pytest # pytest.main([__file__]) test_convmtx() diff --git a/tests/test_detrend.py b/tests/test_detrend.py index 5d115044..47eeed13 100644 --- a/tests/test_detrend.py +++ b/tests/test_detrend.py @@ -1,42 +1,42 @@ """Test robust detrending.""" import numpy as np - -from meegkit.detrend import regress, detrend, reduce_ringing, create_masked_weight - from scipy.signal import butter, lfilter +from meegkit.detrend import create_masked_weight, detrend, reduce_ringing, regress + +rng = np.random.default_rng(9) def test_regress(): """Test regression.""" # Simple regression example, no weights # fit random walk - y = np.cumsum(np.random.randn(1000, 1), axis=0) + y = np.cumsum(rng.standard_normal((1000, 1)), axis=0) x = np.arange(1000.)[:, None] x = np.hstack([x, x ** 2, x ** 3]) [b, z] = regress(y, x) # Simple regression example, with weights - y = np.cumsum(np.random.randn(1000, 1), axis=0) - w = np.random.rand(*y.shape) + y = np.cumsum(rng.standard_normal((1000, 1)), axis=0) + w = rng.random(y.shape) [b, z] = regress(y, x, w) # Downweight 1st half of the data - y = np.cumsum(np.random.randn(1000, 1), axis=0) + 1000 + y = np.cumsum(rng.standard_normal((1000, 1)), axis=0) + 1000 w = np.ones(y.shape[0]) w[:500] = 0 [b, z] = regress(y, x, w) # # Multichannel regression - y = np.cumsum(np.random.randn(1000, 2), axis=0) + y = np.cumsum(rng.standard_normal((1000, 2)), axis=0) w = np.ones(y.shape[0]) [b, z] = regress(y, x, w) assert z.shape == (1000, 2) assert b.shape == (2, 1) # Multichannel regression - y = np.cumsum(np.random.randn(1000, 2), axis=0) + y = np.cumsum(rng.standard_normal((1000, 2)), axis=0) w = np.ones(y.shape) - w[:, 1] == .8 + w[:, 1] = .8 [b, z] = regress(y, x, w) assert z.shape == (1000, 2) assert b.shape == (2, 3) @@ -46,21 +46,21 @@ def test_detrend(show=False): """Test detrending.""" # basic x = np.arange(100)[:, None] # trend - source = np.random.randn(*x.shape) + source = rng.standard_normal(x.shape) x = x + source y, _, _ = detrend(x, 1) assert y.shape == x.shape # detrend biased random walk - x = np.cumsum(np.random.randn(1000, 1) + 0.1) + x = np.cumsum(rng.standard_normal((1000, 1)) + 0.1) y, _, _ = detrend(x, 3) assert y.shape == x.shape # test weights trend = np.linspace(0, 100, 1000)[:, None] - data = 3 * np.random.randn(*trend.shape) + data = 3 * rng.standard_normal(trend.shape) data[:100, :] = 100 x = trend + data w = np.ones(x.shape) @@ -77,27 +77,27 @@ def test_detrend(show=False): assert np.all(np.abs(yy[100:] - data[100:]) < 1.) # detrend higher-dimensional data - x = np.cumsum(np.random.randn(1000, 16) + 0.1, axis=0) + x = np.cumsum(rng.standard_normal((1000, 16)) + 0.1, axis=0) y, _, _ = detrend(x, 1, show=False) # detrend higher-dimensional data with order 3 polynomial - x = np.cumsum(np.random.randn(1000, 16) + 0.1, axis=0) - y, _, _ = detrend(x, 3, basis='polynomials', show=True) + x = np.cumsum(rng.standard_normal((1000, 16)) + 0.1, axis=0) + y, _, _ = detrend(x, 3, basis="polynomials", show=True) # detrend with sinusoids - x = np.random.randn(1000, 2) + x = rng.standard_normal((1000, 2)) x += 2 * np.sin(2 * np.pi * np.arange(1000) / 200)[:, None] - y, _, _ = detrend(x, 5, basis='sinusoids', show=True) + y, _, _ = detrend(x, 5, basis="sinusoids", show=True) # trial-masked detrending trend = np.linspace(0, 100, 1000)[:, None] - data = 3 * np.random.randn(*trend.shape) + data = 3 * rng.standard_normal(trend.shape) data[:100, :] = 100 x = trend + data events = np.arange(30, 970, 40) tmin, tmax, sfreq = -0.2, 0.3, 20 w = create_masked_weight(x, events, tmin, tmax, sfreq) - y, _, _ = detrend(x, 1, w, basis='polynomials', show=show) + y, _, _ = detrend(x, 1, w, basis="polynomials", show=show) def test_ringing(): @@ -106,13 +106,13 @@ def test_ringing(): [b, a] = butter(6, 0.2) # Butterworth filter design x = lfilter(b, a, x) * 50 # Filter data using above filter x = np.roll(x, 500) - signal = np.random.randn(1000, 2) + signal = rng.standard_normal((1000, 2)) x = x[:, None] + signal - y = reduce_ringing(x, samples=np.array([500])) + reduce_ringing(x, samples=np.array([500])) # np.testing.assert_array_almost_equal(y, signal, 2) -if __name__ == '__main__': +if __name__ == "__main__": import pytest pytest.main([__file__]) # test_detrend(False) diff --git a/tests/test_dss.py b/tests/test_dss.py index be390355..5b354a66 100644 --- a/tests/test_dss.py +++ b/tests/test_dss.py @@ -5,13 +5,16 @@ import matplotlib.pyplot as plt import numpy as np import pytest -from meegkit import dss -from meegkit.utils import create_line_data, fold, tscov, unfold from numpy.testing import assert_allclose from scipy import signal +from meegkit import dss +from meegkit.utils import create_line_data, fold, tscov, unfold + +rng = np.random.default_rng(10) + -@pytest.mark.parametrize('n_bad_chans', [0, -1]) +@pytest.mark.parametrize("n_bad_chans", [0, -1]) def test_dss0(n_bad_chans): """Test dss0. @@ -64,9 +67,9 @@ def test_dss1(show=True): if show: f, (ax1, ax2, ax3) = plt.subplots(3, 1) - ax1.plot(source, label='source') - ax2.plot(np.mean(data, 2), label='data') - ax3.plot(best_comp, label='recovered') + ax1.plot(source, label="source") + ax2.plot(np.mean(data, 2), label="data") + ax3.plot(best_comp, label="recovered") plt.legend() plt.show() @@ -74,7 +77,7 @@ def test_dss1(show=True): atol=1e-6) # use abs as DSS component might be flipped -@pytest.mark.parametrize('nkeep', [None, 2]) +@pytest.mark.parametrize("nkeep", [None, 2]) def test_dss_line(nkeep): """Test line noise removal.""" sr = 200 @@ -92,11 +95,11 @@ def _plot(x): f, Pxx = signal.welch(s, sr, nperseg=1024, axis=0, return_onesided=True) ax[0].semilogy(f, Pxx) - ax[0].set_xlabel('frequency [Hz]') - ax[1].set_xlabel('frequency [Hz]') - ax[0].set_ylabel('PSD [V**2/Hz]') - ax[0].set_title('before') - ax[1].set_title('after') + ax[0].set_xlabel("frequency [Hz]") + ax[1].set_xlabel("frequency [Hz]") + ax[0].set_ylabel("PSD [V**2/Hz]") + ax[0].set_title("before") + ax[1].set_title("after") plt.show() # 2D case, n_outputs == 1 @@ -112,7 +115,7 @@ def _plot(x): # _plot(out) # Test n_trials > 1 - x = np.random.randn(nsamples, nchans, 4) + x = rng.standard_normal((nsamples, nchans, 4)) artifact = np.sin( np.arange(nsamples) / sr * 2 * np.pi * fline)[:, None, None] artifact[artifact < 0] = 0 @@ -144,7 +147,7 @@ def test_dss_line_iter(): with TemporaryDirectory() as tmpdir: out, _ = dss.dss_line_iter(x, fline + .5, sr, - prefix=os.path.join(tmpdir, 'dss_iter_'), + prefix=os.path.join(tmpdir, "dss_iter_"), show=True) def _plot(before, after): @@ -155,11 +158,11 @@ def _plot(before, after): f, Pxx = signal.welch(after[:, -1], sr, nperseg=1024, axis=0, return_onesided=True) ax[1].semilogy(f, Pxx) - ax[0].set_xlabel('frequency [Hz]') - ax[1].set_xlabel('frequency [Hz]') - ax[0].set_ylabel('PSD [V**2/Hz]') - ax[0].set_title('before') - ax[1].set_title('after') + ax[0].set_xlabel("frequency [Hz]") + ax[1].set_xlabel("frequency [Hz]") + ax[0].set_ylabel("PSD [V**2/Hz]") + ax[0].set_title("before") + ax[1].set_title("after") plt.show() _plot(x, out) @@ -193,7 +196,7 @@ def profile_dss_line(nkeep): ps.print_stats() print(s.getvalue()) -if __name__ == '__main__': +if __name__ == "__main__": pytest.main([__file__]) # create_data(SNR=5, show=True) # test_dss1(True) diff --git a/tests/test_lof.py b/tests/test_lof.py index b37d2382..7635067a 100644 --- a/tests/test_lof.py +++ b/tests/test_lof.py @@ -7,26 +7,26 @@ from meegkit.lof import LOF -np.random.seed(9) +rng = np.random.default_rng(10) # Data files THIS_FOLDER = os.path.dirname(os.path.abspath(__file__)) # data folder of MEEGKIT -@pytest.mark.parametrize(argnames='n_neighbors', argvalues=(8, 20, 40, 2048)) +@pytest.mark.parametrize(argnames="n_neighbors", argvalues=(8, 20, 40, 2048)) def test_lof(n_neighbors, show=False): - mat = sio.loadmat(os.path.join(THIS_FOLDER, 'data', 'lofdata.mat')) - X = mat['X'] + mat = sio.loadmat(os.path.join(THIS_FOLDER, "data", "lofdata.mat")) + X = mat["X"] lof = LOF(n_neighbors) bad_channel_indices = lof.predict(X) print(bad_channel_indices) -@pytest.mark.parametrize(argnames='metric', - argvalues=('euclidean', 'nan_euclidean', - 'cosine', 'cityblock', 'manhattan')) +@pytest.mark.parametrize(argnames="metric", + argvalues=("euclidean", "nan_euclidean", + "cosine", "cityblock", "manhattan")) def test_lof2(metric, show=False): - mat = sio.loadmat(os.path.join(THIS_FOLDER, 'data', 'lofdata.mat')) - X = mat['X'] + mat = sio.loadmat(os.path.join(THIS_FOLDER, "data", "lofdata.mat")) + X = mat["X"] lof = LOF(20, metric) bad_channel_indices = lof.predict(X) print(bad_channel_indices) diff --git a/tests/test_ress.py b/tests/test_ress.py index d5c39d41..8e99cec5 100644 --- a/tests/test_ress.py +++ b/tests/test_ress.py @@ -4,9 +4,12 @@ import pytest import scipy.signal as ss from scipy.linalg import pinv + from meegkit import ress from meegkit.utils import fold, matmul3d, rms, snr_spectrum, unfold +rng = np.random.default_rng(9) + def create_data(n_times, n_chans=10, n_trials=20, freq=12, sfreq=250, noise_dim=8, SNR=.8, t0=100, show=False): @@ -20,7 +23,7 @@ def create_data(n_times, n_chans=10, n_trials=20, freq=12, sfreq=250, """ # source source = np.sin(2 * np.pi * freq * np.arange(n_times - t0) / sfreq)[None].T - s = source * np.random.randn(1, n_chans) + s = source * rng.standard_normal((1, n_chans)) s = s[:, :, np.newaxis] s = np.tile(s, (1, 1, n_trials)) signal = np.zeros((n_times, n_chans, n_trials)) @@ -28,8 +31,8 @@ def create_data(n_times, n_chans=10, n_trials=20, freq=12, sfreq=250, # noise noise = np.dot( - unfold(np.random.randn(n_times, noise_dim, n_trials)), - np.random.randn(noise_dim, n_chans)) + unfold(rng.standard_normal((n_times, noise_dim, n_trials))), + rng.standard_normal((noise_dim, n_chans))) noise = fold(noise, n_times) # mix signal and noise @@ -39,9 +42,9 @@ def create_data(n_times, n_chans=10, n_trials=20, freq=12, sfreq=250, if show: f, ax = plt.subplots(3) - ax[0].plot(signal[:, 0, 0], label='source') - ax[1].plot(noise[:, 1, 0], label='noise') - ax[2].plot(noisy_data[:, 1, 0], label='mixture') + ax[0].plot(signal[:, 0, 0], label="source") + ax[1].plot(noise[:, 1, 0], label="noise") + ax[2].plot(noisy_data[:, 1, 0], label="mixture") ax[0].legend() ax[1].legend() ax[2].legend() @@ -50,11 +53,11 @@ def create_data(n_times, n_chans=10, n_trials=20, freq=12, sfreq=250, return noisy_data, signal -@pytest.mark.parametrize('target', [12, 15, 20]) -@pytest.mark.parametrize('n_trials', [16]) -@pytest.mark.parametrize('peak_width', [.5, 1]) -@pytest.mark.parametrize('neig_width', [1]) -@pytest.mark.parametrize('neig_freq', [1]) +@pytest.mark.parametrize("target", [12, 15, 20]) +@pytest.mark.parametrize("n_trials", [16]) +@pytest.mark.parametrize("peak_width", [.5, 1]) +@pytest.mark.parametrize("neig_width", [1]) +@pytest.mark.parametrize("neig_freq", [1]) def test_ress(target, n_trials, peak_width, neig_width, neig_freq, show=False): """Test RESS.""" sfreq = 250 @@ -73,7 +76,7 @@ def test_ress(target, n_trials, peak_width, neig_width, neig_freq, show=False): nfft = 500 bins, psd = ss.welch(out.squeeze(1), sfreq, window="boxcar", nperseg=nfft / (peak_width * 2), - noverlap=0, axis=0, average='mean') + noverlap=0, axis=0, average="mean") # psd = np.abs(np.fft.fft(out, nfft, axis=0)) # psd = psd[0:psd.shape[0] // 2 + 1] # bins = np.linspace(0, sfreq // 2, psd.shape[0]) @@ -85,17 +88,17 @@ def test_ress(target, n_trials, peak_width, neig_width, neig_freq, show=False): # snr = snr.mean(1) if show: f, ax = plt.subplots(2) - ax[0].plot(bins, snr, ':o') - ax[0].axhline(1, ls=':', c='grey', zorder=0) - ax[0].axvline(target, ls=':', c='grey', zorder=0) - ax[0].set_ylabel('SNR (a.u.)') - ax[0].set_xlabel('Frequency (Hz)') + ax[0].plot(bins, snr, ":o") + ax[0].axhline(1, ls=":", c="grey", zorder=0) + ax[0].axvline(target, ls=":", c="grey", zorder=0) + ax[0].set_ylabel("SNR (a.u.)") + ax[0].set_xlabel("Frequency (Hz)") ax[0].set_xlim([0, 40]) ax[0].set_ylim([0, 10]) ax[1].plot(bins, psd) - ax[1].axvline(target, ls=':', c='grey', zorder=0) - ax[1].set_ylabel('PSD') - ax[1].set_xlabel('Frequency (Hz)') + ax[1].axvline(target, ls=":", c="grey", zorder=0) + ax[1].set_ylabel("PSD") + ax[1].set_xlabel("Frequency (Hz)") ax[1].set_xlim([0, 40]) # plt.show() @@ -113,16 +116,16 @@ def test_ress(target, n_trials, peak_width, neig_width, neig_freq, show=False): assert proj.shape == (n_times, n_chans, n_trials) if show: - f, ax = plt.subplots(data.shape[1], 2, sharey='col') + f, ax = plt.subplots(data.shape[1], 2, sharey="col") for c in range(data.shape[1]): - ax[c, 0].plot(data[:, c].mean(-1), lw=.5, label='data') - ax[c, 1].plot(proj[:, c].mean(-1), lw=.5, label='projection') + ax[c, 0].plot(data[:, c].mean(-1), lw=.5, label="data") + ax[c, 1].plot(proj[:, c].mean(-1), lw=.5, label="projection") if c < data.shape[1]: ax[c, 0].set_xticks([]) ax[c, 1].set_xticks([]) - ax[0, 0].set_title('Before') - ax[0, 1].set_title('After') + ax[0, 0].set_title("Before") + ax[0, 1].set_title("After") plt.legend() # 2 comps @@ -141,19 +144,19 @@ def test_ress(target, n_trials, peak_width, neig_width, neig_freq, show=False): _max = np.amax(combined_data) f, ax = plt.subplots(3) - ax[0].imshow(toress, label='toRESS') - ax[0].set_title('toRESS') - ax[1].imshow(fromress, label='fromRESS', vmin=-_max, vmax=_max) - ax[1].set_title('fromRESS') + ax[0].imshow(toress, label="toRESS") + ax[0].set_title("toRESS") + ax[1].imshow(fromress, label="fromRESS", vmin=-_max, vmax=_max) + ax[1].set_title("fromRESS") ax[2].imshow(pinv(toress), vmin=-_max, vmax=_max) - ax[2].set_title('toRESS$^{-1}$') + ax[2].set_title("toRESS$^{-1}$") plt.tight_layout() plt.show() print(np.sum(np.abs(pinv(toress) - fromress) >= .1)) -if __name__ == '__main__': +if __name__ == "__main__": import pytest pytest.main([__file__]) # test_ress(20, 16, 1, 1, 1, show=False) diff --git a/tests/test_signal.py b/tests/test_signal.py index 78eb7361..9e9688ec 100644 --- a/tests/test_signal.py +++ b/tests/test_signal.py @@ -1,15 +1,17 @@ """Test signal utils.""" import numpy as np -from scipy.signal import lfilter, butter, freqz -from meegkit.utils.sig import teager_kaiser, stmcb +from scipy.signal import butter, freqz, lfilter +from meegkit.utils.sig import stmcb, teager_kaiser + +rng = np.random.default_rng(9) def test_teager_kaiser(show=False): """Test Teager-Kaiser Energy.""" - x = 2 * np.random.rand(1000, 2) - 1 + x = 2 * rng.random((1000, 2)) - 1 x[100, 0] = 5 x[200, 0] = 5 - x += np.cumsum(np.random.randn(1000, 1) + 0.1, axis=0) / 1000 + x += np.cumsum(rng.standard_normal((1000, 1)) + 0.1, axis=0) / 1000 for i in range(1, 5): print(i) y = teager_kaiser(x, M=i, m=1) @@ -20,8 +22,8 @@ def test_teager_kaiser(show=False): plt.figure() # plt.plot((x[1:, 0] - x[1:, 0].mean()) / np.nanstd(x[1:, 0])) # plt.plot((y[..., 0] - y[..., 0].mean()) / np.nanstd(y[..., 0])) - plt.plot(x[1:, 0], label='X') - plt.plot(y[..., 0], label='Y') + plt.plot(x[1:, 0], label="X") + plt.plot(y[..., 0], label="Y") plt.legend() plt.show() @@ -39,10 +41,10 @@ def test_stcmb(show=True): if show: import matplotlib.pyplot as plt f, ax = plt.subplots(2, 1) - ax[0].plot(x, label='step') - ax[0].plot(y, label='filt') - ax[1].plot(w, np.abs(h), label='real') - ax[1].plot(ww, np.abs(hh), label='stcmb') + ax[0].plot(x, label="step") + ax[0].plot(y, label="filt") + ax[1].plot(w, np.abs(h), label="real") + ax[1].plot(ww, np.abs(hh), label="stcmb") ax[0].legend() ax[1].legend() plt.show() @@ -50,4 +52,5 @@ def test_stcmb(show=True): np.testing.assert_allclose(h, hh, rtol=2) # equal to 2% if __name__ == "__main__": + test_teager_kaiser() test_stcmb() diff --git a/tests/test_sns.py b/tests/test_sns.py index 2d175058..1ffd6fda 100644 --- a/tests/test_sns.py +++ b/tests/test_sns.py @@ -7,11 +7,11 @@ def test_sns(): """Test against NoiseTools.""" - mat = loadmat('./tests/data/snsdata.mat') - x = mat['x'] - y_sns = mat['y_sns'] - r_sns0 = mat['y_sns0'] - cx = mat['cx'] + mat = loadmat("./tests/data/snsdata.mat") + x = mat["x"] + y_sns = mat["y_sns"] + r_sns0 = mat["y_sns0"] + cx = mat["cx"] r = sns.sns0(cx, n_neighbors=4) assert_allclose(r, r_sns0) # assert our results match Matlab's @@ -20,6 +20,6 @@ def test_sns(): assert_allclose(y, y_sns) # assert our results match Matlab's -if __name__ == '__main__': +if __name__ == "__main__": import pytest pytest.main([__file__]) diff --git a/tests/test_star.py b/tests/test_star.py index cad4584c..5f85eaa5 100644 --- a/tests/test_star.py +++ b/tests/test_star.py @@ -5,6 +5,7 @@ from meegkit.star import star from meegkit.utils import demean, normcol +rng = np.random.default_rng(9) def test_star1(): """Test STAR 1.""" @@ -17,11 +18,10 @@ def test_star1(): def sim_data(n_samples, n_chans, f, SNR): target = np.sin(np.arange(n_samples) / n_samples * 2 * np.pi * f) target = target[:, np.newaxis] - noise = np.random.randn(n_samples, n_chans - 3) + noise = rng.standard_normal((n_samples, n_chans - 3)) - x0 = (normcol(np.dot( - noise, np.random.randn(noise.shape[1], n_chans))) + - SNR * target * np.random.randn(1, n_chans)) + x0 = normcol(np.dot(noise, rng.standard_normal((noise.shape[1], n_chans)))) \ + + SNR * target * rng.standard_normal((1, n_chans)) x0 = demean(x0) artifact = np.zeros(x0.shape) for k in np.arange(n_chans): @@ -31,7 +31,7 @@ def sim_data(n_samples, n_chans, f, SNR): # Test SNR=1 x, x0 = sim_data(n_samples, n_chans, f, SNR=np.sqrt(1)) - y, w, _ = star(x, 2, verbose='debug') + y, w, _ = star(x, 2, verbose="debug") assert_allclose(demean(y), x0) # check that denoised signal ~ x0 # Test more unfavourable SNR @@ -45,7 +45,7 @@ def sim_data(n_samples, n_chans, f, SNR): assert_allclose(demean(y)[:, 0], x[:, 0]) -if __name__ == '__main__': +if __name__ == "__main__": import pytest pytest.main([__file__]) # test_star1() diff --git a/tests/test_trca.py b/tests/test_trca.py index c45bcd33..de17d61a 100644 --- a/tests/test_trca.py +++ b/tests/test_trca.py @@ -4,13 +4,14 @@ import numpy as np import pytest import scipy.io + from meegkit.trca import TRCA from meegkit.utils.trca import itr, normfit, round_half_up ########################################################################## # Load data # ----------------------------------------------------------------------------- -path = os.path.join('.', 'tests', 'data', 'trcadata.mat') +path = os.path.join(".", "tests", "data", "trcadata.mat") mat = scipy.io.loadmat(path) eeg = mat["eeg"] @@ -41,12 +42,12 @@ [[38, 90], [32, 100]]] -@pytest.mark.parametrize('ensemble', [True, False]) -@pytest.mark.parametrize('method', ['original', 'riemann']) -@pytest.mark.parametrize('regularization', ['schaefer', 'scm']) +@pytest.mark.parametrize("ensemble", [True, False]) +@pytest.mark.parametrize("method", ["original", "riemann"]) +@pytest.mark.parametrize("regularization", ["schaefer", "scm"]) def test_trca(ensemble, method, regularization): """Test TRCA.""" - if method == 'original' and regularization == 'schaefer': + if method == "original" and regularization == "schaefer": pytest.skip("regularization only used for riemann version") len_gaze_s = 0.5 # data length for target identification [s] @@ -101,15 +102,15 @@ def test_trca(ensemble, method, regularization): # Mean accuracy and ITR computation mu, _, muci, _ = normfit(accs, alpha_ci) print(f"Mean accuracy = {mu:.1f}%\t({ci:.0f}% CI: {muci[0]:.1f}-{muci[1]:.1f}%)") # noqa - if method != 'riemann' or (regularization == 'scm' and ensemble): + if method != "riemann" or (regularization == "scm" and ensemble): assert mu > 95 mu, _, muci, _ = normfit(itrs, alpha_ci) print(f"Mean ITR = {mu:.1f}\t({ci:.0f}% CI: {muci[0]:.1f}-{muci[1]:.1f}%)") - if method != 'riemann' or (regularization == 'scm' and ensemble): + if method != "riemann" or (regularization == "scm" and ensemble): assert mu > 300 -if __name__ == '__main__': +if __name__ == "__main__": import pytest pytest.main([__file__]) # test_trcacode() diff --git a/tests/test_tspca.py b/tests/test_tspca.py index 382dad65..d1753182 100644 --- a/tests/test_tspca.py +++ b/tests/test_tspca.py @@ -1,9 +1,10 @@ +import matplotlib.pyplot as plt import numpy as np from meegkit import dss, sns, tspca from meegkit.utils import demean, fold, unfold -import matplotlib.pyplot as plt +rng = np.random.default_rng(9) def test_tspca_sns_dss(): # TODO @@ -16,12 +17,12 @@ def test_tspca_sns_dss(): # TODO Remove non-repeatable components with DSS. """ # Random data (time*chans*trials) - data = np.random.random((800, 102, 200)) - ref = np.random.random((800, 3, 200)) + data = rng.random((800, 102, 200)) + ref = rng.random((800, 3, 200)) # remove means noisy_data = demean(data) - noisy_ref = demean(ref) + demean(ref) # Apply TSPCA # ------------------------------------------------------------------------- @@ -34,18 +35,18 @@ def test_tspca_sns_dss(): # TODO # Apply SNS # ------------------------------------------------------------------------- nneighbors = 10 - print('SNS...') + print("SNS...") y_tspca_sns, r = sns.sns(y_tspca, nneighbors) - print('\b OK!') + print("\b OK!") # apply DSS # ------------------------------------------------------------------------- - print('DSS...') + print("DSS...") # Keep all PC components y_tspca_sns = demean(y_tspca_sns) print(y_tspca_sns.shape) todss, fromdss, _, _ = dss.dss1(y_tspca_sns) - print('\b OK!') + print("\b OK!") # c3 = DSS components y_tspca_sns_dss = fold( @@ -60,7 +61,7 @@ def test_tsr(show=True): sr = 200 nsamples = 10000 nchans = 10 - x = np.random.randn(nsamples, nchans) + x = rng.standard_normal((nsamples, nchans)) # artifact + harmonics artifact = np.sin(np.arange(nsamples) / sr * 2 * np.pi * 10)[:, None] @@ -78,10 +79,10 @@ def test_tsr(show=True): shifts=[0]) if show: - f, ax = plt.subplots(2, 1, num='without shifts') - ax[0].plot(y[:500, 0], 'grey', label='recovered signal') - ax[0].plot(x[:500, 0], ':', label='real signal') - ax[1].plot((y - x)[:500], label='residual') + f, ax = plt.subplots(2, 1, num="without shifts") + ax[0].plot(y[:500, 0], "grey", label="recovered signal") + ax[0].plot(x[:500, 0], ":", label="real signal") + ax[1].plot((y - x)[:500], label="residual") ax[0].legend() ax[1].legend() # plt.show() @@ -97,17 +98,17 @@ def test_tsr(show=True): shifts=[-1, 0, 1]) if show: - f, ax = plt.subplots(3, 1, num='with shifts') - ax[0].plot(signal[:500], label='signal + noise') - ax[1].plot(x[:500, 0], 'grey', label='real signal') - ax[1].plot(y[:500, 0], ':', label='recovered signal') - ax[2].plot((signal - y)[:500, 0], label='before - after') + f, ax = plt.subplots(3, 1, num="with shifts") + ax[0].plot(signal[:500], label="signal + noise") + ax[1].plot(x[:500, 0], "grey", label="real signal") + ax[1].plot(y[:500, 0], ":", label="recovered signal") + ax[2].plot((signal - y)[:500, 0], label="before - after") ax[0].legend() ax[1].legend() ax[2].legend() plt.show() -if __name__ == '__main__': +if __name__ == "__main__": import pytest pytest.main([__file__]) # test_tspca_sns_dss() diff --git a/tests/test_utils.py b/tests/test_utils.py index 01678516..2e2176fd 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,16 +1,33 @@ import numpy as np -from meegkit.utils import (bootstrap_ci, demean, find_outlier_samples, - find_outlier_trials, fold, mean_over_trials, - multishift, multismooth, relshift, rms, shift, - shiftnd, unfold, widen_mask, cronbach, robust_mean) from numpy.testing import assert_almost_equal, assert_equal +from meegkit.utils import ( + bootstrap_ci, + cronbach, + demean, + find_outlier_samples, + find_outlier_trials, + fold, + mean_over_trials, + multishift, + multismooth, + relshift, + rms, + robust_mean, + shift, + shiftnd, + unfold, + widen_mask, +) + +rng = np.random.default_rng() + def _sim_data(n_times, n_chans, n_trials, noise_dim, SNR=1, t0=100): """Create synthetic data.""" # source source = np.sin(2 * np.pi * np.linspace(0, .5, n_times - t0))[np.newaxis].T - s = source * np.random.randn(1, n_chans) + s = source * rng.standard_normal((1, n_chans)) s = s[:, :, np.newaxis] s = np.tile(s, (1, 1, n_trials)) signal = np.zeros((n_times, n_chans, n_trials)) @@ -18,8 +35,8 @@ def _sim_data(n_times, n_chans, n_trials, noise_dim, SNR=1, t0=100): # noise noise = np.dot( - unfold(np.random.randn(n_times, noise_dim, n_trials)), - np.random.randn(noise_dim, n_chans)) + unfold(rng.standard_normal((n_times, noise_dim, n_trials))), + rng.standard_normal((noise_dim, n_chans))) noise = fold(noise, n_times) # mix signal and noise @@ -42,7 +59,7 @@ def test_multishift(): x = np.ones((4, 4, 3)) x[..., 1] *= 2 x[..., 2] *= 3 - xx = multishift(x, [-1, -2], reshape=True, solution='valid') + xx = multishift(x, [-1, -2], reshape=True, solution="valid") assert_equal(xx[..., 0], np.array([[1., 1., 1., 1., 1., 1., 1., 1.], [1., 1., 1., 1., 1., 1., 1., 1.]])) assert_equal(xx[..., 1], np.array([[1., 1., 1., 1., 1., 1., 1., 1.], @@ -125,7 +142,7 @@ def test_widen_mask(): def test_multismooth(): """Test smoothing.""" - x = (np.random.randn(1000, 1) / 2 + + x = (rng.standard_normal((1000, 1)) / 2 + np.cos(2 * np.pi * 3 * np.linspace(0, 20, 1000))[:, None]) for i in np.arange(1, 10, 1): @@ -141,7 +158,7 @@ def test_demean(show=False): n_trials = 100 n_chans = 8 n_times = 1000 - x = np.random.randn(n_times, n_chans, n_trials) + x = rng.standard_normal((n_times, n_chans, n_trials)) x, s = _sim_data(n_times, n_chans, n_trials, 8, SNR=10) # 1. demean and check trial average is almost zero @@ -158,14 +175,14 @@ def test_demean(show=False): if show: import matplotlib.pyplot as plt f, ax = plt.subplots(3, 1) - ax[0].plot(times, x[:, 0].mean(-1), label='noisy_data') - ax[0].plot(times, s[:, 0].mean(-1), label='signal') + ax[0].plot(times, x[:, 0].mean(-1), label="noisy_data") + ax[0].plot(times, s[:, 0].mean(-1), label="signal") ax[0].legend() - ax[1].plot(times, x1[:, 0].mean(-1), label='mean over entire epoch') + ax[1].plot(times, x1[:, 0].mean(-1), label="mean over entire epoch") ax[1].legend() - ax[2].plot(x2[:, 0].mean(-1), label='weighted mean') + ax[2].plot(x2[:, 0].mean(-1), label="weighted mean") plt.gca().set_prop_cycle(None) - ax[2].plot(s[:, 0].mean(-1), 'k:') + ax[2].plot(s[:, 0].mean(-1), "k:") ax[2].legend() plt.show() @@ -194,7 +211,7 @@ def test_demean(show=False): def test_computeci(): """Compute CI.""" - x = np.random.randn(1000, 8, 100) + x = rng.standard_normal((1000, 8, 100)) ci_low, ci_high = bootstrap_ci(x) assert ci_low.shape == (1000, 8) @@ -205,7 +222,7 @@ def test_computeci(): # assert ci_low.shape == (1000,) # assert ci_high.shape == (1000,) - x = np.random.randn(1000, 100) + x = rng.standard_normal((1000, 100)) ci_low, ci_high = bootstrap_ci(x) assert ci_low.shape == (1000,) @@ -214,7 +231,7 @@ def test_computeci(): def test_outliers(show=False): """Test outlier detection.""" - x = np.random.randn(250, 8, 50) # 50 trials, 8, channels + x = rng.standard_normal((250, 8, 50)) # 50 trials, 8, channels x[..., :5] *= 10 # 5 first trials are outliers # Pass standard threshold @@ -248,13 +265,13 @@ def test_cronbach(): m = robust_mean(X, axis=0) assert m.shape == (X.shape[1], X.shape[2]) -if __name__ == '__main__': +if __name__ == "__main__": import pytest pytest.main([__file__]) # test_outliers() # import matplotlib.pyplot as plt - # x = np.random.randn(1000,) + # x = rng.standard_normal((1000,) # y = multismooth(x, np.arange(1, 200, 4)) # plt.imshow(y.T, aspect='auto') # plt.show()