From 54150cdb61c39235f326ca1ee648384bc469ba95 Mon Sep 17 00:00:00 2001 From: swittl Date: Mon, 16 Oct 2023 14:59:42 +0200 Subject: [PATCH 01/21] minor api --- .gitignore | 4 +- SimulateFromList/ListOfSimulations.txt | 449 ------------------ SimulateFromList/SimulateFromList.py | 146 ------ .../CreateParticlePoreMatrix.py | 316 ------------ .../Create_SingleParticle+Pores.py | 328 ------------- .../Pore_Matrix_Scene.aRTist | Bin 492841 -> 0 bytes .../Single_Pore_Scene.aRTist | Bin 1458 -> 0 bytes artistlib/__init__.py | 118 +---- artistlib/api.py | 69 +++ artistlib/remote_connection.py | 147 ++++++ example_artistlib.py | 29 -- examples/make_circular_scan.py | 40 ++ 12 files changed, 263 insertions(+), 1383 deletions(-) delete mode 100644 SimulateFromList/ListOfSimulations.txt delete mode 100644 SimulateFromList/SimulateFromList.py delete mode 100644 Standalones/ParticlesAndPores/CreateParticlePoreMatrix.py delete mode 100644 Standalones/ParticlesAndPores/Create_SingleParticle+Pores.py delete mode 100644 Standalones/ParticlesAndPores/Pore_Matrix_Scene.aRTist delete mode 100644 Standalones/ParticlesAndPores/Single_Pore_Scene.aRTist create mode 100644 artistlib/api.py create mode 100644 artistlib/remote_connection.py delete mode 100644 example_artistlib.py create mode 100644 examples/make_circular_scan.py diff --git a/.gitignore b/.gitignore index d1b7468..2108ddb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ __pycache__ artistlib.egg-info -dist \ No newline at end of file +dist +/venv/ +*.tif \ No newline at end of file diff --git a/SimulateFromList/ListOfSimulations.txt b/SimulateFromList/ListOfSimulations.txt deleted file mode 100644 index 2160ad3..0000000 --- a/SimulateFromList/ListOfSimulations.txt +++ /dev/null @@ -1,449 +0,0 @@ -ID LG LG Thickness Spot size Spot resolution Sampling ETA Source Type Source U Source I Source Filter Material Source Filter Thickness N Detector pixel size Cone beam angle Other parameters Filename Remarks -1 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.05 NxS_UB_ConeBeamAngle.tif -2 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.1 NxS_UB_ConeBeamAngle.tif -3 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.2 NxS_UB_ConeBeamAngle.tif -4 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.3 NxS_UB_ConeBeamAngle.tif -5 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.4 NxS_UB_ConeBeamAngle.tif -6 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.5 NxS_UB_ConeBeamAngle.tif -7 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.6 NxS_UB_ConeBeamAngle.tif -8 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.7 NxS_UB_ConeBeamAngle.tif -9 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.8 NxS_UB_ConeBeamAngle.tif -10 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.9 NxS_UB_ConeBeamAngle.tif -11 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1 NxS_UB_ConeBeamAngle.tif -12 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.2 NxS_UB_ConeBeamAngle.tif -13 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.4 NxS_UB_ConeBeamAngle.tif -14 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.6 NxS_UB_ConeBeamAngle.tif -15 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.8 NxS_UB_ConeBeamAngle.tif -16 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2 NxS_UB_ConeBeamAngle.tif -17 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.2 NxS_UB_ConeBeamAngle.tif -18 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.4 NxS_UB_ConeBeamAngle.tif -19 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.6 NxS_UB_ConeBeamAngle.tif -20 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.8 NxS_UB_ConeBeamAngle.tif -21 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3 NxS_UB_ConeBeamAngle.tif -22 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.2 NxS_UB_ConeBeamAngle.tif -23 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.4 NxS_UB_ConeBeamAngle.tif -24 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.6 NxS_UB_ConeBeamAngle.tif -25 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.8 NxS_UB_ConeBeamAngle.tif -26 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4 NxS_UB_ConeBeamAngle.tif -27 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.2 NxS_UB_ConeBeamAngle.tif -28 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.4 NxS_UB_ConeBeamAngle.tif -29 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.6 NxS_UB_ConeBeamAngle.tif -30 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.8 NxS_UB_ConeBeamAngle.tif -31 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5 NxS_UB_ConeBeamAngle.tif -32 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.2 NxS_UB_ConeBeamAngle.tif -33 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.4 NxS_UB_ConeBeamAngle.tif -34 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.6 NxS_UB_ConeBeamAngle.tif -35 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.8 NxS_UB_ConeBeamAngle.tif -36 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6 NxS_UB_ConeBeamAngle.tif -37 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.2 NxS_UB_ConeBeamAngle.tif -38 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.4 NxS_UB_ConeBeamAngle.tif -39 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.6 NxS_UB_ConeBeamAngle.tif -40 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.8 NxS_UB_ConeBeamAngle.tif -41 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7 NxS_UB_ConeBeamAngle.tif -42 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.2 NxS_UB_ConeBeamAngle.tif -43 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.4 NxS_UB_ConeBeamAngle.tif -44 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.6 NxS_UB_ConeBeamAngle.tif -45 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.8 NxS_UB_ConeBeamAngle.tif -46 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8 NxS_UB_ConeBeamAngle.tif -47 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.2 NxS_UB_ConeBeamAngle.tif -48 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.4 NxS_UB_ConeBeamAngle.tif -49 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.6 NxS_UB_ConeBeamAngle.tif -50 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.8 NxS_UB_ConeBeamAngle.tif -51 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9 NxS_UB_ConeBeamAngle.tif -52 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.2 NxS_UB_ConeBeamAngle.tif -53 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.4 NxS_UB_ConeBeamAngle.tif -54 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.6 NxS_UB_ConeBeamAngle.tif -55 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.8 NxS_UB_ConeBeamAngle.tif -56 6 2 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 10 NxS_UB_ConeBeamAngle.tif -57 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.05 NxS_UB_ConeBeamAngle.tif -58 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.1 NxS_UB_ConeBeamAngle.tif -59 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.2 NxS_UB_ConeBeamAngle.tif -60 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.3 NxS_UB_ConeBeamAngle.tif -61 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.4 NxS_UB_ConeBeamAngle.tif -62 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.5 NxS_UB_ConeBeamAngle.tif -63 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.6 NxS_UB_ConeBeamAngle.tif -64 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.7 NxS_UB_ConeBeamAngle.tif -65 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.8 NxS_UB_ConeBeamAngle.tif -66 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.9 NxS_UB_ConeBeamAngle.tif -67 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1 NxS_UB_ConeBeamAngle.tif -68 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.2 NxS_UB_ConeBeamAngle.tif -69 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.4 NxS_UB_ConeBeamAngle.tif -70 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.6 NxS_UB_ConeBeamAngle.tif -71 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.8 NxS_UB_ConeBeamAngle.tif -72 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2 NxS_UB_ConeBeamAngle.tif -73 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.2 NxS_UB_ConeBeamAngle.tif -74 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.4 NxS_UB_ConeBeamAngle.tif -75 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.6 NxS_UB_ConeBeamAngle.tif -76 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.8 NxS_UB_ConeBeamAngle.tif -77 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3 NxS_UB_ConeBeamAngle.tif -78 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.2 NxS_UB_ConeBeamAngle.tif -79 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.4 NxS_UB_ConeBeamAngle.tif -80 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.6 NxS_UB_ConeBeamAngle.tif -81 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.8 NxS_UB_ConeBeamAngle.tif -82 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4 NxS_UB_ConeBeamAngle.tif -83 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.2 NxS_UB_ConeBeamAngle.tif -84 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.4 NxS_UB_ConeBeamAngle.tif -85 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.6 NxS_UB_ConeBeamAngle.tif -86 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.8 NxS_UB_ConeBeamAngle.tif -87 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5 NxS_UB_ConeBeamAngle.tif -88 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.2 NxS_UB_ConeBeamAngle.tif -89 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.4 NxS_UB_ConeBeamAngle.tif -90 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.6 NxS_UB_ConeBeamAngle.tif -91 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.8 NxS_UB_ConeBeamAngle.tif -92 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6 NxS_UB_ConeBeamAngle.tif -93 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.2 NxS_UB_ConeBeamAngle.tif -94 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.4 NxS_UB_ConeBeamAngle.tif -95 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.6 NxS_UB_ConeBeamAngle.tif -96 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.8 NxS_UB_ConeBeamAngle.tif -97 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7 NxS_UB_ConeBeamAngle.tif -98 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.2 NxS_UB_ConeBeamAngle.tif -99 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.4 NxS_UB_ConeBeamAngle.tif -100 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.6 NxS_UB_ConeBeamAngle.tif -101 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.8 NxS_UB_ConeBeamAngle.tif -102 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8 NxS_UB_ConeBeamAngle.tif -103 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.2 NxS_UB_ConeBeamAngle.tif -104 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.4 NxS_UB_ConeBeamAngle.tif -105 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.6 NxS_UB_ConeBeamAngle.tif -106 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.8 NxS_UB_ConeBeamAngle.tif -107 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9 NxS_UB_ConeBeamAngle.tif -108 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.2 NxS_UB_ConeBeamAngle.tif -109 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.4 NxS_UB_ConeBeamAngle.tif -110 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.6 NxS_UB_ConeBeamAngle.tif -111 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.8 NxS_UB_ConeBeamAngle.tif -112 6 4 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 10 NxS_UB_ConeBeamAngle.tif -113 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.05 NxS_UB_ConeBeamAngle.tif -114 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.1 NxS_UB_ConeBeamAngle.tif -115 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.2 NxS_UB_ConeBeamAngle.tif -116 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.3 NxS_UB_ConeBeamAngle.tif -117 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.4 NxS_UB_ConeBeamAngle.tif -118 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.5 NxS_UB_ConeBeamAngle.tif -119 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.6 NxS_UB_ConeBeamAngle.tif -120 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.7 NxS_UB_ConeBeamAngle.tif -121 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.8 NxS_UB_ConeBeamAngle.tif -122 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.9 NxS_UB_ConeBeamAngle.tif -123 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1 NxS_UB_ConeBeamAngle.tif -124 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.2 NxS_UB_ConeBeamAngle.tif -125 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.4 NxS_UB_ConeBeamAngle.tif -126 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.6 NxS_UB_ConeBeamAngle.tif -127 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.8 NxS_UB_ConeBeamAngle.tif -128 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2 NxS_UB_ConeBeamAngle.tif -129 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.2 NxS_UB_ConeBeamAngle.tif -130 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.4 NxS_UB_ConeBeamAngle.tif -131 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.6 NxS_UB_ConeBeamAngle.tif -132 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.8 NxS_UB_ConeBeamAngle.tif -133 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3 NxS_UB_ConeBeamAngle.tif -134 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.2 NxS_UB_ConeBeamAngle.tif -135 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.4 NxS_UB_ConeBeamAngle.tif -136 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.6 NxS_UB_ConeBeamAngle.tif -137 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.8 NxS_UB_ConeBeamAngle.tif -138 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4 NxS_UB_ConeBeamAngle.tif -139 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.2 NxS_UB_ConeBeamAngle.tif -140 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.4 NxS_UB_ConeBeamAngle.tif -141 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.6 NxS_UB_ConeBeamAngle.tif -142 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.8 NxS_UB_ConeBeamAngle.tif -143 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5 NxS_UB_ConeBeamAngle.tif -144 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.2 NxS_UB_ConeBeamAngle.tif -145 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.4 NxS_UB_ConeBeamAngle.tif -146 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.6 NxS_UB_ConeBeamAngle.tif -147 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.8 NxS_UB_ConeBeamAngle.tif -148 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6 NxS_UB_ConeBeamAngle.tif -149 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.2 NxS_UB_ConeBeamAngle.tif -150 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.4 NxS_UB_ConeBeamAngle.tif -151 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.6 NxS_UB_ConeBeamAngle.tif -152 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.8 NxS_UB_ConeBeamAngle.tif -153 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7 NxS_UB_ConeBeamAngle.tif -154 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.2 NxS_UB_ConeBeamAngle.tif -155 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.4 NxS_UB_ConeBeamAngle.tif -156 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.6 NxS_UB_ConeBeamAngle.tif -157 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.8 NxS_UB_ConeBeamAngle.tif -158 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8 NxS_UB_ConeBeamAngle.tif -159 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.2 NxS_UB_ConeBeamAngle.tif -160 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.4 NxS_UB_ConeBeamAngle.tif -161 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.6 NxS_UB_ConeBeamAngle.tif -162 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.8 NxS_UB_ConeBeamAngle.tif -163 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9 NxS_UB_ConeBeamAngle.tif -164 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.2 NxS_UB_ConeBeamAngle.tif -165 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.4 NxS_UB_ConeBeamAngle.tif -166 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.6 NxS_UB_ConeBeamAngle.tif -167 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.8 NxS_UB_ConeBeamAngle.tif -168 6 6 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 10 NxS_UB_ConeBeamAngle.tif -169 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.05 NxS_UB_ConeBeamAngle.tif -170 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.1 NxS_UB_ConeBeamAngle.tif -171 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.2 NxS_UB_ConeBeamAngle.tif -172 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.3 NxS_UB_ConeBeamAngle.tif -173 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.4 NxS_UB_ConeBeamAngle.tif -174 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.5 NxS_UB_ConeBeamAngle.tif -175 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.6 NxS_UB_ConeBeamAngle.tif -176 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.7 NxS_UB_ConeBeamAngle.tif -177 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.8 NxS_UB_ConeBeamAngle.tif -178 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.9 NxS_UB_ConeBeamAngle.tif -179 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1 NxS_UB_ConeBeamAngle.tif -180 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.2 NxS_UB_ConeBeamAngle.tif -181 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.4 NxS_UB_ConeBeamAngle.tif -182 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.6 NxS_UB_ConeBeamAngle.tif -183 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.8 NxS_UB_ConeBeamAngle.tif -184 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2 NxS_UB_ConeBeamAngle.tif -185 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.2 NxS_UB_ConeBeamAngle.tif -186 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.4 NxS_UB_ConeBeamAngle.tif -187 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.6 NxS_UB_ConeBeamAngle.tif -188 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.8 NxS_UB_ConeBeamAngle.tif -189 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3 NxS_UB_ConeBeamAngle.tif -190 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.2 NxS_UB_ConeBeamAngle.tif -191 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.4 NxS_UB_ConeBeamAngle.tif -192 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.6 NxS_UB_ConeBeamAngle.tif -193 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.8 NxS_UB_ConeBeamAngle.tif -194 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4 NxS_UB_ConeBeamAngle.tif -195 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.2 NxS_UB_ConeBeamAngle.tif -196 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.4 NxS_UB_ConeBeamAngle.tif -197 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.6 NxS_UB_ConeBeamAngle.tif -198 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.8 NxS_UB_ConeBeamAngle.tif -199 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5 NxS_UB_ConeBeamAngle.tif -200 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.2 NxS_UB_ConeBeamAngle.tif -201 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.4 NxS_UB_ConeBeamAngle.tif -202 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.6 NxS_UB_ConeBeamAngle.tif -203 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.8 NxS_UB_ConeBeamAngle.tif -204 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6 NxS_UB_ConeBeamAngle.tif -205 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.2 NxS_UB_ConeBeamAngle.tif -206 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.4 NxS_UB_ConeBeamAngle.tif -207 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.6 NxS_UB_ConeBeamAngle.tif -208 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.8 NxS_UB_ConeBeamAngle.tif -209 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7 NxS_UB_ConeBeamAngle.tif -210 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.2 NxS_UB_ConeBeamAngle.tif -211 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.4 NxS_UB_ConeBeamAngle.tif -212 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.6 NxS_UB_ConeBeamAngle.tif -213 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.8 NxS_UB_ConeBeamAngle.tif -214 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8 NxS_UB_ConeBeamAngle.tif -215 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.2 NxS_UB_ConeBeamAngle.tif -216 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.4 NxS_UB_ConeBeamAngle.tif -217 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.6 NxS_UB_ConeBeamAngle.tif -218 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.8 NxS_UB_ConeBeamAngle.tif -219 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9 NxS_UB_ConeBeamAngle.tif -220 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.2 NxS_UB_ConeBeamAngle.tif -221 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.4 NxS_UB_ConeBeamAngle.tif -222 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.6 NxS_UB_ConeBeamAngle.tif -223 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.8 NxS_UB_ConeBeamAngle.tif -224 6 8 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 10 NxS_UB_ConeBeamAngle.tif -225 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.05 NxS_UB_ConeBeamAngle.tif -226 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.1 NxS_UB_ConeBeamAngle.tif -227 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.2 NxS_UB_ConeBeamAngle.tif -228 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.3 NxS_UB_ConeBeamAngle.tif -229 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.4 NxS_UB_ConeBeamAngle.tif -230 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.5 NxS_UB_ConeBeamAngle.tif -231 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.6 NxS_UB_ConeBeamAngle.tif -232 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.7 NxS_UB_ConeBeamAngle.tif -233 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.8 NxS_UB_ConeBeamAngle.tif -234 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.9 NxS_UB_ConeBeamAngle.tif -235 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1 NxS_UB_ConeBeamAngle.tif -236 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.2 NxS_UB_ConeBeamAngle.tif -237 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.4 NxS_UB_ConeBeamAngle.tif -238 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.6 NxS_UB_ConeBeamAngle.tif -239 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.8 NxS_UB_ConeBeamAngle.tif -240 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2 NxS_UB_ConeBeamAngle.tif -241 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.2 NxS_UB_ConeBeamAngle.tif -242 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.4 NxS_UB_ConeBeamAngle.tif -243 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.6 NxS_UB_ConeBeamAngle.tif -244 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.8 NxS_UB_ConeBeamAngle.tif -245 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3 NxS_UB_ConeBeamAngle.tif -246 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.2 NxS_UB_ConeBeamAngle.tif -247 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.4 NxS_UB_ConeBeamAngle.tif -248 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.6 NxS_UB_ConeBeamAngle.tif -249 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.8 NxS_UB_ConeBeamAngle.tif -250 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4 NxS_UB_ConeBeamAngle.tif -251 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.2 NxS_UB_ConeBeamAngle.tif -252 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.4 NxS_UB_ConeBeamAngle.tif -253 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.6 NxS_UB_ConeBeamAngle.tif -254 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.8 NxS_UB_ConeBeamAngle.tif -255 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5 NxS_UB_ConeBeamAngle.tif -256 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.2 NxS_UB_ConeBeamAngle.tif -257 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.4 NxS_UB_ConeBeamAngle.tif -258 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.6 NxS_UB_ConeBeamAngle.tif -259 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.8 NxS_UB_ConeBeamAngle.tif -260 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6 NxS_UB_ConeBeamAngle.tif -261 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.2 NxS_UB_ConeBeamAngle.tif -262 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.4 NxS_UB_ConeBeamAngle.tif -263 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.6 NxS_UB_ConeBeamAngle.tif -264 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.8 NxS_UB_ConeBeamAngle.tif -265 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7 NxS_UB_ConeBeamAngle.tif -266 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.2 NxS_UB_ConeBeamAngle.tif -267 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.4 NxS_UB_ConeBeamAngle.tif -268 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.6 NxS_UB_ConeBeamAngle.tif -269 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.8 NxS_UB_ConeBeamAngle.tif -270 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8 NxS_UB_ConeBeamAngle.tif -271 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.2 NxS_UB_ConeBeamAngle.tif -272 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.4 NxS_UB_ConeBeamAngle.tif -273 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.6 NxS_UB_ConeBeamAngle.tif -274 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.8 NxS_UB_ConeBeamAngle.tif -275 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9 NxS_UB_ConeBeamAngle.tif -276 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.2 NxS_UB_ConeBeamAngle.tif -277 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.4 NxS_UB_ConeBeamAngle.tif -278 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.6 NxS_UB_ConeBeamAngle.tif -279 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.8 NxS_UB_ConeBeamAngle.tif -280 6 10 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 10 NxS_UB_ConeBeamAngle.tif -281 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.05 NxS_UB_ConeBeamAngle.tif -282 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.1 NxS_UB_ConeBeamAngle.tif -283 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.2 NxS_UB_ConeBeamAngle.tif -284 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.3 NxS_UB_ConeBeamAngle.tif -285 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.4 NxS_UB_ConeBeamAngle.tif -286 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.5 NxS_UB_ConeBeamAngle.tif -287 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.6 NxS_UB_ConeBeamAngle.tif -288 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.7 NxS_UB_ConeBeamAngle.tif -289 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.8 NxS_UB_ConeBeamAngle.tif -290 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.9 NxS_UB_ConeBeamAngle.tif -291 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1 NxS_UB_ConeBeamAngle.tif -292 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.2 NxS_UB_ConeBeamAngle.tif -293 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.4 NxS_UB_ConeBeamAngle.tif -294 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.6 NxS_UB_ConeBeamAngle.tif -295 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.8 NxS_UB_ConeBeamAngle.tif -296 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2 NxS_UB_ConeBeamAngle.tif -297 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.2 NxS_UB_ConeBeamAngle.tif -298 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.4 NxS_UB_ConeBeamAngle.tif -299 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.6 NxS_UB_ConeBeamAngle.tif -300 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.8 NxS_UB_ConeBeamAngle.tif -301 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3 NxS_UB_ConeBeamAngle.tif -302 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.2 NxS_UB_ConeBeamAngle.tif -303 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.4 NxS_UB_ConeBeamAngle.tif -304 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.6 NxS_UB_ConeBeamAngle.tif -305 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.8 NxS_UB_ConeBeamAngle.tif -306 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4 NxS_UB_ConeBeamAngle.tif -307 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.2 NxS_UB_ConeBeamAngle.tif -308 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.4 NxS_UB_ConeBeamAngle.tif -309 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.6 NxS_UB_ConeBeamAngle.tif -310 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.8 NxS_UB_ConeBeamAngle.tif -311 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5 NxS_UB_ConeBeamAngle.tif -312 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.2 NxS_UB_ConeBeamAngle.tif -313 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.4 NxS_UB_ConeBeamAngle.tif -314 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.6 NxS_UB_ConeBeamAngle.tif -315 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.8 NxS_UB_ConeBeamAngle.tif -316 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6 NxS_UB_ConeBeamAngle.tif -317 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.2 NxS_UB_ConeBeamAngle.tif -318 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.4 NxS_UB_ConeBeamAngle.tif -319 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.6 NxS_UB_ConeBeamAngle.tif -320 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.8 NxS_UB_ConeBeamAngle.tif -321 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7 NxS_UB_ConeBeamAngle.tif -322 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.2 NxS_UB_ConeBeamAngle.tif -323 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.4 NxS_UB_ConeBeamAngle.tif -324 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.6 NxS_UB_ConeBeamAngle.tif -325 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.8 NxS_UB_ConeBeamAngle.tif -326 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8 NxS_UB_ConeBeamAngle.tif -327 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.2 NxS_UB_ConeBeamAngle.tif -328 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.4 NxS_UB_ConeBeamAngle.tif -329 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.6 NxS_UB_ConeBeamAngle.tif -330 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.8 NxS_UB_ConeBeamAngle.tif -331 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9 NxS_UB_ConeBeamAngle.tif -332 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.2 NxS_UB_ConeBeamAngle.tif -333 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.4 NxS_UB_ConeBeamAngle.tif -334 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.6 NxS_UB_ConeBeamAngle.tif -335 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.8 NxS_UB_ConeBeamAngle.tif -336 6 12 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 10 NxS_UB_ConeBeamAngle.tif -337 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.05 NxS_UB_ConeBeamAngle.tif -338 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.1 NxS_UB_ConeBeamAngle.tif -339 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.2 NxS_UB_ConeBeamAngle.tif -340 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.3 NxS_UB_ConeBeamAngle.tif -341 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.4 NxS_UB_ConeBeamAngle.tif -342 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.5 NxS_UB_ConeBeamAngle.tif -343 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.6 NxS_UB_ConeBeamAngle.tif -344 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.7 NxS_UB_ConeBeamAngle.tif -345 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.8 NxS_UB_ConeBeamAngle.tif -346 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.9 NxS_UB_ConeBeamAngle.tif -347 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1 NxS_UB_ConeBeamAngle.tif -348 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.2 NxS_UB_ConeBeamAngle.tif -349 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.4 NxS_UB_ConeBeamAngle.tif -350 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.6 NxS_UB_ConeBeamAngle.tif -351 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.8 NxS_UB_ConeBeamAngle.tif -352 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2 NxS_UB_ConeBeamAngle.tif -353 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.2 NxS_UB_ConeBeamAngle.tif -354 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.4 NxS_UB_ConeBeamAngle.tif -355 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.6 NxS_UB_ConeBeamAngle.tif -356 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.8 NxS_UB_ConeBeamAngle.tif -357 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3 NxS_UB_ConeBeamAngle.tif -358 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.2 NxS_UB_ConeBeamAngle.tif -359 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.4 NxS_UB_ConeBeamAngle.tif -360 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.6 NxS_UB_ConeBeamAngle.tif -361 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.8 NxS_UB_ConeBeamAngle.tif -362 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4 NxS_UB_ConeBeamAngle.tif -363 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.2 NxS_UB_ConeBeamAngle.tif -364 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.4 NxS_UB_ConeBeamAngle.tif -365 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.6 NxS_UB_ConeBeamAngle.tif -366 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.8 NxS_UB_ConeBeamAngle.tif -367 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5 NxS_UB_ConeBeamAngle.tif -368 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.2 NxS_UB_ConeBeamAngle.tif -369 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.4 NxS_UB_ConeBeamAngle.tif -370 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.6 NxS_UB_ConeBeamAngle.tif -371 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.8 NxS_UB_ConeBeamAngle.tif -372 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6 NxS_UB_ConeBeamAngle.tif -373 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.2 NxS_UB_ConeBeamAngle.tif -374 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.4 NxS_UB_ConeBeamAngle.tif -375 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.6 NxS_UB_ConeBeamAngle.tif -376 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.8 NxS_UB_ConeBeamAngle.tif -377 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7 NxS_UB_ConeBeamAngle.tif -378 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.2 NxS_UB_ConeBeamAngle.tif -379 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.4 NxS_UB_ConeBeamAngle.tif -380 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.6 NxS_UB_ConeBeamAngle.tif -381 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.8 NxS_UB_ConeBeamAngle.tif -382 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8 NxS_UB_ConeBeamAngle.tif -383 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.2 NxS_UB_ConeBeamAngle.tif -384 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.4 NxS_UB_ConeBeamAngle.tif -385 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.6 NxS_UB_ConeBeamAngle.tif -386 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.8 NxS_UB_ConeBeamAngle.tif -387 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9 NxS_UB_ConeBeamAngle.tif -388 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.2 NxS_UB_ConeBeamAngle.tif -389 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.4 NxS_UB_ConeBeamAngle.tif -390 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.6 NxS_UB_ConeBeamAngle.tif -391 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.8 NxS_UB_ConeBeamAngle.tif -392 6 14 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 10 NxS_UB_ConeBeamAngle.tif -393 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.05 NxS_UB_ConeBeamAngle.tif -394 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.1 NxS_UB_ConeBeamAngle.tif -395 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.2 NxS_UB_ConeBeamAngle.tif -396 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.3 NxS_UB_ConeBeamAngle.tif -397 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.4 NxS_UB_ConeBeamAngle.tif -398 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.5 NxS_UB_ConeBeamAngle.tif -399 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.6 NxS_UB_ConeBeamAngle.tif -400 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.7 NxS_UB_ConeBeamAngle.tif -401 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.8 NxS_UB_ConeBeamAngle.tif -402 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 0.9 NxS_UB_ConeBeamAngle.tif -403 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1 NxS_UB_ConeBeamAngle.tif -404 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.2 NxS_UB_ConeBeamAngle.tif -405 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.4 NxS_UB_ConeBeamAngle.tif -406 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.6 NxS_UB_ConeBeamAngle.tif -407 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 1.8 NxS_UB_ConeBeamAngle.tif -408 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2 NxS_UB_ConeBeamAngle.tif -409 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.2 NxS_UB_ConeBeamAngle.tif -410 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.4 NxS_UB_ConeBeamAngle.tif -411 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.6 NxS_UB_ConeBeamAngle.tif -412 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 2.8 NxS_UB_ConeBeamAngle.tif -413 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3 NxS_UB_ConeBeamAngle.tif -414 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.2 NxS_UB_ConeBeamAngle.tif -415 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.4 NxS_UB_ConeBeamAngle.tif -416 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.6 NxS_UB_ConeBeamAngle.tif -417 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 3.8 NxS_UB_ConeBeamAngle.tif -418 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4 NxS_UB_ConeBeamAngle.tif -419 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.2 NxS_UB_ConeBeamAngle.tif -420 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.4 NxS_UB_ConeBeamAngle.tif -421 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.6 NxS_UB_ConeBeamAngle.tif -422 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 4.8 NxS_UB_ConeBeamAngle.tif -423 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5 NxS_UB_ConeBeamAngle.tif -424 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.2 NxS_UB_ConeBeamAngle.tif -425 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.4 NxS_UB_ConeBeamAngle.tif -426 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.6 NxS_UB_ConeBeamAngle.tif -427 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 5.8 NxS_UB_ConeBeamAngle.tif -428 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6 NxS_UB_ConeBeamAngle.tif -429 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.2 NxS_UB_ConeBeamAngle.tif -430 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.4 NxS_UB_ConeBeamAngle.tif -431 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.6 NxS_UB_ConeBeamAngle.tif -432 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 6.8 NxS_UB_ConeBeamAngle.tif -433 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7 NxS_UB_ConeBeamAngle.tif -434 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.2 NxS_UB_ConeBeamAngle.tif -435 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.4 NxS_UB_ConeBeamAngle.tif -436 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.6 NxS_UB_ConeBeamAngle.tif -437 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 7.8 NxS_UB_ConeBeamAngle.tif -438 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8 NxS_UB_ConeBeamAngle.tif -439 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.2 NxS_UB_ConeBeamAngle.tif -440 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.4 NxS_UB_ConeBeamAngle.tif -441 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.6 NxS_UB_ConeBeamAngle.tif -442 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 8.8 NxS_UB_ConeBeamAngle.tif -443 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9 NxS_UB_ConeBeamAngle.tif -444 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.2 NxS_UB_ConeBeamAngle.tif -445 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.4 NxS_UB_ConeBeamAngle.tif -446 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.6 NxS_UB_ConeBeamAngle.tif -447 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 9.8 NxS_UB_ConeBeamAngle.tif -448 6 16 0.002 301 1089 0 Mono 50 1 VOID 0 10 0.1 10 NxS_UB_ConeBeamAngle.tif diff --git a/SimulateFromList/SimulateFromList.py b/SimulateFromList/SimulateFromList.py deleted file mode 100644 index addd95e..0000000 --- a/SimulateFromList/SimulateFromList.py +++ /dev/null @@ -1,146 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Tue May 31 11:04:16 2022 - -@author: dschumac - -The aRTist.py library needs to be present! -This is an example scipt which shows how to use a spreadsheet to simulate a bunch of images. The corresponding spreadsheet for this script is as a tab-separeted text-file ("ListOfSimulations.txt"). -Each row in the spreadsheet corresponds to a single aRTist simulation. The colums represent the individual simulation parameters. -The given comlumns need to be adapted according to the simulation task, as the script needs to be! - -""" - -import pandas as pd -import os -import sys -sys.path.insert(1, '[Your python library directory]/aRTist-PythonLib') -import aRTist -import math - - - - -######################## Options ############################### -''' aRTist connection ''' -HOST = "127.0.0.1" # localhost -PORT = 3658 # port @HOST -buffer = 1024 # package size -timeout = 10 # TimeOut in sec - - - -''' Path ''' -#Cone Beam -path_script = "[Your directory]/ListOfSimulations.txt" -path_save_images = "[Your directory]/Images_UB_ConeBeam/" - - - - -############################################################################## -''' Read Script file''' - -data = pd.read_csv(path_script, sep="\t", encoding='mbcs') #Read data -data.dropna(axis=0, how='all', inplace=True) #Delete empty rows -data["Filename"].fillna('NA', inplace = True) #Replace empty file names with "NA" -data_sort = data.sort_values(by=['ETA', 'ID']) #sort by ID and spot size - - -############################################################################### -''' Connect to aRTist ''' -Con = aRTist.Connection(HOST, PORT, buffer, timeout) - -############################################################################### -aRTist.Connection.send(Con, aRTist.SETUP_Preview(1)) - -"""Source Setup""" -SourceZ = 10 #Random SZ pos, outside of object -SourcekV = data_sort['Source U'].iloc[0] -SourcemA = data_sort['Source I'].iloc[0] -SourceType = data_sort['Source Type'].iloc[0] -SourceFilterMat = data_sort['Source Filter Material'].iloc[0] -SourceFilterTh = data_sort['Source Filter Thickness'].iloc[0] -sampling = data_sort['Sampling'].iloc[0] - -aRTist.Connection.send(Con, aRTist.SETUP_source(SourceZ, SourcekV, SourcemA, SourceType, SourceFilterMat, SourceFilterTh)) -aRTist.Connection.send(Con, aRTist.SETUP_SourceSampling(sampling)) - - -eta_out = -1 # for checking if ETA has changed -FS_out = -1 # for checking if FS has changed - -for index, row in data_sort.iterrows(): - - Fname = data_sort.loc[index, 'Filename'] - Fname = os.path.splitext(Fname)[0] #extract name without extension - - """Detector position and pixel size""" - PixelSize = data_sort.loc[index, 'Detector pixel size'] - - - """Spot Setup""" - FS = data_sort.loc[index, 'Spot size'] - eta = data_sort.loc[index, 'ETA'] - SpotRes = data_sort.loc[index, 'Spot resolution'] - - """Scene Setup""" - LG = data_sort.loc[index, 'LG'] - name = 'LG{:.0f}'.format(LG) # create object name similar to list in aRTist - Obj = aRTist.Connection.send(Con, aRTist.get_ObjID(name)).split() # Query Object ID from name - OID = Obj[1] # isolate Object ID - aRTist.Connection.send(Con, aRTist.set_vis_AllParts("off")) # set visibility of all objects off - aRTist.Connection.send(Con, aRTist.set_vis(OID, 'on')) # activate object with only - - """Calc magnification, source and detector Z pos""" - cba = data_sort.loc[index, 'Cone beam angle'] # Read cone beam angle - CBA = cba*math.pi/180 # Degree to radian - - GW = LG*9 # group width for 5 lines and 4 gaps in um!! - N = data_sort.loc[index, 'N'] # No. of pixels representing unsharpness - Mag = N*PixelSize/FS+1 # Magnification - SZ = (GW/1000) / (2 * math.sin(CBA)) # Source Z position (SOD) - DetZ = -SZ * (Mag-1) # Detector Z position (SOD) - aRTist.Connection.send(Con, aRTist.set_position('S', 0, 0, SZ)) - - '''Set object thickness (and other dimensions)''' - sizeX = GW*10/3000 - sizeY = GW/1000 - sizeZ = data_sort.loc[index, 'LG Thickness']/1000 - aRTist.Connection.send(Con, aRTist.resize(OID, sizeX, sizeY, sizeZ)) - - - """Calc Detector Size""" - ePS = PixelSize*1000 / Mag # effective pixel size - DetSizeX = int(GW / ePS * 1.5) # Detector length 1.5x group width to limit calc and analysis time - DetSizeY = int(GW / ePS * 2.5) # Detector widht 2.5x group width to allow for background fitting - aRTist.Connection.send(Con, aRTist.SETUP_detector(DetZ, 0, DetSizeX, DetSizeY, PixelSize, 'max', 50000)) - - - if eta != eta_out or FS != FS_out: # Only calc new source when ETA or FS have changed - aRTist.Connection.send(Con, aRTist.SETUP_CalcFocalspot(FS, FS, eta, SpotRes)) - - - aRTist.Connection.send(Con, aRTist.Clear_FF()) - aRTist.Connection.send(Con, aRTist.AutoAcq_FF(1)) - eta_out = eta - FS_out = FS - - aRTist.Connection.send(Con, aRTist.RenderPreview()) - - - #Print name to update user - # print('ID={}, ETA={:.1f}; LG={:.0f} um; Spot={:.1f} um; Sampling={:.0f}; N={:.1f}; {}'.format(index, eta, LG, FS*1000, sampling, N, Fname)) - print('ID={}, CB={:.2f}°; ETA={:.1f}; LG={:.0f} um; Thickness {:.0f} um; Spot={:.1f} um; Sampling={}; N={:.1f}; {}'.format(index, cba, eta, LG, sizeZ*1000, FS*1000, sampling, N, Fname)) - ResFname = '{}_CB{:.2f}_ETA{:.1f}_LG{:.0f}_Th{:.0f}_FS{:.1f}um_Sampling{}_N{:.1f}.tif'.format(Fname, cba, eta, LG, sizeZ*1000, FS*1000, sampling, N) - ResPath = path_save_images + ResFname - - - aRTist.Connection.send(Con, aRTist.make_image()) - aRTist.Connection.send(Con, aRTist.save_image(ResPath)) - - - -############################################################################### -''' Close Connection to aRTist''' -Con.S.close() diff --git a/Standalones/ParticlesAndPores/CreateParticlePoreMatrix.py b/Standalones/ParticlesAndPores/CreateParticlePoreMatrix.py deleted file mode 100644 index 6e5d4db..0000000 --- a/Standalones/ParticlesAndPores/CreateParticlePoreMatrix.py +++ /dev/null @@ -1,316 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Fri Oct 30 16:20:50 2020 - -@author: David Schumacher -""" -import socket -import numpy as np -import csv - -########################### Options #################################### -''' aRTist connection ''' -HOST = "127.0.0.1" # localhost -PORT = 3658 # port @HOST -BUFFER_SIZE = 1024 # package size -timeout = 10 # TimeOut in sec - -''' aRTist setup ''' -SolidModNo = 16 # Number of module "Solid" in aRTist (Modules/XX. Solid) - -''' Particles/Pores ''' -D_max = 100 # max particle diameter in micrometer -P_max = 30 # max pore diameter in micrometer -P_min = 5 # min pore diameter in micrometer - -N_ParX = 2 # No. of particles in X-direction -N_ParY = 2 # No. of particles in X-direction - -Mat_par = "{Fe}" # Material of Particle -Mat_pore = "{VOID}" # Material of Pore - - -MAG = 50 # magnification -SDD = 400 # source-detector distance in mm -pitch = 0.1 # ative pixel size (pitch) of the detector in mm -DBorder = 1.5 # detector border (1/2), Factor (particle size) - -DetX = 500 # Detector resolution X -DetY = 500 # Detector resolution Y - -kV = 150 # Voltage of X-ray source -mA = 100 # Current of X-ray source - -''' Paths ''' -path_aRTist_scene = "I:/Simulations/TMP/Pores/Pore_Matrix_Scene.aRTist" -path_save = "I:/Simulations/TMP/Pores/Coordinates_" - - - -error = 0 - -########################### aRTist functions (to be replaced by library!) ################################# -''' Communication with aRTist ''' -def aRTist_connect(): - S = socket.socket() # Create socket (for TCP) - S.connect((HOST, PORT)) # Connect to aRTist - S.settimeout(timeout) - return S - -def aRTist_sent(x): - total = "" - for i in range(len(x)): - # print(i+1, "of", len(x), " commands send") - # print(x[i]) - S.send(x[i].encode()) - total = total + aRTist_listen(1) - return total - -def aRTist_listen(command_no): - total = "" - stop = False - if (command_no == 0): - S.settimeout(0.2) - while (not stop):# and ("SUCCESS" not in total) and ("ERROR" not in total): # as long as server doesn't respond and doesn't contain "SUCCESS" - try: - msg = S.recv(BUFFER_SIZE).decode() # - except socket.timeout as e: - err = e.args[0] - if err == "timed out": - print("Timeout\n") - stop = True - continue - else: - if ("SUCCESS" in msg): - total = total + msg - # print(msg) - stop = True - continue - elif ("ERROR" in msg): - total = total + msg - # print(msg) - stop = True - global error - error = error + 1 - continue - else: - # print(msg) - if (command_no == 0): - print(msg) - total = total + msg - S.settimeout(timeout) - return total - -''' aRTist specific commands ''' -def aRTist_setup(Path): - STR = ["""FileIO::OpenAny """+ Path +"""; -"""] - return STR - -def aRTist_SETUP_detector(x, y, px): - STR = ["""set ::Xdetector(Type) {flat panel}; -""","""set ::Xsetup_private(DGauto) {Size}; -""","""set ::Xsetup(DetectorPixelX) """+ str((int(x))) +"""; -""","""set ::Xsetup(DetectorPixelY) """+ str((int(y))) +"""; -""","""set ::Xsetup_private(DGdx) """+ str(px) +"""; -""","""set ::Xsetup_private(DGdy) """+ str(px) +"""; -""","""set ::Xdetector(AutoD) {max}; -""","""set ::Xdetector(RefGV) 50000; -""","""::XDetector::UpdateGeometry 1; -"""] - return STR - -def aRTist_SETUP_source(pos, kV, mA): - STR = ["""set ::Xsetup(SourceSampling) {point}; -""","""set ::Xsource(Exposure) """+ str(mA) +"""; -""","""set ::Xsource(Tube) {Mono}; -""","""set ::Xsource(Voltage) """+ str(kV) +"""; -""","""::PartList::Invoke S SetPosition 0 0 """+ str(pos) +"""; -""","""::PartList::Invoke S SetRefPos 0 0 """+ str(pos) +"""; -""","""set ::Xdetector(FFCorrRun) 0; -""","""XDetector::FFCorrClearCmd; -""","""::XSource::spectrumOK; -"""] # set ::Engine::RenderPreview 0; - return STR - -def aRTist_SETUP_FFcorr(): - STR = ["""::XDetector::FFCorrGenCmd; -"""] - return STR - -def aRTist_create_sphere(R): - R = 2 * R - STR = ["""::Modules::Run Solid; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(Type) {ellipsoid}; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(Equilateral) 1; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(X) """+ str(R) +"""; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(PhiResolution) 80; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(ThetaResolution) 80; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(GridEllipsoid) 1; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(VolumeCorrect) 1; -""","""::Modules::Module""" +str(SolidModNo)+"""::GenerateCmd; -"""] - return STR - -def aRTist_set_material(ID, mat): - STR = ["""::PartList::Set """+ str(ID) +""" Material """+ mat +"""; -"""] - return STR - -def aRTist_set_position(ID, x, y, z): - STR = ["""::PartList::Invoke """+ str(ID) +""" SetPosition """+ str(x) +""" """+ str(y) +""" """+ str(z) +"""; -""","""::PartList::Invoke """+ str(ID) +""" SetRefPos """+ str(x) +""" """+ str(y) +""" """+ str(z) +"""; -"""] - return STR - -def aRTist_translate(ID, x, y, z): - STR = ["""::PartList::Invoke """+ str(ID) +""" Translate world """+ str(x) +""" """+ str(y) +""" """+ str(z) +"""; -"""] - return STR - - -def aRTist_vis_off(): - STR = ["""::PartList::Set parts Visible off; -"""] - return STR - -def aRTist_vis_on(ID): - STR = ["""::PartList::Set """+str(ID)+""" Visible on; -"""] - return STR - -def aRTist_resize(ID, size): - STR = ["""::PartList::Invoke """+str(ID)+""" SetSize """+str(size)+""" """+str(size)+""" """+str(size)+"""; -"""] - return STR - -def aRTist_make_image(): - STR = ["""::Engine::StartStopCmd; -"""] - return STR - -def aRTist_save_image(Path): - STR = ["""::Modules::Execute ImageViewer Save16bit """+ Path +""" 1; -"""] - return STR - - - -########################## Conversions ################################ -''' Particle/Pore ''' - -R_max = D_max / 2 / 1000 # max. particle radius in mm -r_max = P_max / 2 / 1000 # max. pore radius in mm -r_min = P_min / 2 / 1000 # min. pore radius in mm - -''' Detector/Source ''' -OZ = SDD / MAG # position of object (in Z-direction) -OZ = SDD - OZ -VX = pitch / MAG # voxel size , i.e. eff. pixel size -DETxy = (DBorder * D_max) / VX / 1000 # detector size (square) in pixel - -P_xy = (DETxy / 2) * VX * 0.9 # origin of particle range[x][y] with 10% border - -############################################################################### - -P_count = N_ParX*N_ParY #No. of Particles/Pores - - -############################################################################### -''' Connect to aRTist ''' -S = aRTist_connect() - -aRTist_listen(0) - -############################################################################### -''' SETUP aRTist scene ''' -print("SETUP aRTist scene") -aRTist_sent(aRTist_setup(path_aRTist_scene)) -print("SETUP Detector aRTist-Scene") -aRTist_sent(aRTist_SETUP_detector(DetX, DetY, pitch)) -print("SETUP Source aRTist-Scene") -aRTist_sent(aRTist_SETUP_source(SDD, kV, mA)) -print("SETUP FFcorr aRTist-Scene") -aRTist_sent(aRTist_SETUP_FFcorr()) -aRTist_sent(["""set ::Xdetector(FFCorrRun) 1; -"""]) #to check!! -print("SETUP FINISH aRTist-Scene") - -############################################################################### -'''Calc Particle/Pore positions:''' -P_ID, P_RAD, P_XYZ, p_RAD, p_ID = [],[],[],[],[] # List of all particles/pores - -n = 0 #loop count -for i in range(N_ParY): - for ii in range(N_ParX): - n += 1 #increment n by 1 - if (i % 2): #ii is odd - X = 2*R_max*ii + R_max - else: #ii is even (incl. 0) - X = 2*R_max*ii # particle position x - - Y = np.sqrt(3*R_max**2)*i # particle position x - - P_XYZ.append([X, Y, OZ]) - P_ID.append(2*n-1) # Particle-ID - p_ID.append(2*n) # Pore-ID - P_RAD.append(R_max) - -print(P_ID) -print(p_ID) -print(P_XYZ) - -############################################################################## -'''Calc Pore distribution:''' -p_RAD = list(np.linspace(r_min, r_max, num=P_count)) #list of pore radii - -############################################################################## -''' Create particles and pores in aRTist ''' -n = -1 #loop count -for i in range(N_ParY): - for ii in range(N_ParX): - n += 1 #increment n by 1 - # Particle - print("Create Particle ", n+1 , "of", P_count) - aRTist_sent(aRTist_create_sphere(R_max)) - aRTist_sent(aRTist_set_material(P_ID[n], Mat_par)) - aRTist_sent(aRTist_set_position(P_ID[n], P_XYZ[n][0], P_XYZ[n][1], P_XYZ[n][2])) - - - # Pore - aRTist_sent(aRTist_create_sphere(p_RAD[n])) - aRTist_sent(aRTist_set_material(p_ID[n], Mat_pore)) - aRTist_sent(aRTist_set_position(p_ID[n], P_XYZ[n][0], P_XYZ[n][1], P_XYZ[n][2])) - - if (i == range(N_ParY)[-1]): - aRTist_sent(["""::Modules::Module""" +str(SolidModNo)+"""::Close; - """]) - -############################################################################## -'Center middle particle at [0,0,z]' - -Shift = [] -for i in range(len(P_XYZ[0])): - diff = (P_XYZ[0][i] - P_XYZ[-1][i]) / 2 - Shift.append(diff) - -aRTist_sent(aRTist_translate('Parts', Shift[0], Shift[1] , Shift[2])) - - - -####################### Save coordinates in CSV #################################### -header = ["Particle ID", "Particle Diameter", "Pore ID", "Pore Diameter", "X", "Y", "Z"] - -with open(path_save +"data.csv", "w", newline ='') as file: - write = csv.writer(file) - write.writerow(header) - - for i in range(P_count): - row = [str(P_ID[i]), str(2*P_RAD[i]), str(p_ID[i]), str(2*p_RAD[i]), str(P_XYZ[i][0]), str(P_XYZ[i][1]), str(P_XYZ[i][2])] - write.writerow(row) - - -############################################################################### -''' Close Connection to aRTist''' -S.close() - \ No newline at end of file diff --git a/Standalones/ParticlesAndPores/Create_SingleParticle+Pores.py b/Standalones/ParticlesAndPores/Create_SingleParticle+Pores.py deleted file mode 100644 index e3e7f50..0000000 --- a/Standalones/ParticlesAndPores/Create_SingleParticle+Pores.py +++ /dev/null @@ -1,328 +0,0 @@ -# -*- coding: utf-8 -*- -""" -Created on Tue Aug 13 19:30:16 2019 -Creates and transates particles/pores -ONLY for 0 to 1 pore, faster and less expensive than creating new objects each time. -@authors: Alexander Funk, David Schumacher -""" - -import socket -import random -import numpy as np -import math -from time import sleep - -############################### Options ####################################### -''' Connection ''' -HOST = "127.0.0.1" # localhost -PORT = 3658 # port @HOST -BUFFER_SIZE = 1024 # package size -timeout = 10 # TimeOut in sec - -''' aRTist Module ''' -SolidModNo = 17 # Number of module "Solid" in aRTist (Modules/XX. Solid) - -''' Particles/Pores ''' -D_max = 100 # max particle diameter in micrometer -D_min = 90 # min particle diameter in micrometer -P_max = 45 # max pore diameter in micrometer -P_min = 10 # min pore diameter in micrometer -N_Par = 10 # No. of particles to be created -pores_max = 5 # max. no. of pores per particle -pores_min = 1 # min. no. of pores per particle -space = 5 / 1000 # space to particle boundary - -''' X-Ray Setup ''' -MAG = 200 # magnification -SDD = 400 # source-detector distance in mm -pitch = 0.1 # native pixel size (pitch) of the detector in mm -DBorder = 1.5 # detector border (1/2), Factor (particle size) - -kV = 15 # Voltage of X-ray source -mA = 100 # Current of X-ray source - -''' Paths ''' -path_aRTist_scene = "I:/Simulations/TMP/Pores/Single_Pore_Scene.aRTist" -path_save_images = "I:/Simulations/TMP/Pores/img_" - - -error = 0 - -############### aRTist functions (to be replaced by library!) ################# -''' Communication with aRTist ''' -def aRTist_connect(): - S = socket.socket() # Create socket (for TCP) - S.connect((HOST, PORT)) # Connect to aRTist - S.settimeout(timeout) - return S - -def aRTist_sent(x): - total = "" - for i in range(len(x)): - # print(i+1, "of", len(x), " commands send") - # print(x[i]) - S.send(x[i].encode()) - total = total + aRTist_listen(1) - return total - -def aRTist_listen(command_no): - total = "" - stop = False - if (command_no == 0): - S.settimeout(0.2) - while (not stop):# and ("SUCCESS" not in total) and ("ERROR" not in total): # as long as server doesn't respond and doesn't contain "SUCCESS" - try: - msg = S.recv(BUFFER_SIZE).decode() # - except socket.timeout as e: - err = e.args[0] - if err == "timed out": - print("Timeout\n") - stop = True - continue - else: - if ("SUCCESS" in msg): - total = total + msg - # print(msg) - stop = True - continue - elif ("ERROR" in msg): - total = total + msg - # print(msg) - stop = True - global error - error = error + 1 - continue - else: - # print(msg) - if (command_no == 0): - print(msg) - total = total + msg - S.settimeout(timeout) - return total - -''' aRTist specific commands ''' -def aRTist_setup(Path): - STR = ["""FileIO::OpenAny """+ Path +"""; -"""] - return STR - -def aRTist_SETUP_detector(x, y, px): - STR = ["""set ::Xdetector(Type) {flat panel}; -""","""set ::Xsetup_private(DGauto) {Size}; -""","""set ::Xsetup(DetectorPixelX) """+ str((int(x))) +"""; -""","""set ::Xsetup(DetectorPixelY) """+ str((int(y))) +"""; -""","""set ::Xsetup_private(DGdx) """+ str(px) +"""; -""","""set ::Xsetup_private(DGdy) """+ str(px) +"""; -""","""set ::Xdetector(AutoD) {max}; -""","""set ::Xdetector(RefGV) 50000; -""","""::XDetector::UpdateGeometry 1; -"""] - return STR - -def aRTist_SETUP_source(pos, kV, mA): - STR = ["""set ::Xsetup(SourceSampling) {point}; -""","""set ::Xsource(Exposure) """+ str(mA) +"""; -""","""set ::Xsource(Tube) {Mono}; -""","""set ::Xsource(Voltage) """+ str(kV) +"""; -""","""::PartList::Invoke S SetPosition 0 0 """+ str(pos) +"""; -""","""::PartList::Invoke S SetRefPos 0 0 """+ str(pos) +"""; -""","""set ::Xdetector(FFCorrRun) 0; -""","""XDetector::FFCorrClearCmd; -""","""::XSource::spectrumOK; -"""] # set ::Engine::RenderPreview 0; - return STR - -def aRTist_SETUP_FFcorr(): - STR = ["""::XDetector::FFCorrGenCmd; -"""] - return STR - -def aRTist_create_sphere(R): - R = 2 * R - STR = ["""::Modules::Run Solid; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(Type) {ellipsoid}; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(Equilateral) 1; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(X) """+ str(R) +"""; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(PhiResolution) 80; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(ThetaResolution) 80; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(GridEllipsoid) 1; -""","""set ::Modules::Module""" +str(SolidModNo)+"""::Solid(VolumeCorrect) 1; -""","""::Modules::Module""" +str(SolidModNo)+"""::GenerateCmd; -"""] - return STR - -def aRTist_set_material(ID, mat): - STR = ["""::PartList::Set """+ str(ID) +""" Material """+ mat +"""; -"""] - return STR - -def aRTist_translate(ID, x, y, z): - STR = ["""::PartList::Invoke """+ str(ID) +""" SetPosition """+ str(x) +""" """+ str(y) +""" """+ str(z) +"""; -""","""::PartList::Invoke """+ str(ID) +""" SetRefPos """+ str(x) +""" """+ str(y) +""" """+ str(z) +"""; -"""] - return STR - -def aRTist_vis_off(): - STR = ["""::PartList::Set 1 Visible off; -""","""::PartList::Set 2 Visible off; -"""] - return STR - -def aRTist_vis_on(ID): - STR = ["""::PartList::Set """+str(ID)+""" Visible on; -"""] - return STR - -def aRTist_resize(ID, size): - STR = ["""::PartList::Invoke """+str(ID)+""" SetSize """+str(size)+""" """+str(size)+""" """+str(size)+"""; -"""] - return STR - -def aRTist_make_image(): - STR = ["""::Engine::StartStopCmd; -"""] - return STR - -def aRTist_save_image(Path): - STR = ["""::Modules::Execute ImageViewer Save16bit """+ Path +""" 1; -"""] - return STR - - -# def aRTist_fire(): - # STR = ["""::Modules::Module""" +str(SolidModNo)+"""::GenerateCmd; -# """] -# ::Modules::Module""" +str(SolidModNo)+"""::Close;" - # return STR - -########################## Conversions ################################ -''' Particle/Pore ''' -R_max = D_max / 2 / 1000 # max. particle radius in mm -R_min = D_min / 2 / 1000 # min. particle radius in mm -r_max = P_max / 2 / 1000 # max. pore radius in mm -r_min = P_min / 2 / 1000 # min. pore radius in mm - -''' Detector/Source ''' -OZ = SDD / MAG # position of object (in Z-direction) -OZ = SDD - OZ -VX = pitch / MAG # voxel size , i.e. eff. pixel size -DETxy = (DBorder * D_max) / (VX * 1000) # detector size (square) in pixel - -P_xy = (DETxy / 2) * VX * 0.9 # origin of particle range[x][y] with 10% border - -############################################################################### -''' Generation of random variables and calculate objects (paricles+pores) ''' -P_ID, P_RAD, P_XYZ, p_ANZ, p_RAD, p_XYZ = [],[],[],[],[],[] # List of all particles/pores -R = np.array(range(N_Par), dtype=np.float) -for i in range(N_Par): - R[i] = round(random.uniform(R_min, R_max),3) # particle radius in mm - X = round(random.uniform(-(P_xy-R[i]), (P_xy-R[i])),3) # particle position x - Y = round(random.uniform(-(P_xy-R[i]), (P_xy-R[i])),3) # particle position y - print('Particle',i ,' RADIUS =',R[i] ,'mm') - P_ID.append(i) - P_RAD.append(R[i]) - P_XYZ.append([X, Y, OZ]) - pores = random.randint(pores_min, pores_max) # random no. of pores - r = [] #np.array(range(pores), dtype=np.float) - p_xyz = [] - for ii in range(pores): - r.append(round(random.uniform(r_min, r_max),3)) # random pore radius in mm - print('Particle',i ,' Pore',ii ,' RADIUS =', r[ii],'mm') - - ''' Generate coordinates for pore ''' - R2 = round(R[i] - space - r[ii],3) # max. sphere radius with R2+pore in sphere R - # print(R2) - R3 = round(random.uniform(0, R2),3) # sphere with random radius in R2 - theta = random.uniform(0, math.pi) - phi = random.uniform(0, 2*math.pi) - # print(theta, phi) - p_x = round((X + R3 * math.sin(theta) * math.cos(phi)),3) - p_y = round((Y + R3 * math.sin(theta) * math.sin(phi)),3) - p_z = round((OZ + R3 * math.cos(theta)),3) - p_xyz.append([p_x, p_y, p_z]) - p_ANZ.append(pores) - p_RAD.append(r) - p_XYZ.append(p_xyz) - -print(P_RAD) -print(P_XYZ) -print(p_RAD) -print(p_XYZ) -print(p_ANZ) - -###################### Save coordinates in CSV ########################### -with open(path_save_images +"data.csv", "w+") as file: - STR = "Particle_ID, P_RADIUS, P_x, P_y, P_z, No. of pores, Pore_ID, p_RADIUS, p_x, p_y, p_z" - file.write(STR + "\n") - for i in range(N_Par): - STR = ""+str(P_ID[i])+", "+str(P_RAD[i])+", "+str(P_XYZ[i][0])+", "+str(P_XYZ[i][1])+", "+str(P_XYZ[i][2]) - if p_ANZ[i] == 0: - STR = STR + ", 0, , , , , " - file.write(STR + "\n") - elif p_ANZ[i] > 0: - STR = STR + ", " +str(p_ANZ[i]) - for ii in range(p_ANZ[i]): - STR2 = STR +", "+str(ii)+", "+str(p_RAD[i][ii])+", "+str(p_XYZ[i][ii][0])+", "+str(p_XYZ[i][ii][1])+", "+str(p_XYZ[i][ii][2]) - file.write(STR2 + "\n") - -############################################################################### -''' Connect to aRTist ''' -S = aRTist_connect() - -aRTist_listen(0) - -############################################################################### -''' SETUP aRTist scene ''' -print("SETUP aRTist scene") -aRTist_sent(aRTist_setup(path_aRTist_scene)) -print("SETUP Detector aRTist-Scene") -aRTist_sent(aRTist_SETUP_detector(DETxy, DETxy, pitch)) -print("SETUP Source aRTist-Scene") -aRTist_sent(aRTist_SETUP_source(SDD, kV, mA)) -print("SETUP FFcorr aRTist-Scene") -aRTist_sent(aRTist_SETUP_FFcorr()) -aRTist_sent(["""set ::Xdetector(FFCorrRun) 1; -"""]) -print("SETUP FINISH aRTist-Scene") - -############################################################################### -''' Create particles and pores in aRTist, save image ''' -# Create two dummy spheres -aRTist_sent(aRTist_create_sphere(R_max)) -aRTist_sent(aRTist_create_sphere(r_max)) -aRTist_sent(aRTist_set_material(1, "{Ti}")) -aRTist_sent(aRTist_set_material(2, "{void}")) -#aRTist_sent(["""::Modules::Module""" +str(SolidModNo)+"""::Close; -#"""]) - -# translate spheres -for i in range(N_Par): - # particle - print("Create Particle ", i , "of", N_Par) - aRTist_sent(aRTist_vis_off()) - aRTist_sent(aRTist_vis_on(1)) - aRTist_sent(aRTist_resize(1, (2*P_RAD[i]))) - aRTist_sent(aRTist_translate(1, P_XYZ[i][0], P_XYZ[i][1], P_XYZ[i][2])) - - # pores - if p_ANZ[i] > 0: - aRTist_sent(aRTist_vis_on(2)) - aRTist_sent(aRTist_resize(2, (2*p_RAD[i][0]))) - aRTist_sent(aRTist_translate(2, p_XYZ[i][0][0], p_XYZ[i][0][1], p_XYZ[i][0][2])) - # for ii in range(p_ANZ[i]): - # acquire image - aRTist_sent(aRTist_make_image()) - # save image - aRTist_sent(aRTist_save_image((path_save_images + str(i).zfill(5) +".tif"))) - - - -############################################################################### -''' Timer for Debug ''' -for i in range(5): - print("wait ",i ," s") - sleep(1) -print("FINISH!", error, "aRTist Errors") -############################################################################### -''' Close Connection to aRTist''' -S.close() diff --git a/Standalones/ParticlesAndPores/Pore_Matrix_Scene.aRTist b/Standalones/ParticlesAndPores/Pore_Matrix_Scene.aRTist deleted file mode 100644 index d2b7087fe5c3a738dfb40e905685bb10e81aa3b1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 492841 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 z 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 z
    zkA*?oM808yavt_v%G{;*D=del96xd-VHK0)J5*0^X{2{R%Yq$b38!4CJ*}lh zB>Fk7frmJtXM%a4TD}JpRw{M%Pcxx3&ed&BbJB;tLc>n7vwqh(5AR zFIYH4`MIurv(wVCmy}!9*^S$eOoO{x zlcATS6;;wJ5t}vvmk!B2F!i>QO?)57`_cYr8^WkVSo1B8sNEIqi`n#6vI<5u`d<6U zNFvbeYJUMVFJwVP^0ERSlc7{%5omVN*8;p)Wl4=u+xiM^G;d0?<(PHlRw5Z12ALkazysVyvc*bA>Io3B)9 zp9zgXl)*i5+7*wn4fqHCUwqBh;wRYdWGUbgToG{UY|Z53)4Jd^$JJyhrk-v1biS+w z{*ulMkgkZa*N~8x*;&v#pdWI+c+_CKs!kD0Uug-~2|(L8l;U11|9!V98KQk|We`ia z^!KOpZea4@@XalQMl;ivxxAUKT0ry<2~)|}#@uQUvk#_K0D zN4A{mMxi?j9vf*GqV~Iuu)G~@Kt~PTVj-}e)=`Dc@~7&?RdVkGdV_))r0lv92wzI8 zdiS!bl2SD4-9wLq{%E!?x8yHYVtuMLl;{@lu+UaT&^k*zWYt@eoe`U|E13M z_K#g(o8NLf+cc0m(%aab+AE42xeTi-wI4fJv28s+avm(U%WQ)uQl@tmul2ohnql8W zjjd3M@TVjzWlcARsr%tir(ihd!Zy(Fe(sBp78!0YG$bX_mAk;f={=1nIp6O~YTWqe zx%*}Fn=gKRx*mBt;h+1rH801WE40}57JpJW!`m-e!EyKhV)KcC=*C?tqi&s=N=0KG0wfvjqx~T+}I*+|`a5}MU*M`a+* z{n((081}%3oW;z=@aQzYu5NF*7yV@UztJehzcKN!%F z>qWmP9kiuUw>kjWCs z`iij{)sO5sx{#0f#-EVph|74!QF4FTDdKx6!fnb}=Rqdc?@q%`Luc^FcQ%N4Azz8S zs?v>ax_YtGPW`|h^(74USA_a{M8NSgr*-l^gOwHhwsL->D zPd`=GbLkK84-!Wf)hbi5d{HR}z37%<#ylB7P&N-O==VF%(r45T2?Jv3`_Z?B{7^&B z=_kRi7=*~n(bFc}bA*RpFR(=k{y|$kWLP4uO8ZzGeK!5^-BfMNbF9XGkRG$l4pbU7 zm)F>43crXOx>}21OFLFs;A?o_Kz1qzFL|vh#8DkX_T*FB;JEsn!GH2rz>FWdAy(K5 z;Qz9&Y;2mwgy3!kS?I}3Ibe>;>4Tqh&D#c-2$&8GZH>wc62(sZDve7S+)XcF5SjQv zKDrz2Ap$E6$*xNc(!goSF3Z%-1f6aa9&BNul|)Rj<>_Zel+Z(7+O>Z&-iXB1ZBT^P z<5fB?Q8`ku6bFf0EsRBnC$-DGh^_SuM^I&pf6LPP+|`!rJE{bRL5m{dHKK0H_NjW6 zncpqv54g)SGGh35)kgZiqGx|Vu4!dPM9Jl-FDqpE9i{Cbm+j@@Dj8QZ)wE8Cex_QCw8WCDxc@gLN|u zcj~DKB@VN_J)Txx^)sO8$eg0KsFNHCkUL$AHPOF&FE?PV+3oRcnJur`U><>H>UmDK z8lvKUu+x(h8;C2_(f(^rdIvOsq->qERawl8wdHsc>Ra*)N|`BzW3!52Ngzr^FuG3L z@2JwGo%I3ojZJ70)yVNAmM@`IGM_j3$Z=^{av#wIk7wJF{pyv7)}obZgq1%o1?W%a z(`xqnd|4gv-})mb4A7}0o|xydKzWq|2Q#LpZ-NooXtyL&p*6kLV@f)bR^P*8^C|Bo zt-~9qrDgBiBml3P4Vbh$SJ4Lg+YB@Iq60rz)Bo1OGBWI%2G2ySAP=IWhNBmC5J)xPz9gNUcA zEU2&P1xYsT?>ForcHBNkMI`^U`M}jjB@ zyq$8_)%u!IVf8pzJ<=^&tpaLls!YomS39bHb|~pOs&H+w zP%I4HcvNNCx=)+=3SDQ{5tzHY={jJ^9)qnKCZ|s3jtu6%%Zd0sx-y!+P@69w6*(r_ zt-g?5j@nG8|1xML1q5>)aNE!;yQV&i%S@St{NVpQS-xwU>OHHF$;RMicKTdL*AQDJ zuLwMU*ATxptf=5|O?Ns4^0w=k?8GgAn762S``P9g9gZmj?E3HQ?7nOXr)&Nm^~UUX zanRGV7$->{X6K9K>1(%FwwmW%xM*1&^>Vi%#HNnFK>%x~OwRvjKqCj49F`sWedI?~ z4++t^ZNBeQ@rn8|d~$y-F63aS2_+iK2-12hU5L(&X36N04BGTEU8bN3ewMC>ychi8 z$yzqsn>x5>88Y*wvBKT;XPO}NE*7eVPOf^t_Daeil7W2A4MUvfR+iH=e|KppO+zu> zBDY=|i?)=;cq4*>MD~w)rlt;h3Cmst>P)*(Pqr?>_g+2HD{hReym&2j;OTb6)LB4m zPhVTnuHWvg>ol-RLwLKsJ*cXj`a`xta7pLab)FgPie_e=m@fzzeHEdlq7J+unwXy9{ge3S@vSy@ozd74 zrRgP}hG3T9w+ZtW7}S(xv^rkjQ4y)-85-=sdo^-}YZ54y53LE$fL<<-{w)3`&JSRhklz$(!M8E!G6rgY+(nna7NqeAE$sPHpO zf@}^Lgtr9g{I9BxvsRQ&>#(YvHJf(;vW$|nH-mzX1fF!`dbl=@a-BUMAw*1LB}73A zA&&oX1j2S+q!z`Mr75Ab_Wy9zR|cuN6OU0u&+$swVlD1BZr)ilVdZaFcAIws<%yHr zcuz!2GDRKn^dPwGSk{Bo+?TU!Zbq!RIYv5SEoekrSN~TjCKXkjsM%xGh#W5<%Ct!| z1?ABOI?hq&?HtZc-7V#pv!yB!MkdAVB*R<#Beq=aM6sv$n*-4&BdVG3Cwr5acp8om zArfwA@CXz|z2bNXaXE@?yLESu-}oPeEoQL`Ynt^sQ8xA3hc-hs-Sa8HfAFexNdm3{ zKRF;nf&VjfCjLzLe;iMWO01Im`jw(`=NdNZtEgO+M-Yc32WBn!gIaBd`0#kC!GME4gI8mF7+cR_g(>snoZTmDC$U|d z2eHGyRWzx=gTbmVP%7J}Aptf6q@|}kT5^|apyolEnQ3xrF-6kGh(!cIU#CAAhjHF|4mX=XI~&I4 z=44VZ0s&!f;d{d)?yACugU%Jv9%i7Ic{dpRE#4GLEWqPA(yVHEKe6lAVU9H1-Yo=K zHQck+F>jlI(yU+ey|v$GuIPz|9|6#$@at^WMU?6`kIDGa{tp-cdMb;D&4ZWkdHc@gUGKiJ=Lw# z7sRhWJiALIo(Z2|oi3|#D`<++pT9H#&H)n&KCob+Iv$gLBs44^UTKVqir- zx57TxL=@-@j6J5_79h+vN~ErPLW%d~C8WNZ-EMBJyQ{VA8TrCU@q}gMjhF|ld~RUk z1Gh+WXX^&V3p}M%FIQh|lK8lGGZQvNr4?lD!taa~=V#BySU*%&k|KBnE@D7=ZY<>| zXtKT5&|lxC`rERSyVE(ZDAu3IHaq0>cX)nWcve|8$JFo=u3z2=>-eyT^5S{)!UfaQ z83I1KCyy`WNbij%`lt!-nmEbupX)ZA3-Fxp5TzbdLi&b1<=!>>2FI~c#2>%TaQ`?n zS~94m_rLq_&R0Ftx`qZf#Rq+{7*+L>ted=UQ!`RePvl-#bW)oXnUTn6QaXZal>3VL z&neal&vw#uv4*rH-c`rX=jU2S?Ko0cS#m`Lp|WQPmOFK*u0+`|)#9Sh%E?nwzpJ|@ zo0~(Od=5;QU|@Mtw)brL$d$|BQ=kGLkn~Qf{*GkT=DnNf&)-MqzkRDv-RFaLCpEF`G-sA;QBF!VDlAwGuYG* z-0Xt+m$E^PAd&7r)WG1OfUQ72|4K7ZQaaJprkA+(t*2FRECXqfvl)Jh9}=Xk33-;8 z{p$>?7M}7*d&e335Lsy~knV}+RYUMSueD8&`qX9scJ?^Gmaophzg%U3*3h&~g9`@?dNm_{J&jmw{DwVHQ%7kM8h z-%tRREd?usjmixNHRGxMoVUV#PqbnDoi$mraWr98bqWO;A0ywzzOox@-ZQJpRjg3d zv;VIt%wt??k|jD7si{{P+onFAe=cu2Njwl;V=&pcs;uCUw?^1xdaH^ zu+}Yh%ksWpiGHqr#N)ZI#;;;8l19zaQ4NLa$;!*X>_Iy2EG<$nA+3 z*C3JmtC$1B&u5p%=Kuhu*=x~~9ZN-r`@8?eAMaKiS8aNi+p<>cX@y3By z{U5SsCz7H$S~;)u0gxeTp5cXcL64#`6LSZCeK>WMukh4_OfHSxmiajp2RQ6JZEDvW7=gdR1^GjGU`QpGLEHlkViMg>C-8sp~Oc z?fFQ4gYL*>VkgV0lRIu#fAIZ5roBwt1nP^K3Kc>B<3KSgeP5N*?_Zz)oV~C6eA8-$ zM^}G<@;QQ2}Gr$7y@Dx7AgRqt`C`|U!4K03eR5x8b!I4nquD%5R0n{eIF z#`{kjIwS$9541=<3CKozF?O*%%AkUcH81F1#4o{c{N{SEc_RLk))DkoE1m8u^4!p{ zJWR>B5`gAR4S&kal}c@2!+pvst$&OsweWt!+6$h@ls~TgUbFPNWU;Hpp!Qg8`}b16 z6f4DclSV0APD|a)*uzQNHP*04=!39MO(?&63XjscNB??+ZC+O~LI-fPO*Z z`pWEz-}j3H#}yUtnbz1Y%SkQn1ZC}SQYBeQsP)DLr7VqRgXXs&-D5&;r($gSUtiXG zT8U#e@*n5gmHFh>{&-R^K%LCFtp9ydAZ1Ypq(?o4UWWU*DCQ+noE5xlKU9lx=ApMa znmPJ>m{0%K3I&ZbHVBZgy~iiIZC+@TAn!Tz^=x-DRy0i`K@HHSa|%tQo{l4o!9K}d zFOHnPlIDL+oeVQIqwBK@;J9=f8_(KO{l8M4W7cLyuM$Nn5g-oDYmG&i*Z{=@W6gP~ zJjfo3u^<=T6P$VB_zUHGy~c8J!BgPDqVMR9*TlHg!|eKI5G3sMo;7Z5tMwjZJZvZ2 z6=YnGtqp?FtO|w>jClB;M+*3SdI{!SlaJ$kwXnA=3s@}8O;a2Fz?pyE-ka=L?+iL^ zW(fI)?Kh*oKHaPwOnPXD$9}!usK`P$pm1m6L`RRuZf^A=KX&8r%sWM-W_a}EbJK!u zd*Nw4S40^30kNSE?+m-A8xdj)ly6L-y{Mi!D}7&~3K~|q`&j6+u?=5Qfxx@8AA~R@ z$jrQm`h0(kJ)PTc;1G#>U(&jMYx<*QMP%f+-Ggd$QR<+v&iGGQSY!P_?y|1>?4xmI zlM8FtgFhIv=X-YQ|I_cSd(VF0fxOVTFhqL0bb@?m=>Fnuq!B@C@5FAYb`dk%?e}zP zH*0KFIhNqwKJ+70*!v^nHPDqH6Ow*djb87n71D8SD!Z3{ck^%bD)Yfn`BP0E_(7Bq z3*;w{QzmJF4WaYo4h@!+Xj0cgW-;EKdASwLq{y@b>jQk0>Ec8~=!>ZeN3^ffJbl3T#mcNrr2T2Kz?LQ&Gixd{j7 zcGZ3F{_s{F;WOZPuSlGEhbL2SLvSvcbEQ&l1TN*YxH@gdbViz7!r_g~asCE^*J%}S z%@@pr88&4~{8q_il;NEi5%!$hS>wUp7c6jxG8VC}4`9|#P{)dyFPf+K*7U_k0}3r) z-!Iep^IG4C0}$8mwcQobo!eWJ0w3mT($(n~)l;d3_8H%;lJ$jo;5B}9zf3qTLMNYx z5ZBM*QP$Vy}D~#r=ya#Uomg9@DMD#qEins z?ZUUqo890|E6?JsjrLt7j(weutrOZMRO7SIQ_W9m)ot(dWo;kaF;d+psslLEdv(!$ z=0(k={L#z){!X@tnCT~@QJa1_SYV-{b$?}Z&+4zvDJHbuF&{5?tzZF`XtR1T^r&Hg zL5m!WH9c|!$T?rlCOYUVB85%UMHK(ae$kIW(w6@&dTSf=5A&a+Sm1I_o>IS*h*lvWyo;e z$ND(k_M0o|MPp{?I-8lk7jjRRXRGM2O1QWuWi&%whnqRM z%~&Qoru}WzR#lv<>v2vNEhB8rYy*As$lk*oj^wVK3wL(X2Nd8oUCMn4Nm4x8y|I{N zAE7Y)40@eg%(|7U?XGyLD#zlG_;SsheSy?|KzweELC57YQ-q!LBE{raOjby7B#u$c znZBB?Gc8AeA)rL#hXy*75#qIK>rLa8hQyivqomA1lP*;Ql!cP*2u}eK;5|irxNyXn zEO%F`;uHK!b5FShMmb*&$78nMm@8(*1sCaOYsLHgtR;Mq?_+<#)hXt9JrEKC-!=O< zU5?5H%*Z5+6|gp{7LF0@nL9D7_@hxoS8c0}$}KEg$syNMv)JVpk5uwgD8xEg{(j)P z3l!9;u3u#Q+%lP+QR#;#4nSo?&=EI1rh|eyAJ4$TMVfO_iR_b1(+ueZbaX}Zp>T~n z*agV^qh@h%_sO33ba=2$gz4~z!YE9o4rj86`gCI4@ExxjAV ze5hXc;pTav7?;KJP}kro+(${_*^5>%GQd#(TpKEr>TnUdQ&9f1(_ z4qkFTA-eM3~@&K&O+@>IT!L+@5}-;_{RAQrtlI2JW9K-iH5*8M!yKuS;ua?bR%9;y2aU ztzKkkk}A-M@DQAfIhI#e{VsR$b3XNRN4-8blJ98kUeNU2abAPHny%%F7by?WYCjLO zW2aPh7p;3_58?nJu;vJWi-y>P#13!R^@?rOnl4~fO6f7a{o)Vf**CH&!ZX`GaObe@ z7YR9M2wH^OYYRK1?<1Pr#LD~%OsgH-`8SF$OZ{*dNJ!B8#PJ&h8+F(FxzQmT6FKg^lj8_?x8>kyj2w>(O2aCSv1S0 zczkKJM{XVMyn)jy3LgB&@%7WFKaux6O(j{28?)!S9$9Da2Z>adEYlO`{yk%_It0c2uFz){Qa-DaR;Lpp zpYlD!Fya{1;FiM?XF&-}7OxJ`ZBl?A+J2q5Nd+CnN^XA371B>WV!8_YFf74z7Y|M~ zvLR<}*e8dRZ!uK%zJU3ilw)#KrQd~E+U4E0(lL?UG|CAB3bkr|RRGx57m;(?bj+h5 zoEZRbhWJd)p|}6V^mSfjq*PWIN70-9(O6PxgK2(*IQKOVgL^5}9Qf`ncqjwvL-M zDXr4|$Kgsm9JErxu5Xnmzmsbwa=43stt9q%SZXz^9vVlnk}* z+0S(^DI?%?IlA=b)qkaCr8zfdzalb}d}ro_wo8|cK+pBUIc!$zoLnJ}C_%F9G$9rT z-BJj332XEas`|%juYC9}e^%m2DrLuVBMb2}X5&nM!2Glw_A`#?T&}cslWn*I<4l3vTCVOYy^>C=uPabwp~E#f6xz5l$zOp2SEpO6rxJql%C{xx8BLOVcX#5V zqk5xkXhCQ%i&43+iO*A1(p!pt)N%K$wyhDim^uH_)bmXn$B4=-_hol`mT#Z!k=^4BYROf4^8?#IuVL$@;=1 zjk>J(fXW&`+&DULJ+0wdy|7{cR~>Q!x$i(c4~6qP#F>gT6GOEH#YoeiO--hoHBx+a>uY_~B1;Y( zxZ$f4U^fbDj{wb+l{VZnl>eH?PdyjRp(?-F2-u(%<3s+E4V(>Elz_<54y4g7!XhFv zFoFj@B}f|$&?%kn^nqK4B|9g_UR!XfkLQnP%8=Vz6t={W^S}445w8)6i=C~zRHZEh zF?{!v_mlcW(Cyfz7=_V-tppF*e+Aicz~bs-sJ!~m=odbW_e(!|RSSoEp}LHc2o(ee zej}uoHb?j)3J}CWNe`r&JEblcer;9I?a1t&Ths4}is4ox$3o3P z^t1F9&!zkqH+{*yb^mJHpSD$bV|q;RBDNpXgKp9!ngEav*EUGC7rmkSjBl8C5j`ED z!;%5JpnESn+wpJh`XG-ZahQ{eBABD5?~v_fUK(?2A!mM}FaijX@juD8QjrtIm=Kg$ z;yG1P4$+!$0xPn43JIr0hlOcrPGk)}V!jStwv4qmuu(7S){s)a^}9XYSm}7}sRSY@ zPg`1u-4wGzwr7_6IwYsAtSW)duSul#8NQq+`+O6mUcEf;jATKzl|_9i9iKf`WSr9O z1B#SDu8O+Vg4>4u+LY_9ey?)9SBR>dppmzm9*xHDk1}^3r@Zt)!cM2d?Lxlt4br#Tkp0J7 zzf-4X>mh`@$gtUX%IoGMWKz;TMGWfmxme9T(Iq2Vu+AS$oMb$Ohr?l@Fb*Q;*gC}R zlX<5Dd}FsqWAjPX%0#OxuI9_&Z)9~^Na4lf%9^l}6doLZ&bs1Y_bg@F#tMklj#vbi%_|N^f0OlUANG)oG2e@5S9K;AU zzH>UHM%vs=nt*7d8#~nr`JINrTkJ~>>EwGT4T5k^)6P@n_y&``fWnw-^;Q*6DlaH~ zQ53T((dxSeKCWf4 z5$mM3HychO74($$v)0|Fw6t`!%BBCYK8dbOi^K}dT+bJpPDT&rA1rekCqHQU$}vW4 z^R4Bd?La4%PS)R3bcScTq>N|c^P&n2qSjTl(lYCKP*qjha5+b1RPbSg%%6yJ?AB>< zZj$0@(23n-wx!rW!uPGk(cA5eJ-;`r``&)=u;(Muo46AX{BRhnA*F$cA!a{jpX znUqEUvpxzH!SAL$;7Qz7W7-!RLB;xWLoCM7Q!qA6!e>)y<78V6jyMy0wV&`!t@T!Y z%q{}=Ypjlpkq3&ab}0$;F3agCrwTVDOQh-7+1mZ^c%%Cs7PGE-L&Fza`mwv@`oejm ze2BIBP7K{tOBOxg=`6D8*Z3;a9tbt=%39m+0|+%I|5$PTZOl%h^sC=MIQ%|jn3))7 zFA>hs?^BD@FW1?l&Lk`n-+vD?gQocsKy{#r75i92yXOsqdWIBaWELYLGzcEf8L;zC z#j_jH`S9bYjhunHPWhTI9;Wq6YR=7J-*zAEJ!|p?O&dNHp4OU7*;O8!bM7nssKwcu zR+fIA=wL_eDp;u|O+5pThH(;YX>wyZec>-6^G9NVyqT$3&O%`z&E|BF>t#HaDwI(A8{r7N$q!*yPwI0gyDN@cvwi)c;9v8@tm>=wH069Ymc+w3h%HC8FtMB z6{HNS-sxLWC~H+vcQQxxiN@gFT?N8$Q*>0^zTN$+-IN(8*f`!pTVG8>Sa^MB_+d=p zQdY9}4B?Z@VH{ECdkJZj^^!`WPw&a+Of&AJ)#P);iOJ`yQ~P*CX9Hb9TsUnxhqnND z&VP2MFJ;jF@f%WCr-A%8HYzymUB(s4xB0&^dJ@u>fCE}Dc7OW8a%a_SS`{xt;)+Ii zci4nxo&03WEAr9J(493zOuuQ{$zfdoHEm%5JQDFk(p|vP%5`yykxM+gC*SZl2Z%5W z`{=AVRt}8xY4+EzKFKMWv5#zUKDl)YhkLC)UFjh%pN4qW9QEl)@L_;9A<1^hgHfOD z6`(0cJ8PE~dvI$=7grVlp|+3Kb+<2-A7RUpH+eDaa#d{B);ne!NPPU|Z^oYgz;*8a zn_TT51)XEWJLVe#*f{hbe9FA;@Aq2QRtI2DBxn8FSEkybc~c%{Z+xQiLuabrytmvh z*wIzRxfBRzReKXmDqyJ#{XPp5K<09>?~h8?^?S2}pF_ICxFCG8La-7}6WL3lspJFpG1g zpp9yHx9v@?{!+BRHN|bYN5Z6BO)(t%$a{hG zHD>=xxf$hFo_R6^NiokW1zD>t2DfFFiMu5tEvjR-Gy8_;3kq6|VaHPYvpr2`c*j$f zgvwrC#OaK8EAK7A64;@*u@kw(@E*IZsvJ?XohJYL%+a++lrQbCgjIrjbk;K`kMoz^ zRG{c=mYKWLaMn)?Q;@rU9QY=FPLSo+uh!a}U13!gu5{n3Qo^ozXpH`7er0|Ey=c|> zQ9%+pvYW_21phmkvK`_ol2{WN=G#lbJKwH$%I*0Qd{nsRZ?U(AJg_v&9HG*MHgkZz z4DvJ^dLFVFySEIc1I5ImCXJmua+3f*X-l@7w|Dut_oSOZ&1S9i`Pmv+tZr@{ED9r`*JL z31gL})A^6J;D%Lql*G-{Q3u{gf06{uP>@?fGgr{(-z4SnvmZEZ6ZY;-p@HQ-uOFqQ z`*wj6d1}!MS&l2?Paf4fnsDD-)u8$l{w)r@_q}!QHbL82@%{C$ zUfFVtFAMgeiHW)BF{5ZL#qs0!Y8nVU35vgDR>S+)uM6e6;`j&p(*peI$daQSi13gZ zM<;Sdd5;1y&(qUCR8DizJ+TLFR+GYYcvC925E`=eb0@Vs9N>ouk;g(bD!Wha{TiQ1 z`*_z!{*%k~nX)azcJH(YSB>>6UlN8{K-_7_5l8UK>U7dZ$bby(Z&rKS?;=p6e_QWU z2hXDzO+|*${19>JM6=B3@e9=dG!fhP-JlI{z-7F$&w3EGXrnR< zVA1=O8dC2MjAbMLQvlSD{aUHdyZAWtcC5BFeX)rWRYyXrt~eb z0;6K7wF=RV-4WPWN;epqcq^=&Hj$I`?`rkl!r#xE{Y zqUZX0X0^RzAfBB)pB3I!P~|$8uIR<90Ku;1rNga7igfnAI_~Ztfmf5LNBi|(L_`T+;F}S)g7s#trapm!$5u+gp?pU}{vEGUhdleB=~$CB4NLFgNi-Giq#J4_+6-l$0Gw{Hzvz0y{7v_4dGFqC~(*Yy2 zjU~o*n-}OqJ<2C$pq_37(s-z;v01pOrJj!}+uKwKIri&6Q;XQN%op$`kqtN2$ncF( zwXG84MB%ptRn?6nRiY>qVZ5slTSC2Mb;@OR- z1KoGcKqWxkY5@HhSwhRC7+fKh3Ayq5`^n+J&9&mPWto-4amse~@5}LK0aRZv%2Mrk zZ_tL)D@14>I@vU8Btt?fJuGOT5KL<(5N=W&NUx{C} zZvyB%xEj)cAi69?N0{dwNBSBK?tmxN6uPHRZD-Fy2RW4dT=@d@Rcxo=cl1znforBx zpjdHuLVr%&V2437#&Tcgy86H7CnzPqr(knlE-V=F>yks zt~Hqi=%hR@S*$y}i`EKT=5`3=R1u`7PeCMSFL>OANQ#cbGDdAEqdR4VZv{J1Ss5-8 zTa#Y*kk+uaRghu{l;Ad#EbOipSqpp$X*gE{NL6qqG{D+&naBHe41?289#+F-o-7D2=Vv5s!SOkEjmpFAu0#BVnY(#bm{CGNVBU zBhQU)&fG2aeyY!A85tyt2lwD?%U6o%ETmg0I=6U zCxMz=(&RogLh?l}ZwEOW|1a9~M_8ad#u6q-Y$lb$6U7l5%8hxbERtS1nYM zYdwQTovU1dfPO)8&Zc-#K~lOQIUirP4+tk0kxnLv2lY>Or?#|muIcNcsE*!NiEW-3 z|3YMCo^sA_0I&FoI$F;8@w-}!A0y;sgx zqwxCARw^sd;na08a~eU4(2oD^gNir z2X?HY@VO;x5z#U{*`512$9ZULSau&mR3;hY@Z*2eZvwtb87ZgMy|WF9I%Infu}Lkr zXS^u7i_|l-#nfvV-8>#qJA5w!#!jPL!G8x8=jQ=VY7ui1l{Q4SZZS8VwL4@>z(Hb; z?WilsUCNoB@!~aN9K>kDrWvxlGTOhCY`<*Madf#Xqyod!2JXsQmaD`MGWyA{p`Wy| zjqZ8w;GJCB8~n5A!G>3u8+j~PxWYz~w5Q~5^LrFl6>@}d0~xMjv_J1SM|dqaS!uTX zD8lo{|JG6|`I3hoEh}Z4Nkt?+&@leQ?Vt>0_oq)QHv!}gHF-U&*AWJG0sQ902=8s` zJNa>W!+*D4|59B#N?;yNQr3RYN$n*kGs8iW6_D3m1u=J>CxO@g~8 z*FRGys~@UN`=OjE7`xsgg1-GB;c3qgnHxu6na^a&e|YhCKEC}+XDrfR3qOLG2O~rM zRcDjCKcytH3s24+9^DXW%YStk4%xi8?PwZ)zmVfQ#?is9Q0aXYMr<2=Iwk<@q^iBc zu2xy@i;zXkV^m{)&QFH#(u&6H|vHtX1Q4%({ACIoKXw4#ex|1jE;$P^iuk`bxNli>5T6KkXfwr<|-=uCug+x zs~QQ*0ur^i59fW1{3~K5^83P$^!<7K!0%|6xz`Os5nwDs`z^sJJex3xrnTp9H1rIK z=c?J|lg2~t56zSGnoY|m4tl4(%#O8OZg#huiRcX4zK8Iu1n`QGMc*N(c?mo7HxoLc z(rd1i!6ARtcoRP6wwr_kiPNFXUK)FlYafQ*_6+KsoV(tI=#A%in(T ztmKdEm{%~0=nFIlxS7omDLF}0a#F0r)7G(^FVG{3xAtA`MEAM;r_cGaZoO)>)ozIw zqrcyz4-eB29oJ!>##$0IQi_!~i|WT5y-{tjl~YxgPuedwpToPDwkR-vx9QJ)mpz(q zr}}x=M8q2VzoIPY6+>2&+~Kl$!w?xv%cedfMbUffA1^a(3V)w}(F`5=IHkom8$EVAxM+qo!eO(;?>| z;1i}$v*61g5r1WUT}U#`s#?$RPh%mw5!uwF`V-Y*HHnt>7115Ed~UROwJHu^TQNT^ zms7$Omnu|hfqnuW#9(Oc$^ZRc;ku}bl=X)rw$v2G>|VJpbVf$8!jhb09T#no>be`g zbRXn=DgcEp!M>M&te{ZN+TQ3m;sx>o}ym8_(s^fkyjPa3^tMyYSh`e z2KEuk-d^Xp8f$x4=XC1Nzg&7UmI{B}9aXEMNlKbVFNUL_r$!$01b`AXYPqbgsQg)j zN|ytYVe942Ze;EJ9Qgn4FNbS8j+Z|QKejxh-O)CY0F0`Z3f+dEr^JKRfOl?gw;5bf{iouk^VfzFpg%DYw(TT&*LPYHChw+k`@p* zY5H|`u6I+aOovnO;2!AY`X}Ke3lZ_yC|tXa?jclxC5iX|G@TB;h70a|LrlisFzrCi zeAxY_8q+PQ);vnz3*8-}l!F`oP9%ktK>O;I@{W1jXGT|yR|_vvKCnk?XiB3K|2IRM&pu`A6K7?NVcB{Fsz(ZDpCr5Gglj~WD0833| zX?j0chaYEArZwN>nVU$IF9S~*BUo;^mYX}CEbk3whK;|0C>Bt6c72I*S?Xq>D)MDf zz38t0zE%2)xTEfd>#B66FzqTn?xfaVX0>VPFK?q}?|VBIYx4+(4(N!KirL0lQtqbH z{K0-mL4yh48DA0dD0oP*@2F$?lYH1$#{*;IKIXb#C)Nfk*%_hz=UaXwi~?j6->6QM zV!Oq$S@?^pS=WmyNjD|zb9P>ee4!9qLY(yUjE-vI(>s(mE0L@eV#w(9Z1zQuoXW30 zANdaGqcpuH`Du7g{L1vn!lEfX*^Nk(4KAM#u-RSM*BG8YJ zr;<0jzc~LPZ3gQ;{avqbUv0lCidBC2E$eZ%XKpnI4vV~(*UMyLmT!|oUXJtPV=q#+ z0U6eTIGUYOw^cUwN@Dj+rf|?cYVSI&pmQL8GhCPc@uV@wmPn8rc2}hU9|+8dDEv)S^q%lh5tKf z*YxKzh!S&!`%M4u)avw)^IgyF`lzFZ$=#>%e$w6o9+<9U6!JlH z0eT=7b{W`1anH-Juxv~Fn?^r{JVH^!mwEOd3peAOn&~wZ4xr)-+nY+jms280Ou|h48yj9A|{{pItvwmtv_nsvI1+adD>-$GeBl zlIaoIL2uF6vZL_xgu_h188v7ZpNY?uNn&3vIBeNdAk>~T2)f~_?)&d2b}L|ZZ82fU zGgs~Fc%(6R6zhxzkg@&vNTFQgjJ-e6A*>$}1}?c7Bz4Q!v__V>vzeZ2hP@(DBUJLc zk?`haj##(XeL{baD)30m2eScgt66ckrzNJs_+aYM*%mP-mKEF|?V-H87k$W*V5a`$ z;tPf?{nASTe+S;-*%P!CrKuXT0kt(zz@KVMyTXq~=0bJ&@I!S27@~c^UzdTRHJQw4 zwdOW^E-d6A=HjMpL;tFlPZ!Y#x`Gg<_Hqk8^3O_lmaj$LO~`8hWtEq}U7u-v0}6cj zZl|KoU4D3HrLUdYz3A6A+P)ZjDOV(wKbCAb`f#_48>gZM7!C>r`Agwt5)rNsI|X~p z>W!z*nZ6f>{ibLB3g({Hj8hs`zrzzmYqJ~aX~BL0m}vhnBi^H)XrO+z>FitS6y`{;Fknb1rZ`6N!FBzgKK{AH$MpaF zHFxqH-;OckS1mE?7a~Ekk^ouSXH1fPYx2Ok`*KoBZ187&cd$2@KsRSydl1+4Xqg1qLA<=xh(`yW)Ix!BIuU2N))LyTV2SyMCWRC!g; z*6ZM`3#czZzuk${h~w2Xh)MbM4U=e8%%wV9)_dVj7#tJZW&A$1JlO4|#&VNyUo&2J z|1uz2<#4Q&Lt6Zgc`^t6P039`z-%CkvqZNd50r=p;R&kD?$%tt?XTP#8Th2M)@DjI_LxEsOJg;SJ{0-j6Rqe}Ec`n*rh z@7FGnS~ty#=Y82Ls!eAJkL3kvhg0KXhssmdc}XQ%y=T%vc}}I3W9gR+g2B#iClvG2 zEj3z#8TZx`bsa$B@^!i*eOk=&eyK=uoN3T5Ekrqg-ExZ7|7InNVTUUmG;g;9Vv!4aUSo`eqHTnEqOn({Yd-dIBY!*5$k0aq%6={(%X8x)0-{x7 zAIOg7Yd%9%hY^j$j-_U{OIibiILww?1CHpRWaLh(0yS&=6Zi;Gq)-P z{_6otWV*=bnj-XOQ-V)h{yBq{WRm3%!*ThsK81X{vO804{~{g)+zUQ$YtdXtc&5wk zWMqX~n5<#o)r+h#kz2jrTr+#-R(103)>Ju5=M@>R`8m4+1sNUXXYhX;i8`H&OG<_M zKxRurXqXyq*f?=1F78FKG$`K8)-!bt^D6q3_$8>pxF$W0URhBgMb!ofer0m?FOKS<{S*{7U1FQSsnmZDSd%qrB47j1NsOV}~@3nng^SS-VCvpc=^T$$e z!qL8%4~Zi`Ba#y>7sYp?LImEp2ja~Hgo{bbh5q~FrL8CIW_?t194^e||L_huj~i3J z;321Lp>zXGE%$P|t$5FF=s7)>jGhB+rVhx!0oYAYtCH2;V0(n9SfQh$?%uc2wET*T ztbpj+wtJyRFb=@OdC?w+rH=+V1iuuB34y-{wVBt1SN5wbbK{(|fo}w#im+A~GZ_k| z(&@oBl+G#SM-M&;-sh>Ei#DSvz7!zz4G9F-u;I^p>8X; zxxh6ZAZd3`3DPBgz?Fn#2(qtPIgFPsR^I9}0%o+7gQ`C-+x|L(kdgwFDcR!{f?ip^ z2%0PRbUC$W)tokK1sMK}d zWFxC8Y68ix(mQ*A_`jJSykmx+a^7{^X{^_M<7bqr5(Lh25fE;5j86~IoO2#@fn*s= z3%7NbvBw)Opn}mguthVBS@R>6gE`@=)@#i*K77L>=vs%x?g!kHkzg-{4OzM=9nY+y z*DiZGOg;IK6~DeTef{4}-k03@uO=1XuuCK$+DhTEXuI_oxM}Zj!d&Qbc7!HZ zY1$T5C=-~8QARP_fdLMwx-%Abmyj+gU8osJ(5-Y2K7SZ7Vw`@sZcZsz>IvZQZemg4 zHzT-)lk@Asy7reG0PhWV4cw!}gy?>o>Dy0gAQ&-7&7|9e&LFsdY-D9d|Fcwqd^_=Sq+Y;OVC zBO5}@k;_>B^neQy_HhQx^}Q*W!>oq8Nox+M7pQ)nC^K0C09a5xsZY9X8(h zmd}_gT9jE%7Uzfhz}L23$&hvqiyTi7?i6cyviRU?fWulqidJq`)A9Tz$IHoctmWQ; zg8xLwJ2vO+0t#GLwE>6mAOs4Ed6I&AD2HopJXY84<%!6 z`um0Mz3W-2Td2|Ie@smR^f+tGB}^+5=s!1#W)=JY@GeXO?Ic8W9U${Uo#)KrIx zW~HtB?1+j)kL7R?)!-qc82ROHe=y||-GQFs~l(J5c0n7EQPhV-W4 z^s)RwC9eKde9;w1kuG&p7{A);Ijz=$z5h5`e5k&l;-MZ2$J#g8{X1H@okd9Pd{VJwG=2)RHr4On^Z{Pl`~q@ihMhm+;jL1l90K;n z5w$}aQ}LgWsJnDg4>?UU#8;4&c8-h)r#YX3VD&Ns|IDu(!)F*=(=r?m9R?|lTbS#L z{LSp+lImnew~x+!k9?Co9G-0WbY|MsNWkZY2xGT1tbVJ$!!b+zO^;Dej3OQvyD%}M zp8+6`j2}pwkKz1`k1!$LXH@yV%!V>|VV~bPZe}PwbaBHk2kACsi?~}dt z=6TxT`F-aQUSa8+0@RJ^S_{T4xEZ{BoodEiY@I(pV5hZJ((hJnnggk$g{~LR$?nD% zY6b(_scM;N&*r0qv@yg!2)N1HhhZ?_&8jPYhr3DWaAZd1eF9$4n)mX1PEnOAEyDKQ z9{6n`W&8_Eqgt?LMlvw}^H<4HGV4Ctqnfzb)Go5}*DEm+S)29FvNLZO8{ID27nRR!=`! zS0tsx1my6ez5FF~7e}ptvC_IuwvH$Rr`N!WtNj+KD zeS>mp1YjFkEjLxY`O8LM3zpM%}aot zQGSq}Yk~I^vlM$lc1tEz3l+s_ z!=9YRw}4Apm(Rz%P_BN_p+Hcq0jSdOp>No=o7kJHXa1j}b8%<#|NnSLDyK@4LsN-;N{r@grc$Y# zD&=hGU^$r<_P|zoRVqa}nV&yaZfc}ac;f8b;TBv| z!qf%Rj#_GhQ%OpinaI+I%b}TJk&HyzEye@`=r)(MK>bmTULvJl!%u8) z*C#;~+b1g6x6|*JxWKwiVtlCvo-kPSy6|&oYp8X+cXDah_RP1|wW(BCPbp=}6k^J_T^9^Gmu&Ecc2DHR zCYv=?LQ8y%C*B3nugnq8;T{pcBuuj1>ECr}WjKskq--dQ77g!cYU_>obT{*+IBN^P^$ z4L2yNh1(>(+2$Rc*e@nJXi3@TosWmw=)ZOYaV*Ea&qWWLA8&UM-RfUu5Q!RgEx{J? zWBN9=@0Tiw8|~)@3t0i(GOzPC^wt*FOVZuniF2PY6Kx`@iOKP9XWJ520^5HeSLV~I zopv4x{}gqFRNI9PVw)nG7MKgqx#TgO4`7YtmZGE5<@J|#?vE8>s?K)j{x5=il=NZ} z)ST0Zs}{#!-;a3=HQY>oYShTBJ|3uR*7M;xD{q5mXW{ZZRjQX-jz?lOFBLzB;N${<8v)BW8BqTs`dd8HRqeE@4nRf{~y< ztx5^qxXr$`cJNvneWBa8+R(JK{ClM@A;1~}Qn{H)ubmv&fh&~;6Alv6#N9=!q;$2- zbx7RfJAWA~?0>%8N9_KTgj>(S^u;&KX_vG6O?KBa_d#Uh8{koj7gnLW9hVKfPb)ol z$Ug_n@C^WgB6iMYKM_`1@9Ya4q)ht25d3=q(e zh-(M57Eis+kmu786|M$QN%Jh;H1(0tQo^@=W#d$PQmm+~Bp~Xh&xwGk?9Z|LWk(<0 zho16Z0Lw`a79k-i+cR}5T>U{<{Jh?S)n&4v^cQ{%ZRJnvBb_(IxZKjs<`5>PCvM{~ zO#*tXk6ad%KKf56 z`p?bn$CCksBIX5C+2n67kNuatKMC?q<4fQUVR0Jo{Hsf>FoLWkr?Y5N?&q7R_|U|&x5|O#w8u5^^|cgzWRuKyS9c*o&{!HS58YhzO=|rl$^ak z4uJ}&og*F+v(6jbrUTuv;rcg$|Lf=cH)&E|Y7s6tA)<2<^h|WBfwi?G_`KOuaX7vP8Xq%v5o!yAGIaGH4AqGUg`YL=rd+sr%5=LZZlywpf`Au5FMSyk2Grm z?RENaOQzpX9N|1Pv4nS)v4f^fpt-Iyz?Naa>y-vy^W>8D(N`*>~dTnd;XHo zC+_%|$HZ{jqszF-J(5F(qLUi*fOfyV0KSNWU;iKhy|vx(cDR z@RbRsMN6CPwxLrU-VB{FMl`yfC8rGAqT~is&-^}KV}eVE>QZimL19KE|D(wnLnWWL zURrCvb^%af1$5~VW?H++0nT6@%UzcZq#++$q#p_WAW?yCFswGTDSx0FmAk0qFZZf- zbD7X|5vl0ovvC75>psM*ldpB#raVW^zWPIn=T$<-_p;R2whib7Z zmyvb1aaylD-V$D)2?z;IgiVYuFq)qRqF!!>2S#{bmyf0O4U>)8?(K7`)rZD^-CYY_ z)PV_UY}wfYYJ=?A(zs8xO*PLs&Txwfg-mds=44^TV4DhF$vncwm8fYFG!))^E8wCu zt9hk?-YvXLtvO!}@uyB+sF0xPd!e^lb!uW1-OhU??JWCmu&yPs3-3nvI$8Wo3l<38 zcr`c+tpQda)Uop{Qal|?`dk*jky!(Ryq~+=iJN1-8*VU0W%Z^Aa=Vw&$e2_ekQgs= zY*un;gk+prtc~iVuqYz_P~1rOb{~3W<-&jSDqis4S#) zSSxTl(4{YLhnoCaP6EtS8T-(FlVtJ6&h;HoA&Fb>^Csmdy6gwwHGlnSTtU*rPVOmI z>5r~geaI8eU^t1T((Bx&3q8n|8vo83r<`$Q8Ev=1cXw-+Mqwv*@6qr7NSHLM?qsx_-4NAKgqnT$Vz@Aa2;>S9 zSM2`|Cv}ykD#^Blz1cyVt$zof?iNtxM<$hBpd1{Ztr`F+n)P?Nn*H{*&%x)AXJwj% z8gUKx#{T*uEGmKrG~70 z@eGt;y#O=}dZ_^@w@y2sscZGIj!zSZ9Pe8d2k`}ZQfA3`#3^0kql6K-;GDbL3(#38+W3Y9Jc zIxMs`{VzHrLsu*iW4>JW&^|U>3X&CV>R+QY|6(42j@A-t_f~&p|B)eI3aIQV+3N$5 z^y~?a0N2_t{$@P2B1pw6pAWq8s){gw+HI0-TcX)ptAMf6d)+=H)USOhg<*pL|GGgW zD>ze3rE-0Dp5@yxX%INBxw03Z`Xkka-??=PJOS0Xf|bT?5C<&X)Cp9G6H=9mMJ4Xe z&snS&7U*#bW@T{jFukgez<>6yr<=<=QmdVYN=4gx^G(}iYPH2gA+z=-^y*c$AF0Aq z$~6CA7Son&fl${JJLZfdk-!^%#w2ZN1w~Z{6xrvwwJ3hY(=foCv$w?BcGB; zyZ5)-Id3wK=h8ZCE0Q)YEh_g%yJ7|7g+9)sV?->Prnf;0adWeXyZFpqWsXSNghqMd zQmdCngYE11x5PtR(WL=^@ywO+vC+bEFY4djWQ-$dc&)r*3-OMPBK*f);Z6p(!tm8# z4L-H7{PKqIk8(C|6&u<`^w2!gAPq>U^3U;QUz)!^7F2*}jr}Y*>j?{`PxXdP0?K7t zub@Az*8S}Q0U5d!qD?e25qp2_K8YBMx$~^o!zVv&->_{US-Sioq+$Vw)abfZl8b() z6i{9lI!jlpiw7`J`s`1;hvC!yq<|f5kjGr}QXsWT0myn$*uXYOg^!X_(yr=@2I1AJ zo9&gx`#W3DrVIwRyzI+&y2z6$*T&=E9#ILY`ff)sH+&;;cMaTvEjLX@pt;Ky8~-N0<-i-Mhh!o5H9H(HY$+(0M@>Mep=jz zW!zHUT9w%o2hB+Jb|L;`)SPH}r@Tpy$(LBYhdN2qmy@o-W{Pmq`s}jf_cAc-ukUqs z-=a!dW)v%m#^nLxEIsBy?NdvScN>eDUs+N4k+r)TPZ5WBK8htfrv0t4UH!;=vwG+3 zPH3v4e4S4^Bibt;m`^aDkyQYR!jG~{Q%M3eQUf-qB zy-=$Cn$fl(lOcG7xc+-Rr@x+>{`-1;ZhS89=itUTE9XaS>t&9~NABEan)Dg|Eg)TM z<620jkJD5p_`!w=GiVuW-6vK;-49}uVE>b(LUt8VZef46XKZY*p&~W%4Ymevl1y7) z&I|cMh2vVTWzDXKJUdd-Y7@l~Mf>cY@sTS1JX~6RK=upoK6uJ!uY~3isCLj&+>WF& z5W)HMD1^9h`L{DAib1)i2N6>d9-NTyA&f~a#f)z7&0l)!0bL?*Qs1FsH%{y4XkWH& zha5wH9NZdTVU)JGZpPBGMwxZ}IL`gdQ>w|@=B(3nXaceY^SFiiwa1-(TQ2?F=H|a( z`?PZk4A$kfjy)x|90*_{U$UI~Pc(hFVH>#rkU;t&*2sMHAS<6IE?4ZVQGnpQpRj~z zWn44s3U&FremOsqtLgI*Vd@(db`KkFns;;}=%i^IC8Fj&lwp!o?yRgn;2d9~v8lzm(A|^Q*m0o#(Z*Ae5aJTcily zN^e&X=+Pi$jb8d|Y0~R{Wp(X#T6{P$nNFI+T-fCv+W2<}-30rG@c!9svCU%))kD~Xn%3V(eZ{n9gK3{} zg~wMkG7wtXs9%0eLVBfk+5N&oY2FUw>!K?}nIurT%61=2#+GY*W^I~6f(#G|L5o9N zvFy#-1_C8WJkobQaGT*9TK#R>&tR5iBryBjA{yDwRKmRl80eQFZv4HUNug1+Zum=t zwo2`FES>{LvHwd8>(BhD>ripBII{GH=$J-^lBsC)ujfqBxYuV7rdx+wj>S=As zT@JgOzrB|D?HJepRUgL+{j_Gt$3x7?j_tEC_y&SmY9XX(t5s@x&N)bb$s#ADv9{Wa zb86ELlhkuyYi&slL9lvX8>LHf;`<&)@49E;U8Lwy+$F)!lQB?c^M zI=St{IqBqI(}#SrKhyWA+c-gc3gT^d>TgS}sIgU5Zg|4=Q_8tbGl5VufWv-+vISns z`;=TnO4Rd5rSBb)3QR{N-QbJ9dDm=6pP&o2#b&zi`O0jMPz7EZjOx>HsOWO;n z9EE<8oRz8(q!pGfOu=SzaEb!cMFS5I4+u7HSD~jv9vZY>Y&wD`pe$T|>268W?i1TA zuo)G3MwT96C0WJ?$HAevp_8Q$e@3?DlZ1uyvq!VE3V{>a?zRLJ`q^*Hoq88-d+3+) zfvi%p^iKfyTld&Q;8Y>LH0>!RT30W|hccy!a=?f@eaTD!AZ=#1bXg!V$A;8V$|L#=jy0raTC zS%3RH$Df!O3>U>6VxK~o@smU8y8_^tAW9&r&`SID=F*3Q+T3jJDmldQzrPM-OYt7T zc?Z1WoEQHJ$J~^fDR|uh`;@m}oFL=!r4%WUsDa&*4==NGZ>R#o^9jYJZqi)|i$gWO54jJOYwVasDRZ^+3e4$! z3oNB2__xz;f(D~oL|S;c)#3*hZB(ibmW@64gSa^8>>IOTv3nk*Lem=G(^{bqRkA~; zen76FaGLeMaVRHF{5>Fftjb9&&K-318QMDtwUsFi4*Qo^@{zRe7~9%OZ`8 zV+$F#N4d`GEn2xzS)m0XYo5C-?|m$}vuyj!gfr9vdLJOB@wuYQG0$i$_0tp>+K8Ht z%zH4+hE8pjMm+L)0sB2xm@w`Apy(u@x>c5gb%S2fmG{UUY!+`a-#iNI)>&DUKvf|D zVJ>^UzeBW3Os>6N+7Khi4w?g0`S0O(#I{N0RCyoI%@5Ki_~GRVN*m;<*^P*NtpTC3 zrTX5-h{Q^B^o0h-_$n)Eh0WTeSy2YreMpd*N8sIf`*2X3jI|ZYA;1b-BvJ0oU36VT zoE$%vVv6<>II&xGpX16qh*5+;{Q=B7P2)x-8S|y;ojO}pcO+;X@?CYS|495U7{he1 z*5HaS8BP4jvYdBl4(3-7%;cy#TMe>L<*t{!F*?GyP@n3WRar?V%{F?+#2Ou;H~be8 zqa}9smlnRN{sMO=v}t(z)WGS`Tuc^wC+;^Cn<+=3B`l0sxQRhdqnh9@=O;{@R54kr zAEt+ON0X9%Y;KPKhX4HIarx(KQBN<)cp9oSUN?qkM0_G>Qh~0tsK&tU3+jrey(@Rt zc7nW~2##n|O!;s61Aor&#t%uVaaxPSb}Yjll2h(i{94W ziaLk9zr(0H{CQa#xaZ6mPp zN$#V2oC{II?CD4MTpiK#xF{nv@JTr@zJ2CW1hL2y3K|#YL~7kC9&qKa=tpO#wT0PK zU$alpZDOp^cE7eU+-+qY3Hvz;ogZZUllT-Zy3Mq~tKHEm8aJfWFDZi=h1z`6nYt0= z{@LKr>QG^w;D^Cd{Dt=P^xWVZW9C(wT^-jTx~f>82nls zBX#|dZt@KgXLQO!#AsA8sfXVG(Bg;jGMabBmcW%zh3F4tXe^n1kWA)?`KYRYgY5)6dQ!ZeW#J3eFRsaL-5L$hq`(rWa@QKd%FvX(X+mp4 z4~T1bx2ZNgQV?7fwfOF6+gTM-IwjkgA=gHOz()aUf|IBYKLdFpneZ*?#YDs zrYDX4Hl{$$3_u;ey*&ffD=MF7D!D|hJ)RaL&3*M;c!UqIt~kMv=TS03wl{L~V=@Yl zY)xly&A8u4tm`;4k=Cl0*g}9~`AFNNa>s!ha(}2%ms%`I0{VJu=7p~VnL6F>-eG*B zP|eYX{0l_7NX<5j(TssBRnC=T)yR~%jn^fb+ z@mM~;t}_tz#wB>6CMRSa-N~-z5XFPJc5Kk({@Ot0$qwr<^TCRK!MHO+X|=bUir6i5 zx%R`El;WrOudCZkHWBa*7A=8RjBChC2>R%HUeHJGim+lex&gK6Fje`Fm+ z&|}=~L(QKntHi!0lFtReA?(Q=9<>xILqC*0)DhY$a~S-mp;~x*4E}i3;fsbTDDP(D zwbe*;5%9>MmVYy^-9NR#X|8bZ6+bmqP^NJ|%`|iwnkwbvv^e19vixH9+W66*@4W>n zE}CMLL$nImp*?v?;X*AzAoA`iZs+@49;3f0BybIe^sWuD0=I>xrRRpV@LA_D>N-jB zpNY4M<$0_BJBNDttZTi-02Kx@$CL~HQ>u;2FzV70+AqxDKAuX-h+mpaZB6JS&RFe4 z!p!QT4qA2kPqBKt4#;;XL7;LOMLLkF&Ql42AE&M|l5K}cD6Osvq*1M{SW2bf0Muli%=FA(ZId6#T*SP6axd1iRG+Sxi=11qo zj%^)Wq(DV8Y;K$R*(Vcr!C#14j#~GTs5fsA1XyHz1@@IQFSsNzz4``1tmK4Tev*Sd z8~oksqU}t-5Z^W2pnV+~-=bPHn+qANODyCK|8S&FFsu5=q8ZnCy&gvBch%1RSl_RH z0Q0v}r{{V*+_wW3vNuiv!UGfhAxe-ss5AQclpgexW?uBvXC@v$FgM&X>hrI(9M&2_ zcsqJDtTR$h1ootgre=c^?csC_DZ^l^yY)ZYle^7A?$F`K!&Mu$gnQcBkXVd4@^wXI zgOthOwG*=Gfs;Fbwd#Ql@}{R88$;W&!x{FMDk@XlywqVmsfFoPjIG3&^;o3kW_rCj zWNEfMFn&d3tl}kL2y=66xlx?A; zMKU?HC@oXWG5&Yzy8sR`Tsh92Hm#JMmik{VE4|6h@0{?eO{&rl$}VJWi22p7Py28!9RRXVTab}~ zmY9a!PU^^yUZC6S9k?f_HZ^BU6J%MTHKF!snu_Ll!`I0>RKM+re6*e0R zwwqa~@EP+&6I|@~u#R2enf_iQ#C`m+-ItIK?V##d^84p+z!~S=<^J5qd+n;)nNe$_ zG$tKGdLeG$D~NR_)cgo|1h^f7mZRV4(b>4zf5P72{3DO4E7$92ySf-Kmths7|GU3D z;;Gzy$8f|6y*_StFb!Ubx>G8q5-A7GL_ddVmTET$iKK~jEgwLCz~_^p3Ffo6(7A3m z)4+Qpu;zVvm8!uCIYe`iZ~Pg@S*n*bdoOlmt|>JW`rp69a(}@tetnif_wf(6SlJxH z(Ax2h0`qYbGuey$M4KN-VUAO`K)*~@(!}8j`MGaCnbl~tf~vf^`1#ePy}n-VqUHRM zNpgBQQFA4c5ocr(7M{HO-GEgXF(O#4OVB|+!amqtL>XH=75@?8yIfX+eML)XC*c;P z@%*7ai{QSmermGU$kQIwPxX{P!&RK>r_njw=DVtYrCV8=|eD+OliMcBLiSvk)Yf5vK zcm-|-uah6HHT@=1!MnpY*`M4=M`>)CWxSQ}xwjGLg(H6n`?GA$G2OeF{)yOnz9Mhf z2H_xUnwL#J>*&pIys~<+`)*ae0xc%~q3{r;;=xpA=*6@7q%kFZZ@J^VpID#adO^%l z*!HVu$1&TRm3j4=C1B%_y^IK_TwTu_g!kT0>zY*dKQqk6XI|F1S@UeyqJo5?*CA_S zYaXnI#e`;d(;?OP5fg}dLxg1m((fow!0`fXfjeR)*Y-pERQYxGiK#Kt)Hiq<`ZeWL zIjNq>tG?ww?j&iiP;8AhikP8)Ys;5pnrn;tXKPWgdA@63xg{{rlclU7Eu*WR)XUts_TqMQSfBi(5fLQ&w z(qG@{35^=@surW(OnHcf?XQ#;Pf`CF!kF zOVzYY>j}V#ifr^EZ0`amP0@+qfDO%p8#gGe9#?EWTEKErN5939(BQlW4mD<|oT)na zNC?s8YD1c7j^n~k@7%Kd(vSxb4w>CWe@0L1iFF1~ zC5D*uU}DVaeEEIHiN5ub&D`Reu(>*#+Es%%NC)tl{=T!O>8k>T@|YTbbM$}U0YOB* zdvu@~h1{~3IHS>cbG~KA2&*hR2Qj8sF{RVgUIxj>2@k!5ebT=v_+2JdJjyU65UULR zYddj#41DginK;<@_Nt_*S@CWewg!e4_;`n+3g}InfBpQgnN8i*+&UHZfT7xOYA$@A&NVm!pZ>xzXOB5ZbaQ8Cj_RNAk%6TH z)^aB<+Fm6!jz}0Yz2(|LdR=%cSWL^vlFo|l)>5+8VY!#kBT&x#gaS+tb?P4)Q6ggb zu$iUI7Wn_E)WogJ`E}2OyQ2Y52vFJtrJhx@Z3LJ zgyaw03OI*twA-02)=FTOAbMK0(Tr`vg1((#rR}t6BU$;ojgPKtk^uSX_+Y?JSWZR z4>IA|UHnOd4hTg%&M39cP69KF^P?tove1al>K6U-;Ie zlOmJnd|72E6|aQ6pig+5^bwku+332b_jyRkxQ%|T-%-z7dmeE|M3#i|-*n65)G;6h z06+h4T%Cn=#L}H#!JOk%i{GPi!i)An@S;Vf-!Px=oNGU$N=Yc=jGa#_dtR=zS%vh9 z9aXFP18P!3g2}RO^=-^pjAU)@@?0bIix0Rnb^`kxGu z^A=9>*Z2FcSY&X|38q>PJ}4<=)$ls>?N-0w>aqZsMV;7A3K3j+SxwKG))i|K?qV1b zd#fS^zX-NLbxw?jVam$61?rEtFRpZD=wTjGQYdlBqNODQpWVCl)xm?~YLu1?73~%e zIbNuJEq#x1a{*PYn^9PQ6&XA7=4^DZYUqKX8J)kx?IKbxL6u|r(XDbgdriI|Gi0Kq zV`tLX>^P|W@iQUbzz2=B3Bo@Z9;1(VyKAld}Ie*I+pA$x(NU6 zMvtA0oe0awskx_GWIrRN*MFOmYqRY5$F@DRnZkJveF_NN*|*-i#vXk3g#{K{pw<{+ z=-zHMk1}(D#gw^s?CW;;=)d1BEB9p=E{% zQ0#A7!H$oDa17Y+=(Eo$ORY?p?I?~<*-1b5l>>h=f;XU0>fbXm&R3F3$Z2cO- zw$ylvj3t9B2ST(_)%Gg~r}dQr#q=NO=O;BuE%%q|M8{SPWeY9tp4-hq`fi==(vlmp zagh;J%J`qP*ZEYj;_>h`ZsBZ(c_p70vQq{BSm13brf!~wJ+_}lGNIn_%W!|?gayoLdL?-Yiz6x{W^Sj9(AMfEgh(GIR9585iLxoWe;LkB_2}( zcHjjiRCfOZcIM)kUna8ZmA9%`Nm%c2U+~7?X~M=cTh_L})4mhU5~hxoTZ#f0w&)u8 zT87ndVkMu->!hD=w~(u4R6D0ws=SSNw&FB-U^#Q7;AJVHsLTtu2_Jx|0Tpp>dfY` zl6H?{dtsZOWxbTA-f?X>*E2GI*_IVco%Bm$RQTZB0v}j(9g1805dt7=aVQBS@ zFDVbI%>C!@-!N}ayzOo8R|!#YGl7btWW%!HKl|)M`ZnXBFXqYvcbc8q^ET!iGP|Ra z({_V)zV}vRZCjQD%00F^(f@<{_Pd;9UgHDT-h*Bf@0p9%e@wnBGO-8KvH=_gL#T_| zCN&4lJNz&5_l=_$a+e&$t9d8ODGRASe?5 zB`wYDKx|h6vJQ3{mgW@<-@NppGptGP=IGKKfbwJ&^00w-JEYzx3b}|8$1i7G2D2uD zD*zOl(-Y3^kF8esf!}-Q?|&W|yk{C7@kqYeD!{u|a{nDO#5+TNyJz&qhezxY(o&Oe zuUv>O`f{%N$+I&mXG(HncQx6inBFCqt9h&lUe|EY3VZct+e6;P>SL5B!N^GFehj)R zPYE#Tx#8F^+6t|g9d}~H)a8IW9tq{-p3HVemLFoqB9yo=eTK=C@-p(WBzBUhb5(n+ z218yS{^dwdZ}}dpFxN@!IR+eu_ZTI^x zb<|VacCS7!TJoMk&KYE|Rx?WXo>K_LlOWSCXEpQ+r0zlD>Y^RP_t;7Lr+7`>V(h5~ z7q^nH_9n)vGAo~2zsE;~^<{VaPb}X>FGBgIF}=tYO_MP{r%hqf$-5faHx1tC+6wnc z-V{sLqStg6MtqxxAOdSdtPF`mGFe`44U2@pl52gtNo4Q7SRkzB;_gx89$Tri#^q7H z{$A9gn!bW@T;b}X%LQ|){R^Jg9(vJGR~%zFHV1L!>B;U(+!~ZE3*f8W(sLIlgSj_C zX)m?BL)}VBgu{25xw__eP=Qt!8ze_bBYcWLGR_B&*1)NNMd=yXDco!Mc? z)zCDMIodf%oVJv^0x`aNbQd4Zqp+zAmgsDwXzxGQz|x7_+up)nS&3-RCy;>g)p&fSuGAHuY29+wJGbR839f$>u@ zV#oL=47;4kpMrz3_R8!U@bk!%Y`Xv!%H@H9pE;AhzNA)z`8#N@Uwwmi%=@bTfbQ&? zYAo~p&4r$^5Lo|H_Ywa&wbY1xOGzx$q&(UAthS}++XV6dFFHDiYcYJ+FZY%{m>prz ztK>O;6bjIyI>&VC8g4c0Ux~_SLypG3rOVSLN>Z0)Vil4j0t$Md=m%Y2p z1E{zBc3?XFeT!<#L2KAR2vuP_5s2@5qF6t@; zRxh%U6plQRE2{20q7h$4I3NiaC=Ge2E)BTAIZ4jmNum69aT8t}(Sf?4I=J2^22;BN zMalsaSCBuEH%%kyjc-`DgQYiLEO-QXjf_)UbXf@?0GS%yva^xB?ClE^%{e}S<%rGm z5gIl948ku*eaS(w;>Vy;wy7c1*}ArmZlnQ<5?g*hyq=BHh9v5s%Or5~zJWb5VzUAKf^j#=~MGn^_ZVN3izC_Hp{aZfW)GR}n=8g>* z;D4aZINIB(m=o~V>yi`6%fRY~D`v#g*#qd`e(r)+FZQR#(~zq$jnH0h&>Xz)?ZR6( z$8uzd^sJZK$NG5hcH9qrrt)UI_SaQ{I<_9CI9TV1+CNdrt+5Z_bDdMb>$H2A0IwD! zm&IV3jMtV}XDQj>``8*g^Gk+4rMO9Q4p1GmYo+BL@X+75?IZlMCJVCWJlQjFd=Yc* zW3E$uDxdzcLA^rhnz4AcbAKqlfily|ARz;<*my)M@3x;CEIL>t_mz!>r_#>51@4Y>(aNaBpGeh%snc>%mLEbOXnP3sx9 zDb&6R9zn1{_lxD_3O~(yZGFNWGbl_J#d#$i|7c+rS;Z-yS6+%Tc+<~B;Hm1rRjSOb zOoAC~)it-K?{i0gxI0JYgy*cRi9|el1x18${(5NORpi7RZzs!*Qh384)SJWf;$Ed} z%vYfa&Ymo&P-UR1&G@E8__XWTYQk<;@XLn&nEA{>J+E}FX^WLWR#~+az8rseN%`JN zmlfIZP~94HB5hn!_!(xweLK+dH$Ytf>zr^1#^vxtHs>~JOb7GJZPTLVlyxkx)psJ@ z^%V0h#A8!R_T^yW-z)9uodFNKM5=xd8SOmHn>yGUvMa`K&1!Neo3LZHW>2k&-6Kal zZ*@B-jY$G?$2Q7X_Y0^_&+LI2v;Xd*`w=g&ugU`lJ;DJ02Dh>z3QoP!-M)mlKw6x< z(>R?z*&J&|AHI^(Eal<-pk6cmgIKJnQ!b8u3_dl>`NWQ$Qr7kKs+@a14|+Z7eJpCD zUNQ&p`XXo6+m*JW6Vdms$Xw$)qtW0_!{3W31KpSQYOAjRQmIC5T74l4T`f+?uxP&e zlA)}4ONb0xuB!@l6shZ)x9Ehu@_38M;C;F#$!VmF*N9zGr?v)L+s=e{2 z3#sBu84|su_;eMOh~RaDmNf4;i=0AM_S(;Nx74sanjElAUd@2TOG+IH+n8HPh-S_} zEZth+UCP;02dETsqA%t!MF?hx-^W$8d=7eN?hwV6>eBOKtR|L%R|drhpOYH>^MhN9 z_RQmA;XI_aqxPSXauuT$`qsxkb`!{k^qs8*&dH5c8^-#6C=+1r!5G|r;aj{}Q2z*7 z8Ip`da-TTekQEU5hxGrrSzlf0y(xK~vRoZ|m)f68i6br^ZdzbaSWhYICwnxUY~ZK< zgeEBvs?8e6sP+GBtPhl(#cP(B8=hw@yQJ)XY|7Z4E1Y9EdxmNq|D?HrhJO!cOkrRBTglTM2F~x3T^!XeemDu`r-Bx@#I4j8Y$rB z$~9STpUoFvxcJ-cTwhvi*uD|4&|ze46cZi1b= zmA`?|c~)zq*Y3m1P&(WUBRY0wtnRUVN@UdG#}W0~KU<-_cFrY7WJ`_GDdqU826hRTAKcXiEsWcV2|`tNs-2Wmf{}Y1an5aET}SY z0p@J6%6RQ8D?K#PkW0+e_}OVswN^cc;eBx$X`5cr0cmF%v@PGOScZ!OTNSKNfD~c* z;DLN~DeyCn!hGYX@_(i&VWT=4gC8my+^dbtNB$LdI-$UF$@l&>GUkiFM*rwsa~c(p zPd8)|VBAqip~7de87F{QMK^lQvRV=S^GKQj=*!sqPHpuiNMI z)VZ=j80{@Nt3RVz22u@*-Yi(t$4nr+cC%uqtmmtG^g^pcXgUob$ZPhc9>D5|+|VCj zo0?mqP8CwWFW!Y;aX3%*NS~1buU0KuDW8a)E++L~w|cL6h4?N4u7I1KS$3}YU#f{? znsVGIqOu?!xHNS zX~!g6h}_Q;V1o6w>;l7RABOrHl8`C5@Gn;~?tR!KjTn+z{Ia-D!%^p|!3X{KLUUE& z`fOeMUXWK3_M?HgJiDSg&#$9gP($fHAB-K9w&KqxX6;NlzFL#XC8BYp2MH_W3u($> zgYel@-!=ELcYD3;DRYUTZ}Ily#N$iH6X_eE#e~+nUZeR2j)8wskQalUS+m~cpm~+A zM0O}$`Hzyf2wdO`#uOZ3vwEQ$m$!|IgQUDu$JA72Jz@Iw!3L!!xz|#dPZT(P(h$;JT_)0 zZ>x_m)7g`t#t=^woN$CGURikLSGwkc6U)`VeC}35IOJ>9#O^Ei^&{Tz z+3h&~>Z7%j!7s*|PgY;$X_li%hbQy*o+Hj<41aFE^W_%mHY`60IWuv5PfJ^oosBd! zA6MDSP!oqd(0d!mCWU&HiF-t*x0Qy8h*ABxw&|4yGD(~}4cb|>7h{V+qHkZ>vL{}f zWVMR+ti$qU2C>)UO~rtaJkS|H0JfJ*SSN;Jv`W8v_ zfPxzCRt6uXRfP#b3gRedcrF*p7zMbC&htN#qNHER$;jUz{05s>Nu6&CPl>AZ$Pat<;EXpVU5Ly+NP6oHI3WHDaJvU2v`7Pmg zO!EyBjoiOA_nuV;0QP?1Q`{C}GO zM-7MDBBd@*N=uUnCt^d^;(Nnen>w9>%0IV-R9rGUIe6Cpm7ZJe*lGT1mk{iYsnZkG zA%}HPM1i{x6!Ld4-j-IB4ITxA)Qo3hsBXV4-7`c>3=Rs+M$8$G$+IOOh`F)=QcaPg zcB?(O`~WwOlRaY!^*9&Z5Sdi{&@Ia%p#eljPmQSt9|dRbcw6|GNQ2jA;Rm|N?S5XDi6sxVGnbSL`s{CH8;u;)7YBwHoW#d0Y zyaggCT$c&)aY0_|>a}ubk|EXq_SR`7gaV?P$zQL4D>|lM6kzp8lYX&Lypu(_B{N%7 zo;)PtyWVI8v}bCkny|TIH8yRl^`QIpw_+uGp_LQf_i5iVtxGp7Fn2I8wgEYrAAWbT z=wi7+=F^T~U;D*)i-;i_wxaCj;D3%iM1S)(MHbAU2NXB)vdL$&9ClQ#v%APZfu63M zV=x;0-FOX&)<8V)jEJtRg8K{nCz^qq05v59=-1qFtdtUBl0U~3`q2RkpGGw4TO(rX znuHYEu_*k1)#ogq^4E%cw;bY!)i^ORK2RpM+Hp>Kj^n$WHNbC_8 z>-`Nv#|WbL$!u6?`|^Q34oAJV)_S@APagTFFKoGLC&!`3+11{@?>yl$O@fR7*&zoEW zOai6H$ULz7szfI-SiorFR>qDzFuftZP)~P@h;EZu4As?KGe7S(SQ{8;;Ny)rU*r$t zE*WW*(sx_Epx5<5tHX0mul#b57Uw_oXa65X=l;lq|9|mHl3Z5FT~;Y7m(kn}^-)x0 zm2$r;%l#f>?r-Ftxey^gDxsn$BUEurCPGc*NWSh-%q8Q?rtrKi+vUp`vYu9s~ah0l%UQ# zj)ZQA-DQa!Ju#>v27KAy7=ze1C1TiQMHK;iQk*iDgh_!!*MXY- zssM5;BeR8?)Y?R6>qbn6_AdwYfjP}I)`_k!rUBpz6(e097z_CX$rB>D&hDL2!^oLR4( zkhIBqG~bBN*4*o}eW{ch)TZwR+XK1vG49e$5K7t+;<11ved?F%2MHXXjL7efmar{V ztL#MlcdynEU*S4ks~gCn_Ri~v-n#}NS-{`>*s6sn>F%gI890&Pn`-;;Sit%%ztd2y ziqqPq1FuNOx0Ghwi(~sQKL;*mmb3e);Ji12?HWi^>a}gDgl)!CV#Ydhod=9cLNd=prPOWiaCzH*uhJB7?eDFPc~) z*eCuAv=kzeyP*kI8wku7rUJ?Ai+M+Rhp=Zw63g1AdZ3sF-MnWx!#XszpiHe1>zw3! zAm0*IXDx}tF9dB~;jYotFn=$t)q%)tRG3cJv&Cn#`ZFpvi=y9x{@gmazolo+%X3yM z#%j~bi_OOV{n(4h>>u-(%jPkr_j`>ra+NK_|98Z`G30s;Ubc~?@Ag&2ak@i#P6Bs2 zv`44q*s=WZPE~Y;Y;xW|d%|2~iDsD&0>pD68l#SDKNy6Sl0;3ebF}K9xs#&C8tcD< zX=VLUe&R7=chg&h<-htF5MSW`$PO$FGoS8P;oqIHM^WX*LW zKq}BtvVP{EZNh)Uzrgn=6U$jg2hN* zcXs5+k(nH-J9$f!@xKoCsk=N=O(`CmprgA8t)o*h@zqNiV7zYVm0%rN-I(X0iH{G#AM@S;k49_3!oGnaFP?kLNF#`u_}sLfxIc6PTJmfK_|J-Xiq z?X??fFlWM6Y$lfgjD;<>z1vcKsqi#mPJOCKT$z=qK4!qKj>1G4eIFU#>EQpJ1?fyZ zeH;j&zQw9lh+8%{dEDBA2+gp=R%yQl%TMR3i__Q_*pdM6$!7MSvu&WD<8THYV;jGoZi)LP;q$r7x@D5uV3cjj;87&i{jj{z_#iWm3w@kK{INKHt5R&a8GvS-))Tx+Qy zheS((O@9*&`HNdbB5}+IP2|*KBz1h7@T~=(`%(|7i6d zbO=$i4Tj`IiX8nOpv3LPfgjPm$5cJ>i-*}pe;ZG$F#HKgBJCkV{@>F5-`7lCRenL5 zcYEi#@_Ew5{$A2!Rug2OHa0o2cT!npO{S^7&i(B3W_P_=nKCU-j8z229C_%*Ykok@ zn*_~%spFuAd6m|Q)?0*r2#o9c-@dWKAB}+wRb|MT%cx zw{r2}W3y8GM$gX2FQ!sfz2^#ga_Tr|VsT);?m%Ui^X|b8jRW!18$q&i+{&f!Ebs5a zk<+{J$>an|I>u?Ba79NR$4lZS9p9taxOP7yXm^a`*d53%1V#X1Q-X0tuXtsJepv3I~nQ!;n@H!F`Xt611Ph6Q`%k&m6yT>rxlM+!yqxasDgUtR7jsjB zJMyDES|&4fYF*F+n=5Z8P;nA5U)LH`RVimsMehlBA}`rp&Q35tGf<1}3%|z}=P!!4 zd*29WA9(p64_v6j!{^_sG`WoBAG}kBgl5NQ4{UZ_jo4tsF0H-RTkfe$n$VY7#^*P! z;l_-pwsZlaI5~A#lrd_1Mf3W$LXwDHk5BMScIgJ8JDZJZSwARnDaE zsMTdFTWk^2X}$o>&>dW0BL_3>oa~U_)`o| z=r!HAOS?`~N6!bCnLB?q6s| zSzz_0DdT&D=Le3*OA~8rqu=eZ?gjX6Sd|5M5yTSO(O)GMh?h~TS>)IaKX3PJt;b5S zO7R&XffW{-LH0YR(4FqZz-3*9|C*z;S9%T|$A7B#a9^mxao?Z;X7QMj_|!#)7Nyhq zJ|?O8ELfPO%?mY{2<4VgvlxP33CspS6CHzxE_f+8OKzm06F?s&zow@^M>|)%EH5J? z1uv^?1kL5lw7`C(FLnQ*EL`abCQ9X0=@7f(RRQ6G$>^Yl%Qef;mmb6e6x z8S=TTyzg_C@+CsIVDpzp&nZ6J$gt5jd~d9Xk<19Kv1vN3%_Vs;zrr2svs$?x!$95* zvB0H{8#JC!2+kmk=aZhIdBMETOj*Hm?n96RbYVl)4qc+j-73x#AouvBD&|ag? z?zhdknkS;pB}GBzD6V`qIPymyx2M4Ry<)hh=#u-jtK6%WJV8g^QmXe7;P(;P(7UBI9$zD&d8Kq*W7E z3d>VfjaD&p&R_NlMBk=O1tGKXGC3{K+>MQ?DQ_W^>CX;YpX+(+_<3Ov{!y80Zxp;U zYy0eIh9feZax2gr!1?|KZfK-$kJVA>3{s0V_A^6c^t(@duq}%bv35Uckv%kq+$Br& z@!`U}R<-e5N`PcYF=rW6(|!EZR!Z`K)}(X*4sm6_BiBwTy(xh!=7m?PN@9r#K0yKV zff*V~IEVY>7Zp#8Tu_U)D&wH^Y6^^?QZ0iGPW0n9X-VKat1L|N_~@NjHP+i^6~udH zog+7)h-ONF(^4!ve6Kctb9bEdrPVI7$oE)T+haqmQe-yq2k6_ROHgU|`OOnCWn$1g zdNHz9S~Wh*-D8{IBicuI^hiGcUpMY2{!4&P{nE_5K}e^=v`>)3cJanAv@5bl<>AN{ zJ-wI^yQP017|Q3to0pB<{9=21|6;*+j;zRpLdFx%t@KH*mD_*Ay?YyXd=A1Igp7@W zWX|>F{NNJlzNzR9+Z$kyCE4ox0sA!d1*WD;v(wDinM5`}@wmXxD(QPa@FxrnojB@2 zEj=NZSb(z~dC)JpkP5dV40iUweA%pRCsxE>1ci=lI#4+>{su?9hCA*y$f#7*!{w`{ z#9?9D$Holb;}32oHSrkwc&`HhD!w zK`K+yc1{XYoYAS-K08IMyk4P)sxd#+-Jwlp+IfZba=S!ln@7n-Co42=Ik+|T{hClY zh*}Il?K(Dpv4JU?Ls#HCVbn_a+MS;@V^;L1w6mH!+Z`zV%OKBUmTKU?<&Cv66|Xps z)CyO?V5(P(uNU$iHN3wk150wMM-)CY*K!K2P<%nv-Cd;oQ{@=ijLdio-97MgpG}TT z^^6{9vo1W`47c{et-q~ae^(U<8Lf+75}x_^yH$spyQEKSY$$Y0pscBvKD-(Rpg*)v z4`Iu_2fWt*CNcyb)&D-y%I>;fL~eNLf^^jNcNBV1Luw$KoY6*6Y`}0MwOF#(AwLwW zf%mMblRDz^853VV9SNMGx!LI=uWB+sHCtna(P0q! z@{-I(jMVrhH#Mn4mz5dH9DcCY>#|!akWU-=kIWskoK>WMlp?YOZQuF04jt2fW23EP zP;Ken6 zD0eB;A>Rvg4@~nvkmzs3l+RX=1$K^Q`gJsxo~sO9;Mjk7RY#*T!w%Gx>a3>TRR3iC zp*0U9s_+V|Ibd6x#3ddnWpor^!t4{R)~m%GjBx3ecC)u|Rz?Q>3aSuJk5sS|7Gh|? zl@D-vF43fJli>&O`?>KD`b=1PLHw7yGO?a9s@blU?Z*FW&vrpZp_j*hMqoug*iu`Syz*cGo z5+7?58PaFtyiz>}40b=b)R*zXA}4Eg^Fehu`E4D~oVe!h3NTkoraTpmN4Oo`ubK`S z5{y>);zIpAM4%1-Yq!@%E9bs@7|O^p=p zBfkL8|6F?RR|;{F&06Trh#jfM?Y1o%jaCet|L(t?H`Ug}r%fq>JV#!d%ii`#J}D9M zs62%E_N&6Q%)mZ*q*KyXCy)E%C%|*!?b&TsgRET#!pJIwbvCO)2}KUNmW+fKx|u5?7puz(!i$( z4$Iw$t6mTlTk-E34mJrq$#M6p%aBB5f-Rh7sW8uDMbq5EDN0Q1lYt8gwX?LrCa>>% zg)CT&@XTB5NFUv0lP0&&_!ESfh7qy21E6(&4$LZnMKb5vwckDWDI5z8tnU|inXk?@ zDf8Q==780a-n;J{Dn7ZxkZUT@VB8$FVl@Rwilks10p#_z&N}@N?P|-U%?XGWL?VX1Lx4mZP--G6a5OvMsO#_GxMKm$_@5WOozvu+_xo=D|WjJ{6uTR^9 zMWB=Ax{rvOWf*oG2jI&*j`is#?&xPeapu{HD#@_~bKmd&Z+|>b23TF)Y)2(=z$_x2 zHFAp>w-NuX8#cdk;ZVNkF@97@?2r&oy%m#YM0z4OWRnjyKX!%=)Z?vOvJ#zdS8 zbVsu1<;}GT5+?~M=O#;84opYjl*=xc7;q1G1|+?*S9Q~V&;J^Cf# za&m^+|90YFF&PBVa-MN}_E1&ePFQA{iq3IL^MijELY*ABv>wj(pwEKm568Ak6aKb; zk$QxR6)`W@(Wxrz2Mj`C;%h29$Lm21lcwn2>WocM&99#Qq=J%_{}dLSO<#EADS_Ur z+e|SYpwD-Gg~oHyKS&hZ70=2qt0j^{ytp9GG0%4Xt1HF}ofFXB4R338RNa|jNz%8X zLm0;ke5_4sME+(LS4+5s>!&!ux_JrL~<1F;O0V#~8kO9m@Z- zy25t=C8V+Eid@Ji)~E1UwIi0@ow~2_ObxMc;pKw|Nk|sZJrd<4wPnv)ZU58)$KLU-XuS+z_FAtSMVh z0&9iB`s0@&L95^P{DJ+5s0lrdd|@Ux?Ze~>MCEAv(MdX0qF}L~cC$DLelP~9lfXpO z>GaZHVdVw1^19BkX*dj9Q~JowP=MCTZ|@4BavqX{RnT_8{ib4w|A267?VrSeBH$7u zoBg|-w#)=OU)xvuW7djN)A~?Q$zi=07MU6vvv^PHJfJnSg4kkK1`>X)xsO@8ctW7F zbI$|cND_XHV#6jJDdM>%k_CMaz2pDIl*Z)H8=ICo^?stq9*p;4B#8%JcYVL}>n`g> zJh0klW%>FVgz%{5CEe+6d(ivVM*FfsNm454BnS_`#u(#%*pNASY2|iFJDH4-34P|; zzUZz}^e>FqITm0;u_)_oIuZDSgZfnwj7rvfgbzfNWwre^q#w_ok;7qY9cFzjn@XY$ z50gf>99zkvRGYpx=(y{?9++9nI#*5e-SxE8W6yMbj@rT2eh(`tTv&~L;{3xkZ}J4+ zmSza}ZqjG*W}+*l>eoL!J2=ZnA|s1=29P;j6>OnG+`9|=U^hp_w%QQRlKNFH!^mv_ z?p~XlbBm#?Pxop18hm)K4#%5+``0DJ_(K^fJr)QVXfL?NB)5?AD};7^M>4kdz}XJ! z^U6yo;37*2_f;LG>~r4}r3U{M8ccBvrU=)e1Dhm`QdQXiAp6A9Dste#=Gv4ZUsC`= zU(tH1KI>-lv`uGL2#r8-qom>mTpt5+pB}DjCZS}t8GhA2I#(6GJlXze8Y}UtdNnzd z_h^Bg@jve~eHVI5p!D8d>m%^Y?0Sy}lKn6pI7C`}F#6ED$h0e_4fFuLAbs>&UQ(`w zM#%|GhlK7(VxOp>92@L4uEr;=%3SxmPFikWIGB$VluXCrI6oPU#`zjDGxv&Odd#dm z!CRB?bBdytceY#o=ZBb2>L5Zq``_LxNkpRlh;-X%s2G4^a_wwBIIIu&a~x-qO66!r zd!>-CP_K`$)w!K_#XbR7jn9X4Om3usCHiEp6Kgl+O+w%kUz5H)A)jyipXwEA_!!?W zfOUB_(+?>vH)CM0`qFKv|4G)JrcWHH(P%w=!1-i|M_MyC^?#jwFyUPJ3bUT8Bqb}q zQp=?L1@O3jpk3wp{-vXkg*)N`NWT3Kp?~2MjNT)6~-ed)T6_Y4W}75RdIk3AdXUPtby%D}V2lZ(DyqWK397j2)d-iJxnG zrxbzd(O>bod;i;~sa2j0jXJsyd%rpj*JJ*F^QvsRRIFT%PlLWj;UoxRoMk;e676d? z@#mCOlH?qfCB)s)9c!~jumvqfffw+X&whu@o2F*En24%jj-!Fmzb{SryOG%n!7s;U zk$Ck&lhzm*3|-s=x9v+&&{(A9@3@eGB-P@THe~v4lE%mbW zyZiq;1eErq1XxxZjkd4zx+Ep{!=o$Oxl1Cao8gCbp2ya$KX-U4B9i`c;7|k93LB2@ za*mD!50MyVJnHyu2nrWf8v%s&hjVz17uNk534{HzUVR<70B3rZ?0&oI%@c6$P-xwh zdaFPBz{_63?QEf2P5sF-{Fvi1UYI$R2&GM)`oEeNp|&sP{4*~$N9K1%YD+1%|E%mv zZB?yIP;Z}UIQ#^f;b{174Xcmd|D|E$S}^eIb<7}U`3d|2aErymYRCQrqOK;qah%qe zBF;=%qeaIsCWvHsgnUxghX81ByvI{5hz6V!;L`Q6F2V(FybfjZ5Pt=1mz!JR2BKs6 zorMs{x|=ogMOz*$Zm7_<`|mx-+@SPkHy*d~RU0Mv02ECv%H!zHa862`)2wN?PHM5c*ih&+TY$ zHl9k9xh{T&B?b}u_^&u5;`NxUH^d+}B>+e@vsDb~JLYF+KV_uWQp5JdlEo*)CWtlKcr`gxiFpq4Msy~$!1x!wuW2cM80Vv7 zfeza5#gPwYJS_7udy#9yMF^XqFh@dD-{a-jq3QXoowLO%eJ@see+-c)7dE_{##KUI zx-B$NY8^#OVRV1o)mOaHDP#r0PBVPF?n2;NOrbvLi&Kb_>6vDQ31j@_^1qYB-GscK zDBIK2u+cj^(YZ0lyJEPf!TGhg;EZV}r**TLkCUrd(NSS@=i8Q?n^7l)`XX4sO}fmk zKiRw0b9^vpT2m9f6$3LA@F*#CldK~BT=Jm?pekhkfdpiLT2a zbg6N1yCJK+^_DkA$)n~9s=9hvj%1?g;IYQ>s&E8r3(K9;tnZdrI#vMuXp-t~HT|WH z_}*~YWHzrJayya!-^?-3C+1r7Kz4`EPD3$zeysDd#8@QxZiT>veY!FLJ;xPnzH%S0 zV1c|Y7I!3!5j!%%sT~<5`q(lV`g*T}ko*bQz;SUX60C12m6w`csF#h@P7PX7%hX8h z?OMz3uO0g0sSWJo$uIF@oy1@YGu_|0XIUHgMUWDvwbcF@ls}u+_+kToKmRr39IAbC zS5fQYOiuHd!%x9HroHi&_t2NItB%w^zazjBoq{4*>x5_DUbhQ4N-V6b8qs~g3ISJ+1-PBcKO6>XjJums*nRwX*O*f{ zcfj^#BCW6OC5wMNmbf+ZvifbFk1i-AXq^99Mt9G>JB^5HNn5RH)y^jZy$LtqNuI@Uk zYV+dC2TYDLw@7a*>JJl>2}8b;@%5bBYUs~!RcAYM87#NnuI` zSZY`50M^&)6ZLYDTUk4&7n??vwp&Gd64%w#WqIG?--$pfrKGl76n2GJ7dFou9VFQo z1tO0H@pOhQqW%i6`Zbp!Y}CfQUR9R3^zo#iYW?*9BsDueZ>T1D1v{V763Z3| zo`sv&rL-T6WjvUebban)HnykgzzX{pNBtU_wYFDpM>AQ|SJZ3sN%4OtsrU@ewjXRi z9_cqg`cV^sr;HuE92PL9Q8aL4?l=ZT0@qn<+g%#t6OujpRDF8X=!EWB3fhCToqkRH6KtH(>#?ivzPgt{M zC%{iSn~yC@wW;g;(VdsbT#Ld>(gD_+l*wPt;)+7t;{|4`g-ZZ3BzHki^gCr6_0MCa zwe%bfL0@K6RN$xtwxN6vIkYtlqqc1wY?!=|*omSPPP!m#=@O0vVJ|3Ggd5!oFMl_I zikl=bDH^|Q#8ouQ*VXE~5f_B=l3BlFC!DQpWe@#ON~8@?}zh>6)c{JBRMF&*}lQ0DK(U zKo_0*p?XG&iYWz-IR{qJmPfE1Aa$)^5A}fO3C}Io{JN|H3IC%Vri?H_#q|e_fb4c@$8YT34hJTk!!H z2G%q&e@`sVt+0MZ{cIyRV}NVRz~S}O?2pU1taZS4p8AesgF?0sy~O1vs^0;!?nH|2 zA{wb-9mvUS>f0`^*%yYNsPsvSgsLy*x*JZt_4P)#cX}#PsHuPF_}gUA%C&`WtC9ok zOZuHWgY7td%PV@e;?}0bORKj&<#$T4dTLtF*B*t^srd#3t_HB1-`@U6dZ78#C*8vRsTJow|yC=5BTBckK~(rq4HG&)@|YDg0luWJv$c$H^%hp^rrwkZ3)pj=B#GdiUYGP?Ss+U z;rxM^0__%zSC9!$w_c=&0x1zaW&jnt1UjFWbxtd#$)jQiny*A)syLxZJWs0?T((v` zR~^lFYIaIh^Jj6Rn}L=|`Yg+js%$_)xu$=!iq<1ds%owu-^6mT*cGjwqevsl{&;j| zx%E=aKLyj?>ZQ>6T7l}VVAL4nS^+^nuXrli@rzbLa_02%rl^uq`8jMX*RON7q}SCU z4L;RU8^Q}H7BYKI>`$6*ClA)?mCL7zeu%;x?_7KPPrcpHqSFDcxtw5yyXCk|L3-9i zcA|PiHDN#adN=fMU4&pr}5Sa-+d={;jEX;ug6qL(9`k`>G_0HA$J>ik?hU) zatvi6*|ap%SZYRoYjRuSV&m4mznNafK~`ztmmM#~%0te9jdvv$IzmwxS^UTkJ9CjD z&Fdy7)ZNIO2NhC|rFP2?=c0d9YtgiFycD&;hJX|9bxOegs`>6$Hr-CA%&M0BFpuLC zgNs0n8~GJk9{L^OP$3B61+-`+pPd*K4%pw_8AkM5s6*=WCakz$2N7H0ip;jK)g zxX`xi)KeO$7%e@t>J8d0Xr|f)*e&e9IcaTmi{Ky?c37)3>qecWratr>SQcVN{XzLn zxP@>@|1-f?eVm4P1HhqXzigBH=#rlIoCW{Aa`#0u2FrqR&#$)VEsAM3d}v_92ED*K z@=)#;>4TuInldw7p+AsK5|`V_>2+?XcH#s7m(_#c$oX{w2SfhT8x0SdNZDJz_ukm) z5|@Wv`ZmTa3b4iyevZxvO(|)q_AT#tr3LfANkK@aCo#DoPSnW4N}~v=(p2jy)|^qm zIbAZDEBhweVIorfwSu^ci^oWMpQZ1)9#G%LCjYTP6QK#^6PZm6813mne2F^w)DrE_OFDp>rB>)OFQT!I}cQM zrdVdN`g;R(w}p>w3T2^VuDi+KYr7fu>+DV(NQLrW8r&G0ucxMwk?Rkv?rsofPB zzw7jNcT|2!a(}t9&gN@bk36jkaC2Y8LexrRb(d4CqM#BOe}**jcS}Pn-vn{j+9rAM z4xdtdroRDDomVf6a=SY|LArDND*^q*tC*Gkm9B zJrAafJPO>y3Xee25w{V!2Ty2E)->q|`$RP59GtiK+)c&h2=ln?NZTV&&qm%kcFw^n4Feus!Z@3zlZ(LneJk zbS?u`siJMW=GHz!6_}87R;N$Q zSf6Gm$MdtP$7S_9V%b@sWC9f)Q~rP$E2d;|a0c-;bU&%%A_l-+>^M*LijL29fM)4G zE;YteymE5%xDM2*OKf!*v zHzxMZXmH*ssvZi>GmngZ+ZFA%EIvHLP;VB@ zjY!6*QA|N!iEabkoN!6`Viff=;TpNbzUi=qIWMN0i>>CY9YD4!>`YHKZYx-a*A$@A zYT~37Cd72Vw9l*L#@{Fmy&bTJUXY@XlD&H+(-$6DX9?Ya4v+9UjT1PF_EYs0tD+k8 zt`sv+nJ{^MfXhhwef35`DRfq*>5wl&5Z5c#;(yL2l&xFqZk|!-CF{?jTg|(>vse2q z$`nvflP9w3kN3E>_W?U)qgKR%^abgK$qw1LwLF~b&tKZGn0anGc$6D*UsbTm%5^3D z`9xg4Js8)5rBJFnpRH~zO>_rkx#goSXm$Rc-=IAzp7e^Lht$)g7PA@8MEUb;`e509 zZ-E47&p%el({E@gEjnZ|@pqJYdFpY};{k$Exc}}>`+qE_^&OR8xPyfvgcSKRorWos zu8P>JdmiXAuS%>#O3pt|a9G;#Qy@--3q1R&X^6-H+W?Pj0P_ z)Zta>fQw*d&){8+KtOIdIK>1KRNVqkL#Fus)Fn$in>OdqaI)B|Fuy{ahToAa)%rO> z^UASmkGWqOVFGxjW#U07p$iCpHy+v8I3mP2-plC{8*$N7GP*x=sgd#?@^CjmB-VV) zK-TLOTC|B$9-FqJlcT_m8`Rjcsee}fw_C5JR!U=M`NkJ>$A}*DwNn8dB&&zEo$(FmNB7PN?OVn!l#j$9jjK z3~GPAo>Woj)KFoR)R`K5BPcmq(zx+`W~6T5@SFZuUVHQ|$FW}%JCVa*7>a^%>6O9G z#uE~b5G5JlS**-vylAb7mrO4QS61*&S6QrHHAkn4X2i;6koMikYT%0EI#1oQC#~uB`Rh3LHS#-o*d`7 zE(by}U8upwwSW)h7za~{*=*WsJaRVO-~n_uN~`SnO-~@FjUuy2Z7M6rlmv*~Y8^Tszq#ON4_0PY%xjn_P;#JC+)=ckq<{)bveM z*&UQLD(kh5lpoHR2UgTY?4EWpRiOQ|+qzCq-yVcpNySgAUc;xU3|D`leSl%415{xz zi_3F451L*uY;qazcvkIRx@Zu)AYVgkw9)5}DzzuLYg;{bhi!QS9?EtfC-i__d<3)1PqY5Ovp@BV zSNxh|Wmhlz&D^2CB|WkJ zBvB@e*x-xJVEOKq2J)(~I$z|yV1Dr7?H-dLSHG|m3NG~wo4Y~b!EJSFoH{AM(JIHWY* zOk`oAi}FWReZH1wsv5Dt&{R9SUlrQ$pNO;T7Z7MQzk#y%1x-HxLG?Gg%HxEwf159% z*78}4>*s00xm=5s@e-YW;ol~-H8PfRa@6Gl7OdwtI|~^henOGZh|ohyz;C-tbL@~3 zu=+cbx)(vGjtimPmNIny=!MsX;1feL06|z;T-Pv@W{N?fz@chgpD))3H~WY*jQ|iL zP3SABKf68e5N^uiOkVV-`qO2_-%Mo$zClL^i`zU8b)VQ_m=M6s;FZ_?w9@xo8H?HF zhqBR~r6=UFv{^3A>>W-_Z#6VE=F#qhDUz>3a6ClHIe%NMX;K}VV|_zFl_MwpTJ)dg zgEI>Xx%ZBG%N#@sg{v`wqD$2Q&H+(de2C6_Jzz(}`Aq@d3`u0MMLXX*v8PZ zg^g^u23mINI3z#WKrbB+vK>ArM~Iu|eo4Q+o8a{?Fbc%yI3HHc}C8!g1#!3YLiWoc-INqT@N8EtiR0n9z#W4^=T+|_t2 zC-O)Af(g9tq;te)eclUI_*qH^D06s;Lz1`02NJ!%!k`K-TCCdBMSfR7{N7Yz)y1KP zCf2gdSNJR3-}Ybj`6(v^%L00F5JhBT6M1*(Io$vy9eV1R{rHFa>wbOF5#av{?=k=7 zzHD-0?z_}nd6qcdNnI?1GX59xIvIWx?{6N8$kmqcI4*H=q)k{ zFP2j@7XH<%TeP{Ry?$v@AHzzc!!)lz!gim`$R8!(9?sMhdUdH3Hjgx(c$3}UWswWb z&fDL->Mmia8$^2B?dQ0qv!M0P2?$K{U(9ILbrxXtc2D6$D-Mrhw}Qmytg&&*_cLOq zM@a}5RW2ks3Px- z-m#a#cib~G`ensxI7*;ahmynAe>PIZy}xGtUYE5NsvqPclBZ`(WQHGDtZXU0U~mTmr}`QK+{ zczA|-7mM4^LJtf{qpDmc_k%(2aJVVTC!`# zq`%qvfYm;){oY@G7y(*s=xGhi=;J}S9Ei{BtKUQ5y2F4i(*f_-WpO(0%0?5!A(Lg- z{qG}%g~Lp3GZ@Fb$O4eKx5n%+BZm*;ZTaEm9`-7Nt_7GLRf~PXT8|PWvU(C~;Rsl( zEqpDW4tX=46vEc5mK$NVy?e$>92#!XCS~3}psc{wI{DTyP8KK^4;(QMvx4t?9S#KZ zB`+taNG2~n3%I_0^@@j%;J3WBtge{FwRE0nIO&bk3&)QOb{#E#mp2x`O(4iiN4K_c z$1mn8l?`*3m5R+HkRNmgp?lMlZO3)e8zzbQS_Hke@ZkC7Xt^Z*k^YlwIGip`_PINB6X^ixaCv(qmmYNdQYZ_HC z{ge5nL%CyfT)!u3vhtW;Z68eyT;3vf_w$<&Sx|5UQjA})YomYP%`jY(eIvfprEsna z)uDcLPi_AfBvk10ME2Z3H5Xu=^K;IexIw=(C~1x7AFRT0ngFcfOpjpq{AZsEDOc{Q z8hJMw?yIWl;_MCEGVO+BkwxZsqnBGf(**!OHS-0&yYajf{Hy8fWQm<2uxNC2_YBX6`^Ne0TI>Wv45k{WHMn_bivGdt@a~Fqr6*;-Y&8Lh$MmRCSMkFq7pyL#eB; z@b{8Di$@pb&xIHtUpcbCo=Kjd>K0pBrM^owU=zp+E3ekeN~%KKDi{%eHIlJNeRRvP$SHC-*3wyr7; z6_LTpYF^rZn*>I2;<^#24#3Wwd_$I9;L~M<%NY=;0?_6Va*bBjEGfjH_aSEyCOFcs zY;hZVlEJVGe9}necKqA>Kh%)k4}eF8-BvN`mR3nWd>t?1z8n`2vU|3u3f=2J|CIoZ zfXns!6@8_E_6{R9rS|>GJFaT+f>S7I8{e=#b+Rb zG?@631nmEh^vB>ic!mDDe8?vfrwPUI^B8*6i+v?#*08DUIA+p3-!YM(`FN2r8MZ^% z_>E*pFr|Dl(h9%mJH|`@n;Oy0kQmLu^&b^_Y^JD&6JuoiTVJC!^cZDcd0>v}QvETL z1H1BmovstL_p5_jyEVr=-2&D&np^d%VC%Vj_8v~}G%enSn#?Yn-@f!S4CK+BkYTG) z4&Qq|I-ti*74KPY_UGqJg1>fOozTU8+gg|ny%ZW%kJ>fLoWk|Xw@tP?tHS-xYpa23 zMJ~xL+%i=WN{bnTwGNL*O+5~kObRY1|Iaa>knSa=EtW2|1M4v&&vh4+fZ$(4)&gB< z&RxSNRf^p=gViBI?nZ~P9utDkl8KXxDG^&_&j6XAIq(9z)lCW>aY3Bq#-RjzVFhS! zztYXF@@IKv+vc-Np~lAAm+RywX0_fo4oCYug>tHMrIe}G|2g}TVAp*&3FC7hv?i{BvPVHW`1_zBK7+Kz#`;(x- zQm?p3x-Lktg8M8>?LUz{se)^fZwHi40REOf^G^}%Ut1p!!tVahlFu-B>jmRNpGl+i z#`}9-7ER0ht2OI#0ir9N3ldLH0@O)p`qUaL-*h6u`Cfa6DL#J_TKwQ`u z+t_@z={I5D<7e&Y;4g<6?T`-uF^;9`)!WTr%bUhKJd_9jN71?XGxh%uyepMk@`>cK zd@4SDU6w{}Gu>4}CHHGLiZYil%!F7HD!H>Mx!-eV%*>^*&Hc{IWpm$VW;QcFzklKV zIOlQBNp3jW|v{td~t?duhm3LgE4FBa>vE`%5RQ>=d(4U9g9W2Vx8? zU^SO@iEoEsPF^D;%2usp*ts)vnBsf9HfS+!Z1xY=7bT;p((RiMl#-_2dl$MO zhLG{-n)KGRDG3v%ObqX3$qahzE~lKtP8Vm3%VEmYw9ZG+ItU!FB|p zLb4W}q$`pjI9L6b&-zv7-xPxH58wQEDP*fjL!>5~R%E^zr}un;8`1T2Jpr+t)5^&_ z9&GYy{4z-Wo(!&s@7&zkFaxPMk+%AT$uFTeA6bhb^-ZzXGr8n=n-LF%=~{O zxjP8=Cr#a2+rSG#EwM)T1dru#MXvwo(+?ZJ2Q>a35+$EGebr0(o8AlE!wu;WZTNEM zK0c2}xI0uDwy_Lmb@DEioau3Yo0iF6AH2gjYxr0q-ewLpQ^%~qqBJywps!3BNps&^ z^x<1SqP5qL5`$@5bnCZep==YAiSr0;!~e?lLn{QzPImgjPK4_IzoB3C#gSWt85rUq zeWCaa=)b^!LgLP>6=&T1nbU9b8eT_;?9lFxql*KwkpG0!eQqw^6dk$sdjJ>8wgTqO$4x`jn9xO<;QwHB=BN<%$Dn!J~~z+t>UGjdIP2?dQq(&+mT zTci3YM4Q1uKx$h#JUwKLPI$!h*%|uW5F!@mY%nQc2y8>&O-vrWeeVpF= zgl#pa*4_pisocnG2*xz+!nN^EvspD>mO%=6IOAZ9;3ovEjksvRJD0yydD9jeJa>#)7dsd zv`H+dI%{iA@e=mP3O&Z=ZHA%#5BXo4zZNBUTs3)+gPlp=&Lae7YqP{t+z9y9vl%&s zkoPn~4($5YW?w|Vi&vu7bZNjVo0Ws8A!A^zntox(hlClGD^S|nZW^tWcDB}4`6syg z?;Eb!nogDQgE zd40pl9oM8Nu9sBw`B{00MQ98N2^-oh>s^OK$p^P+CH*@dyUX!@cgC95f~SX^0IMU# zZ!57bNo$otaesJyA~Rqc!v+3O%+b9Gz`H}fZ5j4ekGxt(CW1Z3oB|djWxoR@P~~?@ zKT6zc1<=Lu~mUdbMsbe&q{NIlT(fG@il@hs`Hx+dEU+|bpTooH3}EzUs4?6WQ)C{ z=@b6(pS{^JfR|l%aT73(*wS~Z*qmj=g0?`z;ecV!|;7z1Y062|ixIb%o=twC}U8 z5SA($)Y=f1kJ3TD9BkWnc&L%~-EZP6M{759nFINba5o5Sw;Oh~F1-1v;swPI&25KG z(pwW7`~y)E7Qh48$m)LfHS=WWQQLcYJ&9&`mGbL5zQ(?wSGThJm;6O@!!9+-egjoQ znc^ffr+L=Tmvf%;bi;3l8LmP94i142>Rtq$$Qa5JTuHazy+mT#&Za(9-M)rSuyx<| zL)~+Ts66~zFcl#+^ZQ3eD9&FS25MR z6SU#2(-7>f}i&==| zsOu2{xkA7O!EM8pO+~>0Uv0iaY3ssL#byZkj6An7)y~9Km3c1Z;2pUv92~SQ8ud@i z;xn&E3MUeEU1;gFt|D%Y;+_o1Ic0o?xht_8`w{crR0r#ITny z&<;-x??*0FYdo-T2euq1R(hhB|Bk3Gp>SmWX=(@Kq>TYDo%@`SG3yazGJ6VP4jymC zyhpTu-`@m(Gcz^|nEzM%Dr9kVp6tzdAGlV2?m<2@9ngl=QOV%^p8M#FMkSO|2q}+|h)lC0l>q4xIf*KmsfI zDsD-{$J>9vfp9D;lmzwJyhTyr%iSnZ`6W%_;&$inshqLk^-ApP}(pY&PI1Gd^H`z-^- zSmYD(!P3D=MZXrLTZ~*~86h5jeH`tI6TGV#uBdwz^$YRCd>#?KpJR-v+&{aZjm)FX z`z62lCozU;9`DQMwG{8~O2X}j)20oW&j+|LZO7_vYP2tZepnBI#Lgxrw68U*q5sl9 zCU_-%ZMp`fUGEK@#~j_|1XXz*+SoSAkgBDWKk7uuBcgAb8?$+ZfPz|hay_9ARa*W5*<#pn^<+t&{X?uthF+;-KHJ_ENb)*14ZryuUW z&L#2Pv_hfW?iEh9Nz2E}aj=r%frNtzrI}}lQe*6kq@ro^%~5)b>(wjTV=7YrK7mDv6Ub|wpxL+{QK&lkwf zgfb(6!a6l>WHiqI=7E zMzF(|-NPgOi-QI38gyhOFJPw>x!~}$Vwfwnd~0-E{vbvP@wUG0rM5CU9dvBzUEK*g z%RCuUlH1gq3O8Y?9W(GlYT(RPV1tXnWClChd>Y~*y@ivcSToCfzBON~_$YiwFmL>D zWXFM~Ldlpk$|#>^0T<2=o`cDpO&vGGpg2X{q2-6sY~V)Y>vc8Ix06!$p59o8{N3(ECps>J&H>i6}uV;^{-K*>ayheN* z50jXzzmGXejSDnFiTWxGwz|Kp!}r+ngcRqWM>`V>X`Hr~tpQcO^aIlSfBntshx|bucn)oyr$NT9|}00;79xWU`Rf}aYNv`wG=aK zKt%;lKkG|3_9K34Cgs(VCb3O5XRJe|fbX}Bfvu5q1*>umN`U390?SgdJepkt*L`4! zb=@H0u-B83i;xtKMw$G3l{dkwJ5BvP^RM64@>^E3(Qd{06_9x(@4Csh+m$d+D_eks`V{hi zlJ3Wa8xcahfv<8g@uiJL&Uv3`YeBxQ?w+~3|LOEO4Nlh0mFz4eR+C<$ z(^kEg473i6TpMA-UF1PG7&k79KRCcyk?~d*g4S(|L+i;}0NNF28PS8#ZXlyHu!Wjd zwBQ5?%^!`Z#8u!i@KP_{*)dhGZw&{UrBw~j*A2@zI9jCZ(Ze(@I=AWu5%!Yc`OSUE z)ymDQt>+m@A)n?h@6p2;w`7#91Det;w54d6eG}w=A%~4;ZC9RW5tuc9u4{3S37uRj z%w!3<>_cIpx0DhlRGs0_9-Yq$laq$)jOq-^m199qcXiH#^CIX!K)YU94-P3y{aPV#=m+ zyHyK}WQ6lNg5EvxQ-v5qC;7H0xE4$up~yMnIbyU)a#}lTHy7L2K4THGb~*Yi&bLc`u$K3HwM^T$Y+HW`>i)p{D`^OmXRzbv`Xi7!jBG;c%&gQ37>|RLP>J$c8Vha% zGF3l7$F6#K)HFe4C6Wyz$iKI&Gt}a#M#?7U%&AOJxYV!I2eHd)Qab{UEr@@CcrClA z_aj4nqyEe#A_YGwJSwd6ugVOS5lYotME+PSF!UbW68Ag}v7)7h{^A@8ot?Z1dguL~ zk>%UXJ+nQtcAdMMkexP{hM%95!hCca$PBn@TRobF zJN4{$$S-6&XT&56GFIvA@&0OLJk{}`3UjirVCE0~Z*umhvh|#X4_EOf1d*($wf&my zrPxEBv$k!C_$%u)?P1~@uKVgGaCXpr$B5*grmXeVsjcA&JBagsq1%G~v5p zY+c#&#QBut)T+wviOYZtaj0MAWw)4^P7ACuIkn8Y(L3-UWy;%257Iu4qcN?VAph+? za3mymIOhp7%-4c5d&^MIJeEn(-E|y^7i)dT+9jqPX;kK$jp@(fAn&x{TpCR+>*#JP zaPy@bbz45f$W>UklVI4U%7^T-fsNmFKNbxUBpdEaEw75QK!jnWw&8hUbd z=DsyD%{#l`;VMglkae5=5b>f-Gs$q zak*b+G;9v&jCvamX^hy_YBPd?G!{S0&0LE*l z>0$?aXZU|~q+-DCUT2M4sCk*L7I#!YS<@U5bHisV>+~%&PfyPgw|JiJih;K2j9}|4^3DU@q@%YHqQ{=hSh>bx&x_*o`Qu>EbpgpxPf59cd+iC57ne@Ob86qiM z)<~h*G=wPiQ_!p*_yo|iZZRaorul~$aF+S*dN;%l9=2^P*Av@Pz{NP5p}yxa&QrM* z>2?WC3xyA$@4%kd+ER1f*~>Ue`i`r+M%@9ddsE9}`_$)6wom_UKq^`U;`AQEgWWsC zq^t*Bff7V36((x$l?`Zb#;idLdtmAVXN2T!vMhwrhR7yoX&_Yw2emBOF@Xjs1r3Yh zg%EZoP!yW2c*THRIXJSUw$Uji2T9pw*FOrx>YI1H2-GAPd%LFB`=$$(*~APt3f8nc z797h3GtbzGuzR7MMsE}NLRf}l;{hE; z`rSme*V>x9e<8nByu~nJ!$;`jYLGW)Y z6B@e2RUx;wzZ1)M8`wwJ*vZ!eN865Je)0dL>nc8ho(2>0^31Rh*jlBn2rUOyX(n!N z*5_6t4s#Bsi>RC+F%NZ_^A(466q3!%LhbcncgV72b#fiVzuAk887&}B$Oa`ZD9$}B zLB4bqDQeO1xeTo2_3_oXajv-MF0R8!{Na$)s0a$?#mA&9YuzS@!9+P!^8TTWr$ zh|R)%_Bi6!$JmB>$zZ_GPAlAnZv+y%@C&*!;YRG~r%Nv2>?&MmrAkkevucRrY&f_K zK~ecpJr_i{xr%wQ#)}77(=Udkug^J%>^2QcO%dv=S)kZSi@*f8OgFKSTa8oR51D^b z56@PGd~VDeqmNAQ?J(mC?c45n9Ld82UMT-#F209j%^sgc;}+^Tt`t_WUD4)4#VfQm z!zO1bbQoag}c$ zjIDQS|Ln~mRsUUDzM&`&0m=)j3mdo5S?g_HPL2+8VmFNrp^h8nL*xqC^dkt*!swe=n-RKs$=#dtj;-t|De+r-5gy-SUM0>B zYeci25dl%!H*Xjn0aiEgfBKU-XGUxn2eWG~c&gqevu+tI8=kI`< zc(+%tX5Rz+!E+7HoREkW0g*SS=K441w?>2;?T~dRA=g8ymQ`8k&6>r8C#nUU;k(U` zYni|l=OWU4|D#NWzrpO7tp>P_p*f?imj@Iq;iDYic@ZHx&%jE@&1KD4$h# z`WQ8zx|ZVPwXbB0p?*p&!wrPcvMv{c)@$i->2qNBkPFl&X)**dpI@J*z?fbIz#b^v z4UhzF28@?2!+g`&9dED1ZC!OtQ+hk;a4+avaA$lkp>3n-&O(!9Ku-@`P4BjI+Rn|+ z5MKE^cSO?Lh)|sef`!ImXV(8{*v~7Cz3WpJ{3E9K3GE4C@pYBff@HFgT)*b47L3X8 zkOFQBUW54v(;J-wMpu^$nSF5$Pu~CE@Q_seK0%fO-weKzoSQxYDh^a1{$KHZsm1Np zvDxjR?XtIf{_Plv)x!bn$?#h-nzU=v0|QSDTUn~r!A+yCYff=7=0BpB&LejS@A5=i z_W6Q$7qs>FzBu#~_;S+Z1Lr-b*8j>Vs}jfNr~zH=0iyR~xPJV{2BasZH_F--`meKJ z;1+$tLb_`SWij2YAXYUqer~KyvFYlD4q)#T&dXgnXcZfgK(MwADP4~qGXr0ps4--I zjh=Nx4+!>5)<{NGd!epnymG{Z6S5!2izIuCYR&moUd`*&&VFcGL?iJm0f^x-=o*`Y zVDmm{t{al198XD{i(0Pag+7=HoGkHWL%c4^TAUL5e(8!%%4~)q7(czE_vee=w+FYc zwChCPy&v^KH1fu6C0P*Z*M+Z2O3yFd@3?gXyWe(R3FPipI3s;gZuAf`hgLaUUAkho z;%n}H9`R<66p`m&JIo}y+f9A}zjFP^I{WlG`0LoDYm%)@=S!pXqL5HVPTIhmtC%9$ zXc?hy{M_)?zVLH$`qFBgeVfdp*sp#ERWY(Qee1t@daU(_FZeg~OHzo~u>xOluQ=WN zq&S^X%%hCEM#0w!|0AdT=uk1^oV3m*)iNChd7Vcq2M)l7mTnN6Vck#KPoSd5z74>f z2uiPLvGF4gx53{KCCNTUiW&K55j(4t8pXS!c#eSte%I1?;`!#Av*+Sdc=E0@IX{+W zo^0OvxU)s1N$n9fA~^fn&>;6N%kW3+YrR7={|fZen)Mv{D!RuFEr`1d-r)h;3Jj}l zF|2UjO1-AX5n>x5-@q#eQ}3#uV%_>Y*0;)Y(WK6%;?Crwc!YBOdcn+4Br-9+-A^85 zHdtTjek52TzEoKXuxS>e92`4cvzkwJXQdeo;GFQrMZR9ua8h}3hC1?3CtO480_*46 zJ=V*m=#jWC-(uwAI-}p~+jh?0eTlfeBxiUn7wNaoqCeijvw*@XX{TF!%Y@$|&AdOq z1?=2v*9wxC_}BS-Nwkm#kR^&!tux@GgK&Id!wQub>M1#ESVBgly7tcuoOv5kCAnZ> zS3#btrrwandXw?P7}T3k{$K+w_~(oXV#uT|y}HPjV2Y59?E=oBpvj{!3kLbzc4BT3 zGJr^>xtR`qP7F2uP7Hc6d{OYl(|}w~bf&DFX7yM`PQlUwOW76>?R?)ShUR*93bC{Z z5k$(04|Kw}YXdw;a=!m2ERl5PiQuvcefB8@&>+$jO%GtXT;1X2;lR4Wb>{RBikT`% zKL}F^zZ_#}{Z=mHgB%wd9VAg13^RnBmM7?BC%e+Al|Y5>PR1+41Nv7BQ%Yp|?5c+m zn*Y6hq{sm+9|0YuoSekr0;7g6n**oY-k6`g;v8;^NWLg&Iqn`-cF|m~k(#!BGXvUn zzO-Xlo;GRK#l90?Bg6AU1x3QGX5oapP)fB-}uPig7mEM%?q^F@|Cp$)$@ z)5_djHqv`B%AY1Rw8!jeRev`uL(N&^K`BkosA7hWnbAe~q8S5bg^v>X-?vAxKLkTN zAAnVzLw@g0>VK+k8@aL4dU0|JzJ+L-b=;n1{?AKhS{#~-wl2|>w=`6>rr0c&1I*&u zhIX}^QE&U7H@_;^DjDAGH6ognYET+G`dEmRUyoK)a0{9>i8FC(85!`} zRw=uO$Qv-&Nwunb<)b-yGlH@(7jH4adr-l%h&~TfRU8iS5d-|$Y27KC51wuCvIRG} z=GMU9))|a=nu*gHZ+18SD^w?ssuH?`|IWDrW^|aRpZy5D0s{t};CFD2_~L$S-vafq zh3i7?&8$dk_r_|$r!e^@aa}SUwdMg&Mi?7v=muk_Szx<;fo$Ma@2>#SDCzVzAv*7bR~9-h4EBgU;&u9s3}UC;(P88t_X zz$pSaCru+fI|>?byhbNG5#7ttRBd&l^o9Fju&6%&()JgGGxfUOzlL;98PAvm&&*Fc zgYqyc*i)hZL86Qo+FZ)Uqzt@#-zq{&Ie>@_ylrwDN75d5mAl=*7$Q9o7j&m)6s z%9z-O35(~&;sk#vGE@mZR(rm)FoO9D zJPm_aI%nW-NVTWW4ZbSivlt%&4+dQ$E=dEgByEd^E`6=lX^-`j@?E@d-Ek_d7yHA;eQ#6n*N14sKxcU(!NHRDQcpEx&uQTe zo(xb(3tPmfALA$Z!=k^aGCu2^7r&YiFbo-t2fg}JhErczrI^1?BtEI*87w3 zuJXdn(A49I(TQ|%cf|%-&bI4lD&kh>6Jb`7r*2_T@mfSm{&p5{nQrT`RlH5?q}8|l zA@+b_Ho8KPxl5E}KS-Ma%V1e5sLJk4-aBqQ1Aul<(?yveO zN1@NCy&)*zIeZ z9}9&Sp7Xj1wsLZ@mJeo+%Gmd$%N*Y3?aFIdPd$r@8&fP=@HM8sCKk&-@QCOe^4vbN z5~gAasAZ|J$(T`9bR4KM@Ev@wzR?e{KB;FiGMOaSz}A~huD@DUoDhC<(tMI<8IfkH zH?_i^fa}nH#`$?fjV%?-Z3g8WH z&$}hqlMn5Q-|uEAY+7xkv6gx_WO@X)O5PG!73F-@K$Xx~`z0%NG5g*(Y{W*Xfe}?< zca}7CdZWJrN7*QuUiNF$E^4vsb*41-S(6POIsIGRvhY{rGBDFc4g7s9nvt>V-h9L< zQsZ)fyG5`fCm*{BEhyMrXQse9;CEfCa1>}4C#i8!lWI*FYyYqn>jt@QI zzo5PE-imhnVJ%#{#y3l=2c6@3Wi;(B3|3(DVQwKZiA zeT9o=tn?IxU$vP~YkrN+wp{ZUp0GIHkXbl)XYjFso7ezkFlx9N<=u1;Cc;KH%Nd4Z zxOIA?k5~Ol_<=zL7istv4F^Sw;4vVtxR{Xl*tq{M*f%JPeMo1H`?Ph7+*wHbN|u!| z23`e?iY7T#BH|P+-)g36cdk?iT>kTHjN~Or*Wv$(I491$^*2oS+31K~huOF-q{XX<_kL-E)S;|fS&@GgO&=`Ow_2_o92ALVN$Pm3!mgk3jDAYErkR(4 zcw_Z>>|EU!sqBj7iIB_WDb}p-j98?ESHZJFC$W%lupYGlFI9UnVCgi@dCq_kidTJe zTJ(6#H2Q1{9bV=vFt1k3>Gam`iNRhQ1omltvZ`v``E^MTDW9+_qKo|6@UC>@>cr4Z)CPgJF(KX@&Z2u2X(9GneJ)hs&0d14@H{D_{Np zlszzSG49P_kf0`}4UeWL+*Y!`2QQhsp8`FmcvlONV@Lgbe98WAOWEDo8*v3Md(QSo z<-)wn5R?jSVXiqQ6F{%_GPQ3(o|0OlI9olN9v}H17ye_)+qx) zqI{lzpUM55Jx^a}vo}86=VJa1L3aqZP9uvO4J`5~*It9P6usvY2=rYD#F@PNiR$;3 zrAT&1gf^uP)t2ep;SbV&p)*OAYtTEV;?P^ar1AUNS+{tjD-jKBC(i$jm#e8ewIf6I z#NhoAujRUq5qZbu#>~l_>yK%KUBPuF&1I5XVAUXk6=zwp>H(vb^ikJMeb!JS;3zNq8S;1FL;7Q zfVr>^Wt+R~n{H+-^X)yXFQc#DWb%+}yo( zTr&25eK@j=O&4=S|l_8s+Uu`u>t*@7B}nfib1$fh#%hO2Z*ax)R7ZkKDET zJ85EX9Z2U(+A%_UgSI~~ZyDMAH|vIFhbP-_#*Ih=Cyllz928i1M$YC6_pyww+y}Iz z1{E;3*4OBMXVSojZWv&5UBN^A05rUEb;=_{zNf)u_>(}$aQ9iBT?zY@GIS}TMQK8% z?&{7c!k_qGoQ&etiEb30wP^6`Ddq2L3dS~hze3^cv#WI)l*r9vmo%Co)??EBY6Hrs zlgwMi-)+uWrOvU`lN@(o+W_JFj&;32F~U!Lkq~Zw>8{ z*`UJ)Ee-5r98}_!%)2cvn^<;A15#_R_n8y4Gk9gww=S+TRcAgAM*zcMT5c+O!80G) z08P5^3-BwjGy0I-d!mnnyOea5QQ9dHNl)*v8(l4dCA?0DAdp;c(1L>CI?JxYzRAsN z_jf&qXj&;_W;*>tdu43!aG0A9Dbv``*(awtv`HRSYj{t_8=*G!1rZ}Ray~M+To8DH z(7e$7OOnA+ADy2g6N((4}#a4tcDqGw?6gIyR+Ms{Gur>zKeCw;P=)lN5u!~ zbRWJc%KdkUVYFl!ub}allbv2zw%^CG1_Jw3cT;Jm;DZ!Hlc;{*!Dt`OIfr%vE}pYf&2aLt|cOim4geK*@Wj<0;|rm?kCzq_t`=`a82P zC57T}T^|cC3Ye7NJL-dN4`zL{a~{h_#ZS8K&Bga<&K}-`FGQ~Sgl=EoG@AY9-F^9D z=+DudPIs2F5J7%OR<>NuELG)wGD%+1W~#}@wK$C+s-@mEpoO zt@aUtWO?}U%EFLMfBqF4appS+1BZ7yF*1ZF4sFn8kZwyL`?4$$B990C?TqB)iW!W2l5vD* zmCOxhGB08szXUyw{bV!@_@&4XWYK{Sq={ofLY}kJ{LD1tMJLLPOG~W92t?C11EqMq zsp4JiM1%x;Yf)#3-PNtyv2i3nucrxDwy609O}OZ6({zioc3Q%?vPHZ9$YK@vx@#}* zO|WEuND=exA~1l;BP0FH8k~-?%!fq1{+WD+ojDA%W=iSI2R!{(6R%%IW}<>nt{&_3 zZYI@kqDlsSMeV~*USxWGVN$j7&#_YVwu7UW7e%Agxc`umkN$8)eZuO%?nTy_eZ#$I9DDr*F80N2f zNr@i|5aaY--275Np0Td}nVPwL#4d7wGG$|Z8EkfI{}WVG{m7SYmh#Bs8zSC#HY6*i zkVY7oD+us!Bt1sv2a1ct&Flht{y4-}v~IfV*!^l4_=T zfIK0x%R@y){r^G%C}#fr69LqBJ&@wPjP9oOpZR|=12n&2@KxQZ>1M+S8Ls-!(ngYP z%Ca9f-TI!(SlqwhV zkssEdql!nOfnxNc=5|(Ta$T%kq8uB>8Vq)#9-LWq`IViZ!=C>`lR*Z&n=W+H)i#ok zju$-9(nk0+Y4FjV4&j-;Nex)E^}n(!mB#nNL4Ao5STBrj@*qQVK1K< zsb)IbhPp=81H7tH&p9Ij1L^b!29ObBWP4M;KE+FZkQ06r9;%n-7Gpj0myrXG=uKfN7lT$>6lhP_q{u8d^62j*_f;r^PSR73GLm#=kS|2!lM*}e`g?eYYrG|?FwDJ<+8Ozlhqz*^4-~U46N~?&$c=ON=R7PC-f==ZJlANd z{y5OiW?k=lu(%*V>$E&LOPewRS@FMuW4iI$RnzF`t_ofdw{=L5h_a;pSpmbr8lbct ztU2!kcZi^AcZr#9)Ru-z=1xnvIu1Nq4c%1-@lKoUeILcXoRtKekH^?Rw@9@=>;Kxi zN*AcSeulalNX&%2CjE=f*S#BGe$dC!`D8pxHPHKq@A0-WWcAg zFXH#5zD+Q@(ia*_M~h?`M6j+VdIZIsd{ z^Pf{@z3+nApEv!|0WY0590&S)To+1CCeJHigv_EObyYq0yet_qv%{&g1-9+hkI%e^`N6Vx6n+mu>HD(fJ#i#(UW| z#?Cq_(@sB%T56Ur>OEQCk4PU~k(sUy=&D-T zxTkX6WLFN(ScIi-XEH8c4zf3nvs}kp=GO))_gpamkrYvLjZV63k;xV#lKG|PDXqd0 zU<8nGB19uF#;g)ru7t8*<2=yv-|p1zmWwHyayblHc|=GbgTU^^mTDmNxVv0rji}Z8 zFoNpL*UKV3+66J2M_aFf6NzapMX7yx5S@sPsy0K;XCt4f&At{<4CwNEaO*^NJWY=B zZSz`{TNu0B#Mk@X|LW7oF-8gys~G6_QKron5>_1lx1l{Jg*5yulDVOnT9h*_mDh7M z!ec2tXm#oAwhQkf>3^$tV>Cg@PJayQpk?6r<v1@OBO*C>apEe(G9s`OS@Y<9m zW+*(G$l*C{q7bZxmo{#693*IB-dHb6<}lzV)FvLVo=She7g>8K;9}mar?<^WK=;m| zNd{$i=8?3>s(r`@>Sg<6UdbZIU5_UT9UY(y5592M2)>W~HhwzZxO;}snoi*mbbgay zhc`_ezob2#0N<>1-%MPS@qDy=!@_7ShV zqS!sQEk!zteU5UUNY}Il?Mt4lgwu+rPjCSN_l>WD9MCzwfrONqF`KKw)Qg7V_}Rwc zGeD#GZ4W^N4EEsiN9}jA8CTRuMdMK<^EV*#Tb_BjW&>u$c1?i`i8Lf{OuM3;<7UMl^$Yym>46 zORHsD@2@wf=_hvlM9qsxJ%{b{mC*)OkH)LqA`VC0Yk$Zaxo>O0CSBj; z$imQltkWf^M*EGc*c63Ve41tGwH;L719A@xA{SV52YT#w5|9rwmSYp6FfYsa&UIPO z({>u}vzD)xIS0h-To&$V9y%Oqv6Y|lp0uDhSMWF;f7a)8>_B~rk8yAu9u`QMIZH|m z*lNVNZybGd&G#{9#*ZQI?#|B;_yZbH=`=x(7gBh%@kPl5>+sE>eGdH^+^cyAsxC5gzam6l3fatL+vK)wj)v zmK}Frs+jB!7Sc99gFf#XQfA*Q6-XtI(Vx|fB;tJPiffDlf4cuy2SDB+jgavxvv3yP zV4v4AYkWXR>Aq)8|yu zpT1ffQw7UojNNZ>?}lbO!B8u}&&xe3zQ#+dUJ~MWosUlSettF{cP6(p;3YS`luBb4 zYX`#rDx>#aJQ)}FL^Kuqp>o&4O#{30+&q`DSsYWACgxLsa3{lmnNF!6y9h(Mb@6b~ z{2$ijO!M_DDhL2=-g!+}k;Bh^B_w%mP03Q;w4KzB4m>dXhc>Hz@;uXERu{dEZhf>} zx_t}`aJ)8<=zbfxM8hx)^0vLr7g=lehTAs4&XApxg84Kw`3sMnZ*&R`ysy|XRd|~q^qccKgLm5hY*O4C$B&Bw4$qAyKv9;^<3L)oCG+Y%hiq#lP6z@UqvGz#^x;_qNL$o)*0MF$+2( zrfP2R{D!$W@jFlfyMVFRZfIh!Jzel`{#f?F>dn>cWb5eA7PVJ!X)zN_Rz$x{^H&G4 z^Q+TE&9>DFhK>paih06oTK}Qm`yXsfM}wyFRQ&<}U~nqzea@qezeHXeQad>sKkTNc zwwk@3>-;GgzTm3qJY5p3mV}?&1`Cc<<9P&Zld%yZkLd1PXz%b{@t?GYl%-W^)ax{D z^DmPPuiVd(EP+bRpRtKO;|RdDEQs@^^C2xeuM5C$NzQE#0lV#Aye$ zVDw&!$_-$1u<>&Wp}As@hk3H{6?-B%YYV@Sdh>sR`~-$HK*2Kp!!!geV=9qXb)$@$ zo_4dx+&9?WUK`1M7F4z9t9w=Zs^{s@|E({nM3%T1pIzGICdwQ|mZA)!thG3+QI7)E z2q*e1^sG@$PHz-X?M@Dh3XaIYP0K&n9klZCjL=7-%I*x3Yhks-dnuZgL_KVU#qRTW zVkj}ga2|?#k6}?2U8Cb!Ol|l`(eh+=IU$F7w2}2aRNT=Po62vE!{&y^W#)_*pXeW1zJvfnY#>kFnm)1X3|N&t zWpeb9&!%>@u&vEEqyN@*T91S$8!gy=loH1%Dtf4b(;3!%+hQ&PbP?2y>C@pX$wRfsPcsGK-V=n2X&E|h)b(%@Om(cdAi#1!)!f%~ z`-QQawbQFdvc%l{{~gZWi6xF*+DiKc6&(feqvmd9VC(l6U({Q;DgtIwW$#D*UDqjI za2e~)p0HROap~iG@)-MvlCR4Fbe?S>k>0Xj2rX#z(!?Hg6<_w%G15o?_IP=PI&grC zUuN$#&i93TJA~Gg=mu{0IAt#Pv}NA`o~Oqhr!*1Hsb<(^1>&pdwZwE8jHhyUv1#X=w9Y6 z{wBP2Lp0)lE)UhU5*`9dccn7ELG(GB`4elc%#RX*`<{-T znfcd}{RH(fG>qF|5UVY0Tyj*IJ`k|kVLz`En2l?w|F)D4TiWf(;T8y<+8nan@rbRV z3C|8EGcULrm<#F7{G1OlYA1^VhaJ&}_!5wbx^|gbZSjRSmK^i#eE>^21e;-HDrza| zcouAkR>n3>ZOhsT-D+CeM#0}?Bw>rN{c+5MesY4c^1cIi;BY1-%)J=BRoxsECF2I; z#PFTfg6>zrlG^-W7rTYTL;UYch>gtki|KGv}!j zO$F7{TkqNPmh2q2>(cv5_nIj9HL<4pnX*t%_}1OV?7AbGCBw}_4XKK{%*1_zDsHPK z;r-&^p4h>+Y*PM;aVG41hdy<$D6|Imss3e# z%;f#aX2ri(NVmTlOkLi8<>;YOl74S|r}9v{peI*3FXGp60ADc~d1?87uE%K2+oh79 z#Fdec2bPgiyJ6u1TIV=PdX{ycd$uEG=KP%!07M zZ08`~lvT8|F0O;@?}%)SR4W)Z_*`ITqKaDF!cRhE{9RRvLp_?A#cXrb=BQqW_(RVc zC8OEa+QvO!%lWJI8D9j9K(4(~$I!~#HPwR1Ff(&O=+BjD1tpgxgH(FzPGSWun}~(8oXKt(u>);w0}*GPT2UP;&kh9~pH$eLBi)l} zO2i$BW=g*(zdVOmHJF%xJ0t1LUon~CLJ-0tx?`C zlGGUr42ZT+U-}U1-*#m6lq6MEL|s#lmIiy*~^3E*K*G#r7J2sQ`!O0l|S>8_|&6Tg_i!XCvQHwF7w?) ze{@$yfVd|Wx>dr%OHEymCdOflhT5eJHnMiibVHos2mF+9TM?Ms_FcuY`cZmS!~g>O zBK0?^xU$@u9a_#~#QUS3fF+H>9xYn!*jK0l73YK5w^uwdm+fyy zmE3h+sh?tm2|Z*R5EC}K9TPQT;=G^C99ib?j%$$r1kHSPv6xseSkqpt96g7+XC##+ zFl3c;E##khz} z>;NA%l)u4+$pyeSBYJ%Hs2Ru=I62}H7Ft;q@E*}ZLyq3wjoXCSX3T?iZr%~=Dl8NdDkU8Ng+ZSAAXg`iFXI-;Lo(+MVsQLY429vhin z-*dBXwneBitUQW8UD)yf=A4;Q)%4xxL}lLZ)Qx;WZu4!{*5V<Oql|fnp{+YldtHGP8R&!<(|Ma{fx6f1@-?f#$ zp)Z$wT3uQJ>My16Ug|{Xe=tDlzW^8^A1}W?`sd)1Qrxsy_w~1CtT-Pdum)hBm-0|| z4KMFgLXq080{^AY%{VC5gP~wk_gaNF(k&E83y^B?8 z=guljiF%!c3zM@)KCL*-wrG!=8W?%nLyWgxlZ~CqiQL{+5y(|px$Q*B87qXz(d@r| z68eSgtK0>YP3iGLgsb<3jcBldG8>8UxQCIox3gNKPh=bHQ*yKO33IPcc`wS6s1!K)ssxjvDnlrV#HG--O4>%Q_=&sz^>dA z!|`!R>QNzWPg(E`PoLNqe8IBDrPj>zF7#f44q~|f=eENj#~Dn`enj(8fGpa*H}h_) z6~Hw`glZ17)+)I+6xBsT+d#rmI%=?guKnkF%;yAh{s(EP54*4v41i+0!4v=bxQiM` zB_b8w?Fpw*A8{sD*W?8-)9LrCR^>~i7>Nm=*$UXOCWU<1%=dnDof*0vUgYq_2Z0wt zmdG!B%qh=aIVt->_W>}y{T1R~=D%o(rvwHrlM!z2^Nd#G_uls!ThwySESJ;!dwqUE z*@l>&9XU3tBr8f1k7(-iu<9+Ji)RSt7W%G3SxJrRU9gF+ybV1;YFd`vu4P;Qf_lel zGm)vyQ3A&i> zx{Fy9LZgzFtZc%ll`|DPqX|D(mkQ8bn%>I*@7_%zhtNN4TKQj11t^=g|8(6^C4NV^ zx17G}YPoygM>xC-*P3cng85L-&&OaooKni25(x`Tl7tw`{7u!zIlUG)Ij6=FRJr3OP<8t-~_N% zwp`%5PK~!g&8(Kn!J=!{oIX+BBvg_m)40KRrh7lTL~hWF{&&#*>*htB@poZL)PJhD zB^f>f8Z3Mz*)11@#YD@FP6@n8dL9Fs!HoF8wjr5djEHt3U(A z7H-LC5hHA>sD=&i!70(yz0K8A%A(5E%KZ29w)mUbrvItfdajMv#TLaAZ&ExB@K1`l z7{Wt{F=E{P1Rt2y72@S0?XuQgY`SmfLdahLf0~S-$u((&%5mQPnfFo7=;zfp@n$%s zJB!UDmxiq=0OBzs_K~R2g%EaGm&SG`pTSvLoM-znx3qMEr0b9Oe0E?j{H9bZvfkz2 zHV8laW5gwzNM!C!TM;BcEg3EE)(X-sH1hkD!~nk@>P|<&1qmu54Mcz2F2ihn4ZkA) zR>L60Zk4Kq-d@Lpw6w~W&E~Cxh&9NJE{E+xDav?7Yai9u1j#})x5o5jsYMf+X-~yo z*Lej4{6FSD-S3pXuo5-p=C(XSiGCnv+8KpbG>Yol5 zNZVisXTPKdj%Hf25tbrZ)8lrPwGQ8_-C2Wg6vAC1#5TSLEr{o3qQQFaFm9_yWuwP7 z!jM3G!TcRqQuQP`lRk(}&Cx2W3C**LFN42etHX{+&NL`TDRUlte>ZN%awK0VePdY{ zzL8H!S4O>qvbsM%KZVdl_9;kzOnz9F#M@)OKx8;4OCv`5FGh4of3?VLRHPPaw}s|i zY?#F=ydiCRh&Ba4jjhPy>^-KcoLE3?ZFDB@uKTHB7h>diVzZ6Vo(ea$EPQoA79@=t zbjZ*EEN&kkr;}6gl(e9>lv&t-ppiv=4YE8vtGTZy>?`bTz{s+I@6&p>&w4-eIq+Hg zeld?r3>k`uD<_}Tmf`-&MptFJ`vxbogH>uKHrQ8ZI#bPW91&Gecqn!+wPbjEFA|@z zGg`N+RZPwj5#&B)mgvj0hncS8AP|kT?9vhJmZrlVby;x70(2gY!)u}mH7appK7zxu z%`+JTr-cDwG3NdY;{ofIGDtVkAMCs2)8rZ*6?Fygf+jd zi+&3e?bZ`P_JNq=HW@?46KhY`>i<5T zn(MOZ>wU}BEa?I=PuT>Ojz4N1jgD9yWR(5WSZyP(g)f~8mdL=$fI>K!>{e>lTW5pT z)66$TcHNCyxSJ7qlLy$J7ETX}<#c2h#7#k1CK}%-9}-6Qw8*GLYm^WCEH&$I-Ly+h zKS~lR7BMLMr(k`1Sa~NSn_cUIdcn*}7POj9oj(N@vTTyFuki96Fuz!Lr0i^|w9p|2 z^Oe3qTKjuiTG?y64#;Q8MZK|F$E~+@P!eX=qBq9R0R*+?`JZs&$^3>3w zei0nORIw^&iv$k$oNSn%ZibI3tk|vUDDNuN?D4Nmox`d*{nSrS5~6Jb^}3y&Y&oe? z$x~mnQ*Kjouo!&9{$2=A>sK6fG;l=Lf$DUul81I1jaAcscd7bfE@IAOFH{F6x(BZB zWffzVP0H=sg=dE9xl`zs%|aU`Q}zf`Z-wXX^)eOvKi7NK+P?&{!bi6}2|8L5 zzxmqkUL-fQlNir$V~L zKx!Evh^c(PqB(BJHPmF4b#~Y+>D%n6W6sgwCVFp}u9@Xfj(gc(+htRlSLPSo?k2cJ zcE^?g2*;A0w}BxUws`<(hueRnCH%V)hxh1!Ova?b04jC61FY`YVoFs##uNMWY_JrC zDa(hn1Dk&KoE`>(juXomeHelkM=Xgp*l!Qnnwfi2z13eFb2^te+Fsph)_iR0BvTyz zcJet}$Ial8YSNG_G;85t2hBr3q(IU^!;mz#tRE!5bK2CyBI2{%=!;<{uKyC+4D>5_ zwZVQxEnEfc4uWyM{BAZsqW2*D=H`rIMO*iulYOlE3LBtVokC6p@Pbzd6!XuO^RuZ5 z`Q108a?PWP{~xEG^|4pM?ND9C=wVtNrhNBeM`X3c&NJ{L_xdECC~6kbUbK{0p-b`V1h#XZXxV5C%x9?S0vWaviAH`Vv7TwBrgkryLeWnfp z^CfR5zr&|t{;FWlr0$Shc+W6>1tW;ic9xLO{V?p&Qc5WES%EiJuyM+xC`6}Gq1q3yMEuk@7GV*6dYG7hbqj?L9r;$t- zil0A9!X6?Ij7#&z#=%!01^_E{_X)_8J|htx1nt4=&vrPZP@JZBCAoAYSD> z1(TpMI;STrywrxqD2SZIrfPq+yPc@y&+d6`04g(@-(73%vK~Cx^Q7hm>2G_PA@+A{ zKtr7=YNptq6!uaQ{$$aS1`8Ej6;L0|TK*VXX**!f6@Z;I${s$92tFyv{cj;0I!5^b z`tA~I;mc6o7@&C(& z>n+~Y2+vs*uRP2+V}zj^dI0DZBfd z#Zs#;bdMO7NW5dXoxopU-G{a|+by0&n#vKkzxSNP2HXoj0)V+@)JAQ#$r$KPl}}x_ zzaCx)oeha1kKvyycRF^<9M@n!Nsy{*;$z@)A?sZM=O}4HJ>uowgD-YJ4~5P$-;p=uNU7o47^9(FvD|}eHsp86KeJB;>qlPk zKlO)F|1>D_eHS$N)ex+7_nR=;CBMc-u9Ng<-rE@-exz>*=Ofwih zj3v=`)*5EVn3Y_;-(^|#9&441C$R@glVVLhoj?)ER(4^1v(xTq5rW-#6mCi)OL4+V z<3^wwvW@Z6{D(9nCn;{NXr zdtv#1Ag7AEfp?>WpUNmfJAjMU5Y?Si;4{_g^5^UyP=52?AssoD7@gtZq!vm}aF_C- zu;vhqB;;!*^IS&E(j<2`KzdMWsV)hgin*|9gEdrRS!O2$^fzyQa%sJRZY;}OGI;WU z6=fT#@O3P$s&VV5&EQLUDSq?&_!O=4yhgnjK2jiK4Zf?g?`{|7O}cEeZbp`|ca3R9zIhfEx6iO<^Z4%I4Z-l3j4|GWg#QeHZak-(nGr1$M<7 zcJx)aQOHHt47@7i`|SGhrZ|<0&{-$e6G^Qcga`QHy6et&<=~~_`?Befp_R~}$#k}4 zAPJ{c7P7fmETMN-)!xTGO&(??G;`1i3C8QTM~x{b)TV?DH2FAXd=4sgnGYDbSUnUn zz4JHv>FQWXy*}+P%4*w}AI>z15Q$iO*S~@Nf)zs?pj^Fe>OPAnU?St=8j8>hcV1#H>Iiz zMcHqVElHv}FG$FHC|{=JK9}}D)zovY2(kfr9O>O(@%(GY)a6Ga6G@3Q-B1^iXw{E8|YqH^ASx*3nP1>6b(wCdPKPC4Z;QKYCoTcl$;fFa0ez8x@u`%$bLVXf={+ob8e-bAlaJO5675}Euq#?D#$yAxo)bA3@j zdb*c~u7BinW8ZokKTnN(h0uCZ*RZbVxA??K=V>QRFK%Q%d~$VQS)VWCa_ZBRK+Sow z{r115*xD*WAjsorJ;~gQ)|`2Ix?3A@+D*0kU{Zq=vyC1%YN*{FQ`0UpznkG}Np4N} zvIizAx<*bM@A~E#^d?P zGv5|+)=}fgEvW6X(jWsTtJT)UBJO^=3g7LUBlLZjj z8Ve1Tr#~i;f?b)I$LE2v(K;T(WK-T4n zm9=FUYOv;7c@pm}Rkson^JDE&A8tnsz4M4E!!RTsF{;?j-pVBZMn6CZxM@RxF1w0Q z9R{Ut;|_VSo`fI$YJ}q zx_xJ#VA%9|6tG9cc8IL#-)qCwp`6-Qap`cUhA+#GzbXUe*$u@SRMFr|V1w=8^$9E8 z%~hDk^|kV){fEBALf*7+t1kQbbSBCoKuV?b5Fns5DJ#ARr)-&{_9ftCged;6Cvy^P zw0&bHZBn}KVNuv-q0Wn3qqpM)lve?%M0wX{TH9XZ&_$)`4Bk29()vd=Y4A^fOstrg zvTJ7b*SIv8_^Kh%5%n;+@i9D3@AroMwo*^>#X+`u14vUPImaOn+P!qOy(`0bX&f~k z$#oYz5dKzKM&VmeV98pV{*fHdo|lLT=B>d@RCVa{7C)D(+9G9{HAdy{Wk2^+P)X~+ z*+Y_+MG@dMK|5A{i@ss3YsU9SK_6%ZtF;={_pl*58@kvI^B2A4)IUtxROE^c#%pw; zEH+Q3D1i5RJ%3HTD6_wle{7&Xl*ybgCrY1!O!N4z&wgP|hyQI}9a<=`T(JYju#n96 zHFM9=Z0$Mc&DpXM$?92Ow{JIE-OogaBvg6DjT1MDD_Dy^)+wPtZmq)cb~g#3z0Gw$ zNZqe=NQgFt_R(e93jE1Qb(6ix%c9GxBY^8_eL>TRti$9h69>hnS$UOfhkNOCnor>F zB)!ITpL7Y+ifMjO@Iz=)0L?HK5=BajhOa~`D6h#ne5JiD`YP8|#L#OF(lKQ0WdpGfeFs47j zS@e(QmsIFa-|o>3aM_23s7;;9I+v8QDPM8lP!e>LN3XKz-ue&6KjmfP5wmm7AC&OI z#Utskv(T@`iC2bvIbH_cvw90N_~OwY)w{6gGlA=eGA-tLdTjTN7H7O*e*nCY(Q>Q2 z8ck7Kk&p=5H{`uCidGBYE9=x(9K>GAq+g^F3%fOqSgsqqjS42^hSD4ab$dz$%MvnZoi zf10*qx2A3(y*ttR=;%-ZhCh;lnjL+!n+ zscB=-+N0*L(4-mY^l4gJ-=EeC=wFp8Lq6Ky4#utBNbicJ%)evptbbqj-b;F&d1`B3mvEBym;~Q-#H|$~r&axt zw%v`J(|ssYWJI^1f#K3P7AMoYOW(eWw8KU_4AA!l z(}$DK`gei_9z|m?KOU4sR{3dv!|+DB2d^TcZ4o!I9}$`Jx*XudNfYb#1!b?w4;^c` z8Xef3?W z&EbrywYE7;r?|RU#58JIn@pX^?OZ`V;hzWRtwy>|@0K7K?nkd0lZqfA5%5zKlFNPa zpMq+?EKynQZpbOe^}5B}h#JT6!WpU6OqlJ&A6<{KwToy2-XWdwz@J*ulW4-#@gf&X zf~dAp1b9M_!X23UZ^%D375tTa*cMln&RbADpW&ywWGtFMd1>Q*W|A4av5uT?d1}Kb ze3Gs4S!~v*nLYDG*V6w3o+FxuN@Bk-_EOuH@_}Y4i?wyz`5KS6xR+vs24+&@3yao2 zW!B%!A;P4KlI;9K9m}-Zc~O1K?yTE>(JJdn->rFuaL>BDwJb*EU5_;2Bv~w}f2`nF z6lYgfzVlIt1WtPYTt2ugpsnV&5$SeHR@(oznn#2~)$_1ACSX6v9(p7QDB^F6&;?k#kTYXq!*MO@^w5G>gmHHHe?O{sUsY|a;? zxLHUGlzrANP13u-`Br_qs1-kQE3}(+E#yK#+SW^apVi&wxE-{Dq4nM$eO=#1J*_zH zp`DM`?)TUUfh2xNvhQR>DfKrIgonOIPNMV5Pfq+-CRvs}vRtc_YMwKDVNh1w?`GUH z|LUzvlHnlMVWZGd0_l!PDoe8AOEv-NKxgtENR`@JVQ9YWcSMk!HmPnl+G&zL{U zI=^hP#e#s~1VLC_yfOMx!V`->-XJ)qC$iuP3J#x!p3<{B7Se>nduS?@-qTo%yDz-x zIRhJ1C{n8W1kZSufKq}&g^Vg+`Rc6in^tnK z6owRVl4A1Hjxz@OPqSR=M0vhMsZ$YZ^qAL4IBd<3y)ot<6Jb9-nf=9Pq566 zW+%CUfuG%;uwMqMloP5yE5y18`8Iir&uRyd(IDh~*=x$9+us5%(lRqSOIeh#2&83( zio)StSM$8yrLfAjud+w?OkN@Rn*@vNqluU9(&gW%#LOA(5o^6W@`Te4;8w(a5_!_ZI>vivF6^QnCo zSvT1Ezxv5uE_Ixtjbu)d2~hEFwtLA|57(gnEZ=+Tp7b}_K$k@jaFi~=e8Zm_Y^k3( zxw+n&0fYy7tg1M`dTKP=U)se0nhY!b`_bEn_KrfQBl9BBdc#5z{Kp<|M%#8InweYA z@6oK|ley1$?*P`WC5ZUJrGecB!`0ic~4@|8qjB)eCYV1_3>6jm` zZ9I-Xym3w8tYsLlpY!ZP_~ZNxsTH4~M|G6i8asKhacRK6Dx6O2MNk1q& zZ2v;Jtfj4mx#_&Ny)v)k(bt0u;h|T~{28@P9V?^q{_J>&f$1U4^ud#I|MdDm((K*! zL{f@^|*ri)@b) zZ&Auf3$1Q7bVvJ2V%#~D_@YX)-#{-k*O&#o}p&Xq-LLvxQP2PvvKl-x71J$8_DQ4SX)3VtlCcV{F_>n$vAl-*9_xYPcCTp48I`sw}ME)-u;OmH#}78 zjY}*Q^S2D_Ok9u4p08SvX~Lz+c#2gKjzDhWH>LoxidNzQ1ea56!R`YM=bFTaly!c` zRS4Hx4?+Ofc9S%?js=HX97kU=euP!ch+7`A%)@6IHaOnM9sO;`)+D9VtRpq%Y_T$D z{#*TE8VK4{wi_kZy_OM5X7y({LPh`0NQlT!?Z?l9V$K)?e%Vb4aI&N>JX_t0I~_o^ zGC$2;-^m%Pvt5y7Fbp|QW+Yib)SK)=;)l^Y;Xm$Rbw!h4w#mBLACq058noX=!BCOz zB^s9fJe`RD4C(cx^jwa^tsd+tp%%YAQ6WZ&MnODKC23Kr>FiowT7%WM)rvBd8n-uz zK`d?U3-W5u$yAjMe?C*6^(40OcL&Yqe(0~9IN`uwr5`0->rD`N?1H0@&3K-RiTqLg zdu9-{&mo%s$UBWHyqu|@k&{^(S&I%MZiD#OP(#SoWdt_e>iO%gzk6+-yD?xRf~hmQX?_v737Un1CEF`*S*NZ2agX$ zNA+olPIA&Qf=0${!)x4s^;)#)u*N^zquk?&Fys(DcKglDpnUUh9P(*B3H*cG_aszX zMN(-X6Bqk2VV$I}+rFjHzrFg76te4vZ=ck9h;T(sbX!alPvTgf9*Nx7Rc-Hj-RVSX zpOy?> zlM7-Q4wJ+4QEJ`$7;ENa<1qF7Y%sHPEq`H79>0?p(~!Ul=TsDjAR_r#^W2KYb(-hHYT&4SJNIk&#<0#Sn@fta~d55 zQra$-Is^4Xm10wCPE;S{@BzG@F6;C^ zR@}Sf56LEg-_^&(!!KMdGbBFy8QMm1Cg9uz9iEEPSX>M4nBhjv@bp<^@-?zyyzN&H#D$K)nY$+8ifS;bF zLuVxG)F=0KKr;}g9IK=Gj*p-ATlwkU&!HRL-S!u_fnDQ{8UG^=12Tg&byluE-3`M- z$r0ae5J-Z!Q{iq!YI5AbyE9c%@Q#tez&hqkc59!+#zh1 z+-XYi9?ThDt#z>4dTf+oeWSg1>t^a~L;!hBS|vxlL{f(b9UL#5jiHST%L`+o=2+OxL^P50|D- z56XPfI3)BKqn>l#`2n0J{j>??~T-p&2c zT;foR)Hf=2tuZ~N5lDy3OnH;3vGsasBlRC}fgytmSK*JM<>3$!_7tFTnoh(f&MvUjNQ@-N2!p+G@X<(?gj(zOeCJ z(cZkI6_DpLP2u_uimke4o3O1l&{}7raW)p-pOmuzIYe1>fr8sRxAXckWL5Oy=r~0@ z^t1tQ6FDa@^YN3K9fPu5)!esdMT-pK=}L zCF*?v&k=-N;w8Sq{C@I^)eN+|WK9pr%p`QDN-|mkve>zema78Yxu$Ov5==#7D@%!Q z#~T#x;&C@-4#Igo^l8|p98LZc;fP()Q|{aDsb)OWyu;3P}6~MkykobwkPvo?;9;QHGgG#`6Ixh-r_!rrF7KU0w{)J>!F4Ua{i%l}By~??c_ygP@{eb=8zM_*l zF+zLzX-B^`72k_)J)oDKpGX{1Hc?^9kr<~vy?>?7p(e59{^nS-{llS5NQqXFXxM2o ze1_{beBVfE(le=F%cp8S3Wz*Cb;-q&)kV;SGx zD~vC=oi*}b_5B~gmHid`bhs7>#5-PPrLxQZ{A`W}9Z(&TOxZ*!bMCS23W;zH&0nK& zNy^aIaitSrZH#HSGQX|r%%Ciw5-fVEt=$#;4?Xym|9<9b{*wqdd(a=mw@7-2f-qqk z2vm;4+!7iNwx_+xbbMiBo5ISUMZpCsZg9=&d)nJ6Ucs-)Rr$;sJ7v2D%%Tuh(omME zXJPLgC)4P@DqfsR{VEWq<8v;keB=mK`#WRZW82lIpiF7@v`xP%DA#c_)GTmd@j9(1eX9z=b|$<7LRxf#1{Dh)y5n{81RJL5 z*_>T)Yk4Zz6gY^#Srs))dB;d_Y(AYq`eGDQ+Lb&fQd6ZBxbdxE?R|madY%F7on04W zt-0_Ay_)}&*Y-&ib|%jG5k+E#1lUCz-oe zId1mVIQr`5R5q3~&(>!vbyG}=uBCWRw=~q|3U^afCRU6bhPI!sAE`O6EC8JH^v+zJ zE+o;2*Dh%!7+w%++5kxozqj2b`g54{OzKr#&*Q5h`SF;mb-(zO(aL}o$)G=l@p{nK z29X&sK^R9_92O4>{)JClD5?{26kP%fOy1CzgqRpbj{e2p19TwPzGEHa3(DpmNm!cy zjaZVkak)227>_5;&ZcQdp8=f6DwEHTV~5Wiba#Xtw5R=cyDzOmPXC?PdZsy}9`!&| z4iKs5NLiK$W)_oV!_V?yq5jo7Ywg9TG>3_csZ-&sC4MxV9bhicbVgdZo5MU4jGjw} zH`MvUOT#hD?>+u_3Hr=49wjUYyH?i3n7%a7z&|x$fM$A(=5`#!%E%uCyeQEV??K3W1!}dMAJk|S8DUzQezjZuTi1;{-bZBcL0kw@jmh~BbVz$dQ5x8KMRR} z8V3$7hIRu%cO!goJ^y-ZX|l&EwXsFnGW{AW(Uw0@9)LHOh-=P-zXfNM$ZYRIZSKYX zi`o2432g^))f zn0`YsalqtABadsp8Qs)f3ZxM2^-Hkci7cq_5~8+i0~DPL%{sr@s0zk=c@HdxVCA>S zBd>j~%X?Mo?l?NDi!E7yW!P_de686e3r3{7PvZx`!u!W8N1E8AjzK_9LB{E_w)=Yq zo28sIs}H3;`{bJPP>%&kpJTsg@<(vb{wF8YHUfVDBq0^2u2za#tU6A-21G1MF#Ms} zp{9wSds>XAkBzI~&v5U~3G4(`xRM9cuV~#v43J)k&w?p?f_rO^It-ZglgFe-9U9fN z*szmB$QNh{Oor>tq~>IR-}sJwu0T({llE%m z*=a(&Nszx!v$j%#S>-AZhqUUJ`x-Mn$oyL82KMU#wEwRe4ZlPy)s>mS6m&of5$MvwD@#C346xo8P%?Ku8$)N#Lp=#gL^_cOiFRg{p7S z{+Q@c*DN+Iuj8tZpY%~@*FBYzc%|gj=K46nqC7R*<(6PLodGC!2mm z^>c60Zf_aj@1aI$0I?6^N!|K$r=!Zay*bODTsqldrXHszU;I*aWtCN7npjN%K8k1d zeiTP&7b9`|l)>h6@s}wIwj|HN)bTemt0oH1_7;AY2^i>W2vil==3nkZaF20K`dz8F z{-oAPAp?NS{^J#2OHRVz^BY5b9Xp|%{(7w--ogY53jMlf+q{U>*ejVt5#s0fq(3Ur zF@Gg?3;-`6z)3Z|k)21mcDs9B(dkLYsr#?EnJL@JD`CB8nXMr(5F9HV-EPKs35%AA zJqTM=^C2`J&dty;nVr_X2V@t~HNFN+FR`c|38U})pWBr^m#Z0t&x>%Bkhg?`@-*gh>&i%3v=lD-2}ip)EGd_*;|ZiZEH!BpAVrnJ@gM>x4IZuMhOp zy?!2wtpMb${**{f7z`aQ4?Wd-4E%kk%4}6QxqL*HFVJ${KFZ2Wc8>Rq=&S%~ByRb` zg|Yvs9SB>K`EJai>fL%Bv3p$mKJ<9O4ik(Xu5$u6K#zoBLN9C{jr)N>LbNZIGB@T> zsLV2Q&D%xEUDxWI(wEBlU4K6>Oq3!<;D4bCuZ@uKtVrokACCsy9s|IKN{g3V) zjYzEdnz^}XZi|;%?W`XND9n%DV~Y9sfga@~fw}KtI>l)*xrQ~UY$H_{6ZAbrg;ZKx zmw45FNl&@1jQ>a;cdPHLyFNM2$hFjtxMaXaf62hQK|#%3yTZcu#{#RJr4>1rJE9-ZguFM354HwUJ5`hl8P~g>; zN3@p(%~KY`Z6l}lRzBvu)NseP@bEt+-A?X$67K#6xMuT`!8ZpB((|_|@Oq~_*H7dF zN)>UO;(}cIODdF}*KWZ)&cnbj_>bugq2D2&=*42l(M>?T70*uz)MJ2s#C+WTG^ng} z(kAQU6Q#Db8Zz}2=vF5o2tfJ|b&O>4;aTjns|(&!9kK672X(}6iY9ojqdCq6 zW$Qa@Y*yEI3({Ca`<4OEQZ+wX&-6{4TMXE9G>RA};O0bW9-VKjfpC|1Mu?!REYZ?w z>$YU}zXgrl*6+sNhph5Kx_K)bsp)Y(eomiw$Eg3(N3IZ>qp<*^Gd&$!;rhO(gq|iQ ze9=PgI&e;@3VIghpd7p`e8!WteOFl4oO5)cJj(3J?o_IPWX98t=dXD@(LUR%njkuPZWC z36;vye6E2qk*(BSz*St)J^_iukYpNcqJ;2OobXIf%cT>-%PBTd18^-zp{+l^$>|Cqvp)E$oxhK;He{%@yN2JBFr8GWIHfwN0 z5aEN2hsj?+KakZDs%(GR_{?Z`n=g4(IQBzsi7_}8Vpn;T5+CFVk%XAJW-!j$ z{UrnbaF~-wqa9Z*@6qy|eCWNDzy8b71xh+%uusW{0E>_j9JK2@nKy+T@4vIxN!xE! zd9&WSPN)zvAd#kDMF0KnzwZ+?97J0F;Ti2*qFk@D_~cCAsBI?Q?rXRuf`@D*MdhMS z!Syz-iFH8w05__h^-R5KeR1^XnkDaa{}nIlX-3%_0HERjZgXQ+%yyisE%blu zaku}Le~^E+D_E)FzwgrCbXd(DnSH=PGX1L|tbZc^Gqlu-$oh%!b-RU$tTfR!vl5L( z=*T?8{Osxeo~1S^fYvB|K+z$eH2N>Br|UNAdJ8@~H-<%E5;}6gBcT6Ai^JkPzsjV$ zcQX8X&dCK=Enfz`5$h~^8q094Z9N^KM}9CKiKiQQv^&PeYz6vg-6J0}^2dr{GN=t~ zQiP(?lH3pZ{@a+i)Q5(RRmLf)M4tMT!)7D!9*AgKDO~XrTKr%c64Pt zUYAr@BM2O^wBSCW*UpW%$zg|J3^Sj4ds3b$YOj{e%w3f z!OnD>rDZ=^LKj(17;x&PWVd%#wmv!|d0`Y$K zmh!J{1D-6wKszli!fZ!C!9d1TEKPU#v=OXFhPZ=6lvG1yFYM_!x5%0R1L=c~??NX$tg5Y9;q<>CI^%qSAalKZ>X6Tn&(Y5!)iC=h#?70IBp`y_UbR;}!WDg`Y zWR~+%0B0z&$PtRJcMlu?fb|#`E+sj9h#-q7A=IZ;AcJu>sciDAB5#>L|H9!3)tQPXeibB&V-Y~3I3T;4-rF3I2|#c3gJO1neZOl`Us z!wa*KkgLDB_0v7jbM1KYsZ}Y31C;M%qSPB`4hFm=r`{ehC4!RtW+ob!*Nlhzy^zI+StXA+T`jqI#7k9650mU_(Si>!jO@zptKW1!ds2isj%=~ z6R%42y-+LGD|B<$#i0Ual+D!Np_9qbm(jq!?qWsO#O}LHmWGe1KEx;w(TMG06x3rA z_F8DKoGZASFC`6)>>snIpgXqZ|C2kxxJ}+M!HQ!>wyhAR603vY00K(;JH(4&1{^nl z=%vNTx8)q{>U+GG4UuO34UKKwxZB;vTf432n~nK#XSMf#jX{HWhNjh8|2fYX1Nb?p zJX`i}bYM@2AYjI2pt*ch2c@GW37e%GUaj3!vnZ|)EUflLd~w=)%`MHkaK-2D&^3~X{=JIoa!UzGqpLNWwV(Ol2fG|hN*;{mGk**iETNT!yLxuY%{Zs z&A$GD`-l6w?(6-&U(e_3@#xN9T2)dvq(eB{R{y&9!UnrA1Aln~K5iw&KLO}rJ}HLJ zR5d6y$tC^Dzw|O3xuDuQpN!Ra)CD}R3%(YO_y7#F45-Tp4Dq zNolN?0leiVD*yS{1xH{8tQpUDFPQez=PIcVUQ&M_s4il=w-1Tv>Y5tNH7_wx~gz^K*s2)dzBi*prVV ztaH?F3t~xL3R$Ax6h0Q77{O-k|K0tXDjAvVJ#(#b7@03Vl)*9xNZCyf{a;@9SxVJ8 zzw*7!y`urmYC7_VL?}PEm~+X^MAf3>tMg%8m$%q7^V~4f{#?KkO1$u`*cYq~#_jBN zbD2VzbGr75?f1ZypDiy-ztzRW4<1Bsl=E|V+MJab!saR`N~L=2+WuGli91uARZ0rj zOw;enUnsMHkc(;5J!D>(EM(p(TNyaUo&w`;Z9Vhtbble74tPi@Ww(t$8c}2L`xWs; z#;_xDb@FK2+=KYfs%_-Hfc^;?NF2`4V%K6PLEX**+ZaoRxv)I536iT8apQQdz zh4yvyZBeqg-(f3s?tSNr@Mppg*=J_aLdaonA+0%cI`Ypl^gSBa_N{WePPaOd+#~oT z_&Rp(Non_k7Duk64=(<7@O}`jT0wf$_G-HaGAzTj+_L4-6j99zsLCzL@^Rb8#4WWW z8enpF6XieUnfY|_QVub<&-2!02FHRtiu-{VGn1{4jeBr9`}4uZ!>vnpHgCfUb1wtF z+sb&!L1ikS zw9+u8_57NY%9pVcb;jfA&Z$Na6Mai$HxV;l**7IDV@o5%*Nez&Z}pt4F`c|?MEqy9#Sl=et9CKZWP7zs@_H+kn7JpX#$EBbEA~B7D>{es!rLS zNFn+18Og|LW%jXl=P5SKw6eif{W0fyJk8wJsHTYc6ErSR;f!FZ@)vN<(Jy`9H<-(8ycHd9AD8&mbUNI_orqv-xC$)BMDf!2ioyyCW27a4o zxX+rX{^$DLnDBzZK$bggGWZF=YV&tQ4~!FHW58`K^uoPjoq%3D_>frbPZqJhTgqT< zV$3N`t-mug1ZzQ?ciCO@w9r4dsXv3v;C?eU8@7$|gu?m-#{f|HYCv^}&4ESh&E1oP z2YCt8C(Ysb-k&c6zKp-BzPIGS;vcUnn&U%sAvmi#9XE*AJZuIS0~h<0``QiDL{r;y z@dq!|{%nbrPF6eitqNL99`JH>FGd%QaYroadGo)Q&Y~l!4rSs>V{^VUe@h8Rr3<9& z;_ub(Th?n>$m`JVLE}8TfU7&)EZD)qyN2}^DS{J@Z&Z zXuuD6R>1Xbsq(R;Tb$^YBm}DdxU-J=0G;w0m%HVncn+6Rk3t&8*Bn?qF8c!~PhUme zae6`sY&gm2iT`RX6uA?ykc{u3cIV&%MlF0)Dubo1y>>fh@=>;h4DXB{8HfV#?6iL} z?PsZg2MaMC5Di;{DiI_m+}k@i;Mr26!3R^?OcW%-YFoz~mF2>A-qqZAC+v@HHrF<< zy(~XiR%N;uijxK2rTv*mV7%ViDd3)O$*@~SyJDp}XNN+{J#)$$b=rk7F~q9F|0v{) zf>2^ckX3!t1j@>2_?khM^pRVdTD?gkKO7?$xti_!u}@hwbf1M&5sE6NsX!5fa_+>; zs@`zEnZ->RL$fDZ^ZS9)E!7w$iG`0nNPsJaT5~zVmpu;leUpIb7>_|R0q`-%qk(h_ z`fPFIpzV7Z=6jcGG+uf+Q5<`{vCg(VBjk5;#ioUOH&fe~oUQBs2Q@bJg@CxwCMf^R zAuZg=SvrqDHNEwe>M+T}+;>Lfsk~{c?}pD`61|?1?=5^y{yS_XS9`VEXz2#&@Lasy zw_wVWp#DVX>kNS@bE^vceb4Y6^3Y4@$DGqUm$kXc{alK{jYo1v-E+^$@`EU?ofmd& z4?Z6*W{hTs2zdK&p*hPblq%_GJ~48xf~|k{CUT4R4_{vgK#Yg*RBOI^Q0ZBWUj~#% zvU{~g#HQU+w?|6Cws>US2lk@=h!;qSf83dF9ZOJQ4oON+bHpKoNt zG3_@}=ku3l#D@)^kH44l7PzeX4>LnuAT7VxBT~KuHB3@W8@KkhcPebSzzOj8DLzWt zbdBw9UG3epTd4;mQf(4P?TVb$pg4Ee#BV$?maKL$^_Gut$sSIMZ-M_nh)-YrJ5nOp z3_1ymT-0EsgJeL8=?hW4$3m-Y&yYlCrE`ATY^&rHRPu4X{PJ~5a4#&cjFN;@(fndRzpu8T%A42Gl8PMN@P~v^S$jga4bdBs6#|MZ$ zxl`0?zuW>E#^sm2Zm)S3DA*3uPvKD`C}v0CzxnbyDItqrnr$% z7^2D^@@se;o7XAV6|X&R9V4J3Kqyq5J2iTw3zgyShO`GXp=&Dl28 zRf-XD4L69E4@1kz3vn=HO%S&p%!%-QhJ>RskxtP5roO0wv5m$aY^dYSV2!Ef@Ui^< zj4xXXePr@yai2pSb4=$x|M^^tTV=SNN4eTZcCQFVro2A!giqXcQ>=qPHD3;%ytn*h zT-rBklMnwLw*0`WXIA)>(hBQq^QxG&A@&7G9_9;z_->)cVS_>g_45>}Zv=2uL^X$S$)Xzvu%szA~h zdD9~kIFtn%*D%i@cmwCVJG-C`f8))2g1g$g*j^VQIFP<2xrvrF(neV%`RFFrOqEyv zoIAVrxE04&kRiyuT>0lH^xqVEinN>`Xr(hx$r}`*I~T(gT}AjOR!(tjkFXb8gUyJv43`bFA1UmoT_{_d%_VxgtHa%FGp5`KNBkNb4$BZtM`Ri7? zv(mv158A03>1CZ;L3(+x(J;`ea(FT-CmvGY-_-%${T;XiXB|;kN9E3RiN$(<6`LeD5B=1!<+xxZsT~y#cU<02Fmjf&Ozw$I^4Ne z6r*^pN~5OG4Yy46QvL9^~|%u^8>xj?zBF%BI+~178Q! zR}VlFB5$?I^J$I@Pj+*fXMxFJ0-=7~qmGNc?tfmkb@($PV-$f?=O4kl<u@?g&H(a6(IxqX$JRbc_QvLO+9+3k|EWsg`> z>s)$a2}VfbRpQ3VEq{i0^mqmI_jM{%XD|F%!G-e=e+T@&pb5kRd{#N%V^uh zkDyfRv6vJw-{33T)YPudb`mmNrJd|1a;H&jpQ?|dt8BCOzK3F)x-jlE^n6yJppN^ zmZ-enTd!JIYSI?YCY;oY@GjY;`HETU(Uwv7dm~-B+nLnULj}w{=pg!}Fp;dSK}Q9H zC~G@@f!isI!HomRTiK6hFo$s5X;oOB(Q(NY!dqvsydX6Y~jd`KgF1K`%l{PG~>nA%D(NDy%Tw|s@JbqDE?4F4_KJ^8Lu)BJXc4&-{Bk*VD=cs}B>czrbMzmoW zFRKqtv=lX_yZo8bSID`))|)rT(r^zQFFv?)z@zkG8z|~mi!e<2oeJxyp%+`5B^uX zn}CUb-@ik#;QSb^`H4ZKKjLA1fYyyo5X_7O>?lzXC_>&{*uJ+tD3zex76Ub!B|FYV zMdb#XhjSw{=)rear3?nTW7@Z{0EG8$a^uO6o2VoypGdj!Ms2oLP(mZP;r!%>%rc`f z*jYqXjSwJvQ0i;cPS+vqhwOC#PkFi`LwbH)r^LzC#u!JeotW^$H>k#6#tmDSc~_sn zn)JT!x2_S;aTMajk6zN|)jWlMq~EvIi`RhAbY`W-S+rFG9pw%DX**SR#%M17?!?Ya@Ea8Y7>5G2AsjJ{d3I~@{fBj+rjlVNYPB> zjw|8ww+KX&(enqmh=L*1(>EaWMffvZJ;*b^k_4fGCR7Ex=MM4HZUOOL!ZZysaUbzVOr#0cj#PASus z9B!kwtwy%+h-kMh0y>>EAb1`vm6vdW!Bp9c@GY4KboL~YmVk=z z!S+Ch1J1aV$JNV}ewhgfm5sRP=eIWJ6o_YQgotQfmygS^MOXt?ZPk=FBe3|HsT*yM zB6Wzkm^1F|tIh)>4X5{W^Lj&Ny?)siQPm|fJ-bX$J;8O5 zNs5W@9?Euq%{%w+lc7q^^|qC5*W8K2;$*9V43exlgij3qJP-+Jn8`7-i^@8VV2AvW zS$Iz#BaZaGpn&F{EQ^PcSjD}tc#jp*-<6?{?N;mQ)_s5_NM^M{CF36bMTPu25#6T5 zewQV~UaMKE7xr>0)sY#OyB?*aR}PycqR2n3gYlAnPX7K*WQ|IvO0O4_L!7ivc`M(% z{s%QTAe#n_zk}n9;HE+Ojov}$+d`wjv(uVoi0?+bS*|eOo$0B4u;dEd6LL01lAFxe z%R@7z;@&>p1?COBPl%yhPw8RX?tRt#u8NNLaQg|a`!&B%E6tl?ki?vsuJsEahUG6`Oq^oM9=M3V#E!vti;lRg>;O-0I4s@4J{}d&-v6ut;{0cRtUCKsszA4? z{}h|?WeA^>S~1=y&~?hIr!~Ab4?Ch;XC2JyvC%Y0Hc1s#xVcIE(UXUvtz%!r;yv4T zyzr+|zeQSYr4i2BiJ6I|&&jM8^#xX(a^U4%5Ln4!-UIGs(`0ijd)@D~f2pUiR%ky! zWD}DBf<&rL^1X^+t5OGnj4YaYH{uE+N+*v^j}+WNlea;pDAx zYuDtr@ud4hwe;x)ACL1SFUrv@&SyMjBqsbNct%@nJS!+DanEp8syt?vAa!vhxLI}W zBeF=|LSgL!;U@j7fe&=dHryg%1nM_^aT+)AH8MGc(!Ha8SfcdP*R}I>4dv33Hg}tUUQ6f+#2Y(f5VR|Z$SUKe|Rk?T8;8n!p zIRhB&8c>UsHXb`+nb+Y+>aZ~cw`Lyi*h*aMS=;zTKi>UkX7F82-uewEUs&&;B!eqC zq)e$`{%;S%*e+vs#e%MqZeh9FKCUHR{H&TwZ#|bzoHkhgoeVwnH z;d2UY)dU(g$Obsp0n?u*?ojowVBEuzzi#=IX?LbBia1Ymo`ZZ^D>PL|8Cd4u2n zxA28*X3;&g5WP#Zl(9_q1jpKasFy&)yvI-Z9aq6{;f3LHfrxSbc3HnEA2{qx%D1%{ zIsDm3UbAFH9?bOk^b}sJGS)*Dn&OxH^t*iL78Ff8QR|HfZKGd8?l5=+OSrewyll$gQZVJ zE1fe7ueM%cK28L}w+$R158mT@egE=;Zw_@rO<|SHoxrca(~{rfEVHu*?o^IJRJgc9 ziu9eZTQqnU^fy7S<(NP=rc0|s58@X$84Wt2)L)M&?M*dyE|Nphz91U_ImK;=Oe_B% zPQl>~SyH5zS;fT@cOAKP>w3C^$)f3t&5c*v$+USbo3rf&q#6aP1(UkAU9FZR|9r2h z^(vVfx2FHCe%bVo9>1}}aLa7GQ7@4QanLG%(K(t8J*xX7CvmDPcDNy6doQz6dbA~Y z545#%bEfOa?iH2jxZ{Szf3VvDJ)|Zb+5_CTUZM=kWbqRHXKiv~Q_z!OQ{C?EpzQm1 zBNur8B%0DX11ah&j*E2lw24ORno`G@Qf3m?_UB92yP^8>j|~>Hp20a^?Ws>I4K{~z z6y*5>rw8RZ=k4il8Sj-hlAdOBi-j;`}@7(%pU*pok zz(m_q1jUMZm`~bHtB8p7>@T95#|W7ma4DXitr^wM7J z@nt@+gN<<&uY#V?VrM|#PMR_;NMX*-E}M1R_<3%Lb51C3zsu;7**1Rbh?Yhp0+ZD% zS8NU|-}MOU7st+4&J@e1k(+DlcdY9nVT@C=lg(boYDMuU{lzBNY2Y+4x@F3 zN@=71D^?qR@)#w|<9$uqAp1INtHnVkQufA#pjyslgc(L(1ut8K8CeEiYCRJ40U+%n zMgwERtyTYAgAVT`&Ao(4j=io)RZzrK0-gST*wv4~oyNb1dq0S8!>2w^*40}`nwDYa z_{ZmU59+o>I9%9xS+VHdqAO&J<;9p@()xoMd_EoU1o4`T(MnSNk~}=dd6dTS5B9G= zHwHYz*>7;tuda+;`&KZYN%e56Hc(!Z!R)1%*^-^-d7(i)rPVY-fM%XSp0*!4#bj-< z`g7v2@Vo?4G3Vdv5Z&{l_A_0LjlZx|hR_B_CE9^+A>c|-`H5c5FFLI z(teq_*wGgZ|x*&x8E%G3TCzCgF=7YiExfW_cE0fdq#q4NJ@YcVi|GBisHzYf7Tsh+Fm+2LBzWf8F7&tx-$k=29_sHu8Hh zhM;8$$fPdsC=ujjl{fmEzUWc3JD#~U*k)T76{^Wtg1CUr4d_W=s;rM95GR*$BrH*m z9R!Or-9CXS70T75|9geDn7qMw#>R+?TD| zK<~|wVk1_Hr;B!o{QCVE9tzbUHC2qEWbh|tUMp}tET)7*wIwlEMXd9Q`W^xz8j)N% z_HEi8>3fYtFq0nh9UgGe3kbQp3cEFNPoz9_$zbjn#h1w_wFssGSB5BXZJw=KxA7DR zSYawZxWH*_!cSpX#>McQh=H0lvD4*P1TV9~C^~kKH#&{NPdf2^OkqR9h>M?lJ-&tF z_{Y5>oNn`K6g41*{SgV7{=WUDHBJ)1yFYFgs5-(7-cW28K{aud4%LL!_S$=tMIYIN z_W$^{!Km_L;ZgV3`STI~fOL$b*qCt)U~ayncl+GDdCzk;>YT8B$&DS!(%cnq%8VYy zX=_XiWTamv`49f~-<~DCr9?F+wmUm|qN9J=(;{pngLQ3(vQ27}B}l~o@-N+unlIBt z9NCOv_!s$k9%Wo&Y@eD>9BuYG!}&>m-5tCIiwvOe=tO)7zdJVM1)^6%iVLUVE#Qr= zwd$qj1_PA*fzkD^VYHAA_kcIjJ0krB+Ml~WthtI;o6L`1MlqxXAA1{U=18>;g?;_8 zp=HHx4>!7AAoFXA-4LSM8oA>R_(%Qeg@m3e{DSXL#XSr)<8kUosA?ukKI>A5<50qf6vSRsZFe7@U%tr)|yr}PJ$bd0Is6ZoZo zE|6xAAryrjHWsRP#F;=&J?YtU{DOLqd*|u!zJRWxwF&G$RCxbf2;_?GR+XA*+HSxL z0^?%8WmQThCiuBIY9qucsLA_FWIs>4S-H_gfDw1sZ|oBkfM*Qd$u*yc(?aG{dY>a7 z1RqwKA_60}1q4mVlRsHFYx6PNOAQti!qz2OV`EIk(3btzssGipfm;JcZs|`4_RT*| zY?PJp(WO*BIONL*ASL_|^`pRX)%L7R;n@Vn4qfIyTH=1y`y6h;^!~U4$hJDJaITjW zx?Ht=a^_j9I{7ncN>3>oc~|*EJ}cnmBj3)nJCftZv$%|NrP64LAZ*pbk)(l<5J=JL zO?}4=*$-6IKuU9`{@=6;OP_Dv6ae=kYnf()&MJ zg<4{}Pw+!kJB+{a8mCZk^0H(GDoP--nC$;1ov}}$;l`pFl0d+ita zqQw&klGNM+c?GfbP!s0a?zG1(ZTpUkp}oW=2$jw>o5GzBY;#gqizKRE9s;Z5|P`NsfQ{Q?1wM0nMJ?a ze@pI-^qkU7((RHxJ$c1nI`Ya^UZ`=UufDaIrFTnxqe8RB1j4c&d>BbS^G=wl%4J`I z460w>IJ;XIGx9IMx#f)pR5u1VN7$Fu&IpqLQ(0;n(~kfj?L90=9>1b+ey_S$;u24Y zl^9~(#4uE*TfNiymI(~s$|Lmme;>4uGwR3E`byEksjf1a@(PLO?=uFsbPE~@`+7^2 z(Q?@7j~J$(#K7d!(xFpjt^}9qOa3Ph61Z`GF6D2Z0)HJIU#S7UqUy7F4zH znl>^GKAN@iN7e==57XTOuUHX=Ky~&bZKI%c=nKUQDJR;i+!mB8UDt@&*YQet$JOn${bY#)~NxG|u~R#q__64tuYXT6DNPClUc+qY$GDfb~6W4{zgb$2QZp3`9v^klA|}4J@~+ zSvw0`4*XJ;?bIw6w`BAKU(T-&Y2efM1^3}x33jwSAKIkHGf48A0;X%AMeCt4tF$6! z>!Um`X0B|>Mzc|Bj%cg5TLm?pT8#3?r)*}_tqDFjcucFA6K#vgN!~h$@3}Sk&f!bN z7mJ0bgIgoChxUD#2$d$?&65XX+`&8#?20l&UOW6yB_SiHYOu~4Enbc0d=PU9I5)ps zcE>wG!F$RNW>gj!JmT~Q|7OcR*-gI=BAuL(QiuMRgk9@`Udx4atR-}RU7;d69T#j% z#b02zRa=$W3OTDU9+V#H-Ye1zM2F>f&d-~(9CPT$6FWP#k?Ke4leny+7JW;A3E9&L zD}t+gNYkx^wL(hJ%E>rEb#GDUekC_BK()f@Nuw1qB<`owN0Ll-0^YdNisb&Wz5Z0X zjwV~=dTL~2t#eD9Z8Yw2`cz;X)G9E#4-8sYzs?at_G-?jLfJc4d_*JSw04()?&=Qg zk>H)Y<*D&ehhlDE^mbgZ)lN~!iCPfuv8;Ob2w=RlH@o_0Q)@rj-*1~G21raCQQiJW zYQ}1n{6j)7I$hgOwdx_75G}K{N1jv~Y^A}gJ$IuUlHkFL|Ep*jL-ZL314Lepe{WL* zY*mb2(BQ@2#U9OUeWcxlGgjxqV_MuzOV zG#&hw8vdJgu~!jYX|B0OS?gXPWthsJu7q9pJlGp1WZ}DHDByYF07LMp)tCj-&!*J3 zln*PSy%4JE8(WfhhdcDl5Bsgx4hD~X?=Tv)wTmTly0Vk&hZ#Ta(t@>KdRe7T_9K^~ zsPNUZc%1GwO~a}-p0nDxqVP^&=}L7$pgwMK1pmsoLm`{LFST^@$w(bD{3kj)hlL+C z-_v4>;!J?A%=O{Y#~kA&1wd} zft0}qh3LqavC|@eJ&^vj!LG`cELupDFhW#_pBw{-sXowrIypc~D8vzpj1G0Ph}iVI>OpH8f5*>1r721#b~CCJ^2LXO4&MAO>08BTiWn zU5C)=ZBE(n4Ux5%xu^`EWa5|6GA}in4|B}*7Du)w=_P3fy5hXsvbIEi8rgmpSi663 z$;?g~og^8Z{$>g=^`y1JXcD&G64EB4Z@<-qHihV$=1Co6Q0i$%^+3X8;@}kyxrN(q zJXqV;cP3`VV1LEj+bP(5Y+ax5fJSFJ&ntNkuE)rUS-`63|EPRef@+HB_$as3=$P3q ztHH+ZeeIq4`7csJ1O8zP&vLuNe|?5JISK2YYtPp?1r93LE3thz>*r*h;x)cF5x3-e zEB=UcigWioLJg4t!NZHqMh1Gxb?|!d2?}G?lwJn&?3K|J+ahFG;0;8R%r3SSIzxMF z5f``{Fxm_B;nSXI2O8Yr%s{W4JFDeBUJ@>OYw_O~{!Wx;3jsG3k{zlajVHoqcXe;IM<(0eVHW{P2@CH7O~bRt)R^ZYEZAn~&f=l-Wfy2- z_On~h%a7-5`W1I#r8^*Vn$$b~k8ximhrI)hw4Fjnul$&Ew_OWI?R3cfEe{?*SbIAG z=l=bXiHeU?o;>(*Mmy+-Kv|q^S^LG2SeUyn(KWe|Nh5z zY02pJAWlG4FfTNMi3m8c^VR6g02H&LMQO4vL5irRRz6FcR~i!qJ_1Gn#29q{;!frP zPUe}&vFo>|F!o7`k1OZ;S#B*86S3rX8RZvf0aQ)WMJk5~-{nW{_k72N6Rx7YLgj>Z zXq{#n#sqf<0l$I4)9gy<#_Xb~123p32OrbjT^!acc!qlD$1z{kclaCuuKQ8@IjkN$v11TpQnjm{=8-mhnc(Eg zcISt9CHa-|pK;jCdaIlwZ`EJ3Y;eFu`K$+@jnWie_M448WAkWV*%LN+$9;0cCr)(m zp}QD)LkP`Z+tTR1P`=kr|DQ>EJWtX2lsW4B5BqRUkrWY^?73^K?&)xpa;~s7cf)BV zo_VyXz`IX!_~NC8ipa25!bnd>#T-9NvgP=#GB@X|cOU**O!4blz^TyR!j%N*VgxxLJJYVjnMN-AhD89qPS6CX0^n7+d2pUYe~XmP zB(hgv?i*eE_gIJ)&67%{C~l4l9@~eHlqpv~9zFa#X6wgh_AC=?_M7d)x9i0KOV@xm zxmqgD5w8t*fz0OIh@;*rlCt-;q9rR%O(-dL*6n2mj%!O#zpwo*AV@2XVwSX}v0qIE z;8y~`$5%uH+iIK;v}a2PI*Lw}*j`0w!UP6kC9edbv#(MGtpkwb^+-2|^QLDdd-65~ zGl~OVY?Srf>2+@qOXXYBO`Yp=>ebS0g#XIBPwSRJ@t7O2yQ->kAYEaDsx3xpx#-(~ z^`5J`;%In0(2!HxLPI{t{b{?P>qr3Jr>T+$CTnkv9dXlWr>MfmxXQaj_r|(66aNB0 z<$=$r=6*!ydHh6%N8hdxr%A+1t}VzWvIvTzsy&1p&yy7k;UahfxJdS?+5>K zB?BjYSL9(>D01k!76q@*e|MEMkU^ZlTFG?*cn`PPQbZ);?^DKtNwY2+`(n+5k46oT z>8X5dGMgzlAO?34OM^YS*^E{5A0Lrr6E0Mym(|+`w=1=X4=Y~-WU+S+f_BS+zK%D5 z*V^~?@`r;C=bmpKe9N#;KB=dZHnlF)1~mYXVclnUp0sXin9-C~%v$fYcc|~vVh>r- zz*NF%K;= zRLk;EeGxUPgLi5+%N;rS%rmk)$qKWA#1cs>f!W@RrNu+Pk0>&YyB&ga;F@RI1y)I%|erY zY-^%gRSR|W{!1nNGnHri)Hj3^h|b3%6SKF3oTxO?cBdKhf%+)IMR#1c-@Szgcjk{m z*aKz|EizRQ*Ec|%V}1>MjzE!MnF{v=`XZ>InbxkGzg7Pe7}!`iE+SkpCa5F-A6>$r zhutuh4G;J=Sdus@8y;PVAM3(@zdRbJ{b6@75sAw@SJ`3?pXVnREkPEgVw9kQEa}0| z#IUX#CQHq!+p~MMVZ+sh7^DAQ`na z3xaNZUZl(I_1K8uULQgIK|4VRf^aQR4j8ZxpK0rf*2OC8bh ztHX`ugFD`gDZMa7hWuQWnBL9rv~nwuD))Z5)^akOQQmJ~VS7*{x7=w1$`o(!1NBy3 zwW9V@>oPaW3%`x6N@1e(D)BjT)tesL)`BH|`|gxi4eoW*soAx9gc}F9QwrV9s4L>?;`}XGVwTCmyDme zO??Zy!6Q>Vk~6z*&t7~szAzgTflX4w+|8}NeIP&aO_hY4jeOR&vBl?2^dXDn)mo3o zGuIF~)qsn3zVN{>ia6i`Wsd-la+;m!FjMSh4 z4F4S}^7m=Gguw=~n~5-+ zis_x_Wc*BBas+r&FC3aL84zR?iTGC5DXry#nShwI5Tb@U+SL^JLee(fyOE1O=60 z?vfoef3Uwb-*!!5nUu8q!|tNjf9&=H1XLjGZqZD&v+lLj*J!}r>!z1=Psb1l-SOW5 zQ-0sJP54mz9mU`dkc;-)fK(7yX?5s`CN zKFcWPfYmzs0{mi*5)e{jT#MnJnaCYzv}@ng2chL1+Ris=fl3T)bSr6PJK^)6DE~ok zS3htunY?B8$nk3*!?91%JNd2esxL$H)fM3!uSmC zftA?y2*@hm5LV!W=e~C+B0t{B;dECH;$J!Mxo^LPdx9km7`r`M=u52`kdWW)yUn9L z1455W3*ZBexZGE*t{0u$G~c1H4)SPA-SRAY%Uw#f^jo8+3IZF8tb|pizvULFwnjk9 zvv4=)XC{KGwo%rP40Kcz$6?#yh0Noc>F^%&uLg65Y8OY#3Js%)tVvezmh9+spn+XD z@9d|x+mO&9o8^FzKeL)30Qng#eMu@@zjYerOFnHrYAZEQ@si*9b@f#B;YRmw{O>+0l_XO0*v|`5W)M*$3^>9T6pvs)fu>5voxdA6<6|5 z{*YOG8<6c@#b!u$5zsJd@Z44dS)O*+|3j8i;B02she$ zUZ&#)9lPY?q^ecPFdJ)puW<@)m$x6=C>$)bE1S+;$?G%+O1BKuIAn6HnF%Dj^mR+e z?FtwBAA{?s0Y~Qqkmq#=17mgq%|2#~9az$evpx6Oy4$+GYkx)`Kq+Zmu5U(mek+KS zWS}dbk5{>!ipV~kp}Mt!MCb)nk=(4c57uMFxL-Ff#wsoDk>G9ZFnW_FhQgeCO78DE zY9QkGdSGyYDhN9jz@SKPrq=lsp7DPVxG;K}eUuHaFB}gNYPr69yz)Hm-e%9mZc(p5 z2Pw1n7_@w%#TTXShvVO~j^l_`?ab4o{^7yIr{JC?_t~Jy=hRFLq4ZSgT0K57( ztIl1{4g-}zNS9~SKe%zMxi~a3ZL-_sCHnT?=lwtnT1l=H2J&5n3IMa&&%Z9nsVJyk zeW~MpU%`C9+AMu*{Q5BiNX}IeK0gJc#I%n43tFtUMPcc!$1FL6mNg6amCCO7D{JZY zJ)=^^{QAz2&zvvz29I>Vh9AWo!nx9#A(S0{EV|k2S)iDC7f5&lE<$+7&Tce_FE~Nn z3P{mqt+>dnh43Rxi}uRPJ*yL!oRAj)oWKpzm601`eA@onyymYNKZQN6@5)8Q$D5?v}&OJwod}Z>d^6nvlw#R5OOZT!q3Eu|f;_K8^np zw$EqMI#d09e?M~L;uq>)r#bT%{!?d)w-p3BW=-1r&NZ9o4ZZY2jw3TfDAT)FOr;>M zeYLuW?E@6x8Q=DU`A~{U%POg4HD8k9*{waOdcwliP@BIA=r4F!t2`d_D?`CtF2%yS zG{Jwj&TfJ;KTqn`NW71i+bXgRz~isWr-1GPF^R?Zfrk4NPXGC5@*5he;c?e5HFlA0 zAdDB>Zkr-LVuE;sdwZ%R0b^T?g_KX1(`Obc`%wUF%$>AJ#fd2Lq&DoCc`oWC`B&Hw zx>L((U!qT4%S@#wxp_SJKckYwox3XU?3gQapa${E3Nun=OBsw)VjISler84_zqI=L z_f7p`=pw7Io~qPU2L3ft!IFg$JkD1g^&OebUV-1K+}3jx1-;G4HfRnaBC$=~nC$pp zpaj0Bplr^fPHE_-F`6OED#m72E4Eak-t7u1%*DW@57P6jGZs#`++r-I&;5@5i5$I9 zrD9?xkdK+CjvgT78pIiaoW<-PKwjM@U{A~zkY#_<+96pO^L8TWYu0GkiBvt%S!>gQ zg6zaj%4$#oXE!k`KYVBGONdWvqnG34py>>%apm9g)*l9VQ(UE%9++Z16O~`Z9XIvK zUrOX}$mVn}Wv|6q+)NwMEXi7Vj&q-Ap7Ltol-SQZtJCrS^hz(0l0N7S=G}}$rK{W1 z4rrQd@Fj4B^S`T=s+$W@gTrDL>jKsOJ6D#a)FJ$R8ucAgbW+l`U84f@Sm^xyc@R{S z88R5u)n9Siy0w$OzPZ;aP(ADX0hhY)WnQasI_EOrHeHA4hUN#o4s%pr z6RrE;&(3L7T;*xfH`i7e|{qkhCTv;fGBvvoEYH&9;M}H}-kLhf# zdLIgwe+_I0v@zm3b8xDlYnoCAJ+Q9}+3+j7BM>BteI=D@{il46*M`@B5ivJa=uWX& z$p9LX-p+k;O)EWPl&k*5iRDuXjxW=+A`dky>_r7$Amw-b)c73VQ|j{MKw-j_kSMRm z*?=Ae6tA#qg6M+mrGrvSV7(LNLhD1pu@OFt?e)2z^efvTZ!)~3<^80O=Y+hd;+=hi zlsY&c8f|wFHYC(5(&V7$9Mpo_n!czrfsA!6vt4@wK2}Y;zx{44HY`O{Z<0NSmp)UbQ_1t8M<5S26Yi_KGIoi>nX|!GVeE6W6o%6SR6V zHa~=3m2^O{Q;OmmVM?RB1g=&mo*e*&XFdATM{Kp`J-m(Y0(HhkoEvL@5I?I$Iq3oH zJbndLvQCA#?|)EKPF)3^=8e>O$}Y`x*(w#M9?`mNumji3cx~1v>1jUFLFO;afajPF z@%MdBv(F1rIZ)fb?_j4G*rA!|7>*pQP@fH_&JnxA3j*I{jc^2T&B4wdeqNS@SJgj3 z*qNJ&2@*Z|$D8M<4j}ylzL^E;QthroLPAp!IBO+QbE<#+7&As>%&t$FD9Sw8XzaBB ztyF)qo}F$XLv$_eN20N}_n|u>Km|c>i5m*h5KP(~&^y(gnLS^+WW z-biM;X!n)9u&dL(2P&?Xf#y>M$i2=FQzeuKUDSgOuYbES}1oLefFXCrtv~o;oyk&+nk;7ccwl1{vKw$ zBT6w}5#4hr0z1Y8Z~avuFa_{~ zY09ixjw|PSx9olomO!962cJlsS*;S-Cyls_YRnwN`U5`qc;V~^b7vo`DVic>8!KiIna?*VH4aiH4`06&8pd70f<5W&(OK}Gxh&*yuOOctx{A(rBbQT z$ZfOyR4TVhxi^=}ZMn{6H(OHVUdf%UQY4oVavkQH*yet}ZP=L0#?0n6KmWmboX0um zb3X6S>-BsJoL*t}8=Uj&)AQ@E-Vhg?5AjpmI9E%9zk=i-lvF&5KdiUq*)8aiEY-JElI7%=dNKysBh?zqFqM!)YSF zMbelFi7fM!vPr@o*=-2`4S@Z-l7s_ziEVM8u!yGI!3m&!#ZiT1VujsWf|jQlN4uw9 z(4P^z#!GEZpC{~ovSG(|7`2U8eD!vY5LAYBQpi7IBqak&2;x%ZTzMM_80~r| zJ?ptJk{Yxa@L9hq&~f`T?#;jnD@!GMS(BKZ2+&x(iOresOx8YhSB^`*`$ulMMeu^@ z-=0$%A~ddP5Gw&Mh;gqF6h9{|jL(hyv08Yx1xEiRwBaN1);>SeJG7=@C^!1YjaWH* zuZ5WVA#N_>=y$N3r@XX~(v~N@^=-c=^LBN0sRz`Vsif3WiL|$Aj$S^0J^<`*dEpzY_pl03Ne9oB>)19|Mz9<0W4aI_O*6qwRq_0NIgP;VH`;Pv9Dgj9&H0Vc*Kh ziREsB#56rGdrn1(Sz#jq0KX z-{&MtyYEVsbsvHPN_D!gnZ3xt(DsH9mh?|I2lqJ|LSZ-c!M}ziDt_lqUVxZlf^_b9 z9W1eXzmI>jOdbl+ z+q5BH3110JRUJUCwEps$-?SBH83yjhUn+FSyw~%Hoocx8$Chjd6>ibKz-4Uaho@nf z1H4O1Zx}a1l9n-KXcuX|#AvAlG8NxcM*p)M#tBC{2z%YA&}`|wVqTDg(uI096TeT2 z!;fkG5PToFPY#XnpO95};!y8wv2S2bf9f4fDvYf%j>J(+9P8|f>l+Q;7-fIobzPKy9;xbF4>hSHU1U< z>FEIL@xPxHy=9xW@BZTM;i+=Qb)%0H}-blr0Cjfz%zoYLzY>{ze!gk;cnQsiE@puFs6nTp_z zsNNAyY=$riGxLb3!FhXg^ep`ST}CG!r~ll}ly>r}AkahM zfALJjJPh_H8Yzi2kG?rEDtsv29!OtQdh;$xI%zsjoq5aa2Vc^-&_Es5lHu+bHgQW~ z6-L(u??6aCwFKcOwTld0E+zF+4*yVjx7jMXDu+>=f;c2XPg9Fy$58(_7Wkz9#`p*6 ze`U2F^zM&F6g%r~{ATZvn#>X5$smF6ACWHt%sjd3sy%tdNtLIBURv)GMYuHC zx&^PqHAV-#SPyM6%PV(8JaLvES3tkTur2njwOxc1fYEM?5MAHQAK=Y*hN5G6lb z$rmj@2KP}X+j_sD&j}t>M8qA+GUK1>IqR{(k+8TD((Ir(?^4ZKz>}-2P=A|U7Gz0* zE+??x=cn3()tU@PZ^W6$K5zNFuHo6FdX(Q(2u;8*&ih1^ynC(~iT$6#nuD*LrX+5U z&EC4)xQEa#ZK(rl>pUkNg^hoW-IG4zQb*fY z%w^%d8cnr1Pm-qQ_ZyL>?jhSrl_hnkQABAWI%H7C|ckm zk#&? zmi_b>=f3osDwl&6ho~doVf0~MK1t`f?Uc?9w0Lc&MDL%R=MVi@{5F}b-l79OO}3?k zRI*!eRBKqew`u;jN1V^LbsJc#_lhfH-UV7XQ_Q{EeN5fmtuPR=mG6gmc|$8n!2ke1 z=q4)G5W}(@f1EMhGsNsaF*Xh}I0JtZcU|%4fX4zb0eNE%#L}!eOli34E*Kp>3Q7t< z!erc6>Bmo}8@TizQuxUn*E_BjEFsmWTmYei8&1=H&9x%8dT%mDMu+oY4=H8^`^pk)Tq#ZZC42tzOkx>+(mdk=NXciR#$aNgils$m{_ZIIqP3g8 ztymXd-bKwaOa*bQdv$8@^t@i@oxj_bma{4&!4Ef|nZDa5zw;aKi*95=8O={ieyTd3 z(M5{Z*_XSXn1zN)k^_7xpXX;}KACvbs-0)%dAWaaeH67HE{cf49~-A5x?A@ccX@Ab z`+REb&0wlPNMkx@(uz=rrh0N`?w-=CO99NSveV|&%G;r(HVBEJr#tndE}Ec#bMT0P z69g#ueYy)6tnVXED7TGAcjKamG)hki9}~UMk8379#nSTErF8&-?^E4Z^c>EZXQaX# zO8j0FC2yfz2)JTU_V~BGED*zkrqOs`qH$>1b;Ss4Fc4MpXcH;rbH8@xTFVT5wy+&L z72-QZVRS-ot0m~q_~B}wiZxqy@z!;csT)0n2X5-%$BXX?%z-JxhQL$;8pG1d(DQm2 z^BLfDNNeX}qn`e)n2;;f%%K0V>j}%m$u{`^I+QJU>-4j^2G5yWluekK^h*Cy7$TIfLC8H{w8$%7}p_|Q&wBbelef%gZ&*>pH7mS z_X9PPx|3&TW{qXx2)IFdm|HrFLZa_qgA8iyyc;6{t+ao@)C%PYr6CkBQGX zfXv1x=;5W!y~O2yqUKJ-2ScxKCXnZ;V`**X?9z#e;~5bqQ{cn2$V`xF(xiBP|8NcIH1KJ85MFp*LVH zd7__7{BrQ_OY7Rzfgpx-Dw)zqiN8qrCsJ_-bG?GQI%+(A#^4Eb)w+$hdrMk=tm{`& z73|y;UIBjr&i1V={Sd_1e-EV_>~x_c*!(LuNgFlqnER|Fzm}?Rv1@ZhJajhp2u|?c zfyY&`$Gu7Gsin3Ka%P|KB6Zvc{Uykli;K1-S%1O6zm8P?yRL%lxjM&4>Nn?+_OSj}g(rh=Ep%PWRRKoW~>y&4aprjlNpr3Bms) zn#+xSQm<*GVBShssi(9NX*0db9%WBt(kb^nicr`CX%>MW|UT57c) zgUo5S*9DlqSUmDKJluy-TLYMHvRwko)GUC#`-9z{aOHT)KO4=dijN7)cTzP}vPU)r zx+S1V8Ezw)-^o4zqYa{i(~g3F0rWZ~2ZBpBe(GGycng4bNVMFU%IL_WOL8UL2@K1* zvJm5P zxK5bGlg20(@o-;?B6tr) z+Bn*xLHnouSTNTyKe@X4$HC?5st8r%Iy^{YAHOl!M^@aY8;=S+O_u?NTYop6W7m6h z-fIF-O~-y>{}Y>a(1Bf^lSK1fo9B)cx%Iy39~$0uR`t%h`u{M{#5ohcxN7_|Lgag( z;E#8kk1>XX{yE(?D*W(h%%+qK&0X!_THrN-qyv9MMtb(Brb9;N(08DD={0U`@0->& z6L6C=cWiFQvShaSi^@c%!>^WUFnxmL&Uob(F|#1#eRAB?1a#m{F_z8C?_3LGMDI44SZII4CQU6 z(xQxhTlId|xr~f9fB|BhOmO=H@o8z=&#=vlkzk!igO8;TL2jYp(85P!o|qqqv6enAtSOT6oK6-31OvUNkW+#B;*aM>-npb4E zMZX@%aqOyXMj`P-k6Fq!s%D9I@6_3stf#7=v@EPFK5e8#{BOZtOW|OLDd7pMf$LgB zm+gq|M3F4Z97FECUj094pJCU5)=(KHg_d;B4c)>q#j z$-c8vJl>ni6(it@O(h|54FR>SaSbos-3|@yTGn zZc~v{5ePMS0PnPUggHNTT4P)U@MKkY?%KnwDS&{t`i5Ig8|kIE(mEe-ZZd4<20oj> zotBeJy)(qsW++`Wj{}rMesJAFKlf2xx!WPr&vpB)+l_*6aWX;cxTY&L$7A+r>!`Z# zIAP&y)02TUpD{gZKdv{F&+Uh(@*>MfF#czQ9`nq_?_lwH(8d>Rae>4F9kG<719v81*Vtyn z=*G|~@`=YHos{*<%WpgbA*jj-i}qpLua!zli&h0p)cm}*{b8vVt(Dnap3@7(PDitT zg?8n;fo6_IoNcRh*M5BJ&(XW8^y7^5#)9RDMq8FD)yhEz zTp&|boHn-Q4tE^4zogTDQXYOga4)uL1#!1xr5~SKQygMouOMrLxH&!2FL%QV-U6yG z>oR_(f*H<#ma&-giHdJ0T5<6jS6_)tM1MqD_gZm2u(Q@yfW4EY|KlDN^f`HyoyHGp zCm5{`3H1<$qv0k};yV#LdfF!jtHNfmy?IrKaJ}ibN=WmK6BTIc%qO&1P2Ps2cks^f%)aWYdQTNoB=eP5woH62jlUAGiE z4j6YYz85Q@IwkG^W=H9I@6zF$7t|Ers;S^D_#5fh{xbieR-dfAv7=zN?w4w2T=sIz zY$U|1PBTjir!NHl-1_EtYv((^=KQ?;!0wI!{nfD=qfKp@55e;BYmrW84DKn`%mGZO_c{<~skYbY6UPQtSE4OA zm*NGFi2vsORlLhH3$$%PVM58^DeknA-q2lA@>YP{dE@#m9UJrwVwCxT=#B@N(KFB^ zOEbar<;rUsRJ2GfcH=*(CuU@osao2AuN$TG+qE5K-7&tl@?8iR{jK7>LKWVcOV{b! zop)l|$4SXOZ<~VoPZXPG8ZRRo`<`!1yN{twl~^+poaHK?Fy~C>VvO?UU1FKD?`6~f z$v4(@o^coGI0}pxpHq&3WX+q;azxWew@sb|FAuVE5=xw}rNslhtbNuN7c=SIeV~y5 zlO1~<>i^hT8~=#k&3e8spDBeY;`AflDUbRLcW#oYk@=O|u#@3fx1Zz|hNCIwV{ zFHW1kqin0Xb`Be5>$-CyyiW0nmukd{E{Uxq+3#>uxAT>8&3UPblKPUrhHL*xxZXTF zR`0ghrKS|DucV?FOmugV>oC^-PGUX9!ni(QrKe`+AspqdSn_vU=o4XBKVRJn5gpu} zny~Q^E$w#o`e{=a#c&<(5Pa(3o|1oveq2TEZOmP-`UI3=`NlQ(7pf}O@10%0*hqVB z3^kA@4c&XJC83xyMMD51Udr*icc;%UxoF0(yPxeRtxnu|rc4;Ihd)g_im4BA2+Che z2&|hd+EVnCHrenTrPt#P;4a^G(=vPqIE zP5oB;hBs|+3a}UriODJ+pD_seS3w7>1h2ePz^9GjT}9FiquT+kj|fmT-txD$k63Ee zJ7qt94+x+njRTm(dcR_n7-R%~njmj?%iQbf=FjA7))XN}M_-K=RXS8S)cj}42a+$= z1`l77+SP>On;hovJ4$%ls_m1mN*(T(8e`Af0t(+rsa>4i|IKI-S61atf1M^qm1NT_ z=N@j+F&5I2L~d1E8vYK7*4(J2G^m!*N@Xf&@Pikd0*5umd0h@U{4dm%XZ2d`qCHdF zi1@xaK(*F@!u8P23H3{LZ-qc;`z9!z`8}xl9hTRezCO%-T0Wy99Hn{Ge z*W`8La}qPHHzD9$$oJ~~VIBK)?{)t!LgzrM~0i&Ij#Fbl1V>P&i{?tEW)22k#w1FV< zJO$#hv+@UZ1=E0A<*YeOMMkL@pAV*Y^%^5@vmY2l+#lQJ@u>CPW|-MYiwBsni@lxo zF%L_i19N?RnPm5&tpMaI?RLhylxFU0e%Nt}xs-qA%KLFOMJdn%566V|*c*!p_Lf^%YxmXj@*9TyB_DnKb7` z2wHRgJXw9TwO!B#^W3vtQuG^h2arB1(yxd91}1GYoi}gQsb>SO-!wa&75poc40wck z>qbcx_wQb4)RS2V+sIEtuTdWLv2|WnjZQp~Pi#Aa8YJYm&c#{>4b!pLZr>fb zE-Ad*YCnD~X7bd6bQ@P0j~2D{{xXPkNbh)nU)dMLfUz-ba__XpBa`m+`MQr2#o1eClT^*+G4v4WZ!rsrz#?oVs_%ke#yjB)4&u(q@DM6Vy(_${{q7 zWvke~byRV7{=H#Q$H?L5W36&YxFWGTO`GbtNdlR$VQjz*tAM{V3zuI;5yo6puD8k9j)^}#cQLvX;St`Ojv+MD#P~R~`DjXL`AElY5YO$do2G?b2-(d9=M~DZg#_dpytGI z=};7BA2^z*KRZx~MNR8+G>3BfV=#Mad$Ss|Xw+qEGP{PPU9x&QZg<{dW1FCuQ|$K(Db$ z82WPVc)z00oH^;q%C!R1n%DcSEo#TkXhiI=#;0Ebb(YZhrWfo{d6Asnwi0b^OLd<#OJb7HGc=Limq7E{(3xQVYc)n zR$rAf)M$(DcLa)~k=s$0AF;jXDlWLS%=cwi5)n2fH)K<;u&WTduGL)tvQ8E(3h&FG z3ae_3pWYs`r=E5++(mw;@SEb_M>F>~rE`|HF*e-AkZiXiGtVP>87Wtj{x&k?qM#Lf zQ)F6xLz};>H=uH|_4<=??w2TXM||A#`eSQg_vlI)5(%$T>&mmI*KKLPosSS_ zHl^orw2vIzM&pdKfw4kXAT(tDrDmQ*7`%gpcI%K@JLit3n1Wo}5m3iX8cS=V}FPKDm?M}^`B zshV%n?_S)+kr5*Jwu=L}vKzMObBeOr-`JcJoVJ3w{S>q4wyU)ZOvI@jc zpQ@=GY!kU1T=~m>{Q=~ycwG{(!a9Md0I@iNu0))_7pDelD7QA@UC$W zN?y4kW97WNprV99am_2I2vvLkbhcg;cFB{!3WEL5hun_`W(41dA91L{A8(a@YnaXs zw$AY-V#6+AlYz6TTm#OZ_gyvP8{-*(B_O;6L9T2_Pi>x7=+I6fX#5&pX=wZ9fnd!_ z6?Vm(2o%dWh*~*7zdoymRPFt-sUn67!p(a&Mn&p~p>wJl5ZR@6Oi@$V-u|;b{cVxU zTYjsz5b*Rz;<$T!yNdg0XB>ORyK(@2Rbf6TR~c@*eKq85>mr+U zlVLD9<{kxU4lsXcbujzIz^+QS*qgdG&)%Ecc5W?QGu~ za*W5FoXc2zLnS4eQgf%wR!ivFX=dI6Pr6i{DB)+wrGcK)y)V{MLfo=rhAl&$3uWRW z#OO&)P*gzc0>VzlA{rM0e-j~!j1k!?18)3C}f`Mu|4UliV62_ktQ+UG-{W(@SE@V6bXz+VZ1l!y^eau zIPf@(rXjoOr@Zl2aJfTCBVskpp=4CB^`h?pdV*DBUbj{5X>I@>TuNksus5z0yl4kv zg=UD^Nhi~Zcdm`;|0&bfoqa<3b#A9sDLx-`8HdoGa(~a>5nR|-C+q?NxQvq|%bp7$ zWdV&mWCH&#^XBDj6LQi$c=1(1>8)ae^lLF#?d5`|G>5A?VR+OgLw|Af z8s&8BH;a4Qq=-D(lDLe-GnDkr=Qt&4ThyP4+sy}11ByLa-&<&NQ_&twPf1pdOYKp= zV>>NW_r->Pj#RrN_8j1n%&W#6l{j71f#5J&pEO6;;i52ircaUOUKyU`68;q-SD~j7 z_^t8}tSV6%DCZYtuoue;y@A@3vkM(i+?ns+u1~h*G8A8>oq8D4gU!LvBad4*1!^hA z;tC(6mxgN}>JMa-5k1!RS%~Eq&2y+X@?^gr`H1p|+64)4Hj(Gq#dWW8)%ry({|m?= z|02v*BApga*E$YI3(j6|NcD8%cU=Vmzpnpveb6PIUr^0`wIGf>8YdwuBQ^`Q)*h(6 zU8nw0&pNhETFqLIJ)VDOdk?1!ca{G}n$0EGZ39c}fpRvRtVbR>NPp)bMA)Aen7JEF z*n=jsN4s;~d~dOiD_kLjukYD-t0Ec*a;c~^*m%|ZKmGIG^WrzFXUfdUL$9&!vs)*{ zE`oo}ZGo;reFpW#q@a|2lqm0PV^N`{4Cv-hZacX+G|*WCic=x!nr%sJB>A3ZDe5Nf zG7%Rqgrm&x_;%~^#Uivk?%Kq)oo?*o_}mGlLoHKvIf-*4TBv>HCcy#QaOC=f#V^@F zgA~!)MqT;{CPU%7@qPkjBqk>q>~#CorRy0=GZ~Y%Q2d&++SGeLKh5VjV|dKY?fj=k z_F3==RGLoR>Ju88cVKJ3J!s%s-D=sGo=*#A__zIVEl|juy`^(?{y*$_X8QmIQ|t2( z;vCZJX;AUmF=P$xgO&g_^BUBPj%4B$&$O(-Cx4Uum?H1O6c5DJfHiuyKCRVoivNK& zPVz=;K7eK*^)J*rMcS%;E4j!51fZcoj9){GECsJSFWUpPJa>3vfv(XY<=|ymb1mwQ1-S&@Rr5zl zR=OqYhA~HXY>`0Rb)vmS8iK!1@Sfo$#wYU_*ILasBn+BGEZZYNTkX+qcjYlhr6rkF z(ktB-#y{@=B#<2%bsG_$PV2XJ4Qb5fH_9Amp}C}La30lHiUEtNgQL?9Z(S7|30~5m zyaU%?uZxK?i)pM2pPGV>iTaiRiR|y)<6lQDIzwkeVrnp=0}@Z+HB-G%MVp0TtGX7NARlh>PiRl+P34>*Pfx1u0j z=$50q(bfFRXkF~ly0tdiz2!fQPYOe-aW*l@d3}kRx>d;=g3k=C%`X*Ne)2iSn~l!1 zv=7t_`&txScJOX(6OU#8<3|Hc^G1~t`UROjpx+j$4l1;OG^^48*-UgUZ8C(HZ2PR@ zBFM3(AIRS9e-e{Q~pAW! z@l0rh9L`Lk^=ZQ#L!9K9BPz{Gf4xJ_X-%L#g8TXXFFEG8w_c^S-Cm`R(a0lfS%IP8 z-c8g~^&9cW9e-|9%3Zxy?5W^9*SBd1hQ2O1cS4O~66<0yI~MZQJ_RRwFIw-qfG;;R zrFj9c5yVcc&9VqAUa$^1k++W^)JFAgm&!J6o+OztKK!es0D&riqZvx~w0}?Z0fF*5 zAmU$E<=W_cI&HXYht9O=E0CV!ikVkUmNs)z&mQm zIf@F$k{brT8owKew|H+HNQY*4N@1;>YT~W1y(G7FFqVBbZrH7u6rkQ!Y&5or$A4 z1xwz92ikzRZV>~?;O1L)?aCxxounwEFWX~Sq%?$g`MN?jBUH=&JvL01ebtO=<#nh> zcPdgkc_JYv%IdZF%1!_s5%zJ>Z0q8y#`f>lM`V{5W(6$FM)9~I&hk_(aUb6tl|lyP z$gT8~Sx=u`&R+JL%v-+=FUXL4fVZ?*3DDWu-6B}`{8>#(`QcvBZ7=ZPL2{Yov;nB! zzn>egdricG^XhhfGXn4DZ2hkve@Z}zBqLKZ?$0Ws)VQ~oeb;V-;WF&?IYXY+WNWXv z|6hd6aia{|u!vA5e0S{yDEq!)o!&@6v`dSL>_&;>fRQ`jw>wLu4+PcAH>fefxo5ev zbIv#TRt2tPmi$|$P>nCXYn5GnuyMUK{6_-J`4X?ZauDu^ZvU^X4t^7(l9r)(7Ia2X zsVf?2e!!yV-%#F){DO(kccT%Xe*N)}N$vJfv&xG#{J=`A>P4UK6U+OS2pDb9NnhP~ zb;9Ri{{ip0Y1br2)pm^)O@(-#V&btH> z1&bJqdQ_KL;o=kFTjrd0(ck<@eXT2AOyh*W_+EP~6eDc$=FO8L;pXG-+0rJhkEhBY zKa1&Lr;ke0dIE>Jhw2qNPDv{!V`)QTK3#ZcU`W@9C~8B>)t?hy30@(bGzx$XN2Bk_ zO{O<#+k|mM^2-c!R=@IjQ4^oIGfp-z9!JbSe9%nAS8e^|w8fxceKJTR%_5ON>bT(+ zRqqUZuIruxkx5D zTybj|KfGYf*HNwDH9P4-tsGi=x&h8lQe?Elm~Thmwac9N3u_3qnsPngc;S2rpWJpb z;DO9L+m5hA{OqVeTSqoIC{-bI+|*90P6@Yn_WEaKpNMQ%y@W@#X7rw(*=i%{5E@;|Xq z6V5UJ%=yO_l{=*vMRzR%@9%tbd6-NCY2_hO7B?241_DQB6hG(4?T8rMe*{q0c$DKwm0v#hm9!Om#u;2+tE*BEfsJNATM-rR zh8#JnUTs{tnBr@$@BRu0*zlyhLVHLXR_AZlZ|1C|&H+TcPgJ>)7dbtuCsb_xRR_kh zr|YS^Pk?-7Mo`84PZp-aK7?1^)UUOY8MI`rCQ-26T|7XQeYGp#r5)B%y=G6{&S62{q%Pb9+h6l+1NP0+|BApP6&oCkllY5DoNfv@sc>7 z{=Is|59x?A;vHdYdLNKFCgb!lhLs#ri`!=Y?x#!zao|f81OAK;vTNd&im{iUUcz^D+W9{RZ)vNm^QAMMbu1 zCgRT%@=|Y_ON4)156TR4GGA=S>V}dHNO)4Xt0wLDY$aHse|@Sj8B*=+pB=bf;Gp7w zd0E&clymDf(3y!Y`Lle9K}a(TdtPS1^Xn-r2=seeCt-eTEPIU)Tsr+3EMJ~?^Fu3c zK9NCCc|O3Pg3<()h#dGO9UG8a2>S*^;q&f8kq0Y(g<%vz=B6v)dew*o)?K}yxI0WU zlvG7sUIL$HQF|16%-eEgMM+^|Ye7lg6k*TZur2qr<9$TlULwWn8NY{kn5Wvs^SP0X z&DyWlieB3{7E@&!(=LC-<$xi0fwZ_@-G9Lsu#NE2(_GV8p&IWOTiW=Ia)0nUAKjZ8 z7y?i(MJCw!`gh+gsbEn*oLVIJvZl+p$DL_3I(M4kVw8vJC?) z4QQI2ZyMpF$(&!2uHu`WJrPc7J=Ykm&eLdvt?KP6yV8pxPb=h3Nsceob5wPtDtm(a zVF%?%0|HY&LxUb>VfJrhU@%4lS;{-ezLo)B9%=fw?7R+bHrL`RJbxGIl<@BN^_ge9 zsBO1eF~zCuT-G~HW7Oe}EWF`(xspK3*}XRT$3`=$zM}LhP^2z$@Ec|NU`yb#!P4=X zI#1S7)cw<9J^~2ddz_t|$+}S7;(VP)#PmGpzN#rd#d#xW^UL-OA>P(h=Y6OI&ClTe zjR3E0o!{cS7^A{hY!LV+goaC>6NXnXxl8Ulya>3ZIz=F%@I`-x9$p^mQT=W(scOokTG@y^-vroy&UBpCP z=syzw2bR{n(iWL^xSOJudCiD39_|}y&c_0o zbGGRfN5D|C9u{wuV+l@ASkdT;8Tao_}W^B4xVXI(^U$k-ofFoD*L+I6W30$jUfW z+%NHcQ>=Na^BaS_nYUTnPtZM9RD|>zF`NruBBrHXf2-6b;w6-bY0LYDy$2%18&d%m zUkt<{4(kn@4YGwi2F6)Lur+Admn%3I;zN;Po@E~Skg$3eoW}GlphvFfmABb3wPwm5 zq2^*gKJR~^FnxA1HHLou`MFIkcfulk54(=%u?3I?6#TVXl$>*~n$Q9A zu){!eszdlAXJWh{^#{x?KG)FK8@5lbs+{!-cTdp;wl<50UzxXwRl~L+ z>i$9k8Bzu!%*j_LYqXx7E^N(P`MSJ5`E{K-Fl&tshYyLf|1w*+;VKaYy}q1O+>x3* zhc;!Zd<%72ku*a|w^pmPV3fbdSIBG~sY_Krc&O7hFGfQXRA%1lh9778+$Tqga2?zw zs`sV;Jr49i+it82N(qu{p)hiLH=t|9Z|b<%v|C81E2%SvTw#UsJ|?k^q4UQyG_68<2E<@AV#gnVF%g_M2>GgPQ`8K2KUrpc{zHA zt+GN>nblAImBE^?Cf1xxldK~xPUGhxb+QEuQLA@)Tr+ezo~->LyU6>*!cNu#nQv3K zZlE3GxvM7#YuM4e3rZ-A4hk)|zp$(z{JiN-r7&ol9|i=!LkuiF4qM_rMUZziv^#Mi zEyVG=#X<9H*a{?*89lqug|7yybW0MI+47ubR-d33aZ^4Bb zEN(9}-EBGr!&_@mT9OC)`w(=_4LsmCU#15RBT9)I3FC!)!Fva_!p*OYO7=*N_gqra z-5z>-7s|uprwYYOxV<>mFj{iddYT(6`c%K3gx2#7ugF(PXa1{k2BpLA>s3|t)JOtP zgTt%#Bx&*=C?0R^kaU1P#Qm4Sm?Qn7uks?V?b7e?eKzYs-VJ&ywkPc>lBUMS zCUN{g&pNJ4*8<$m*>K|v@}3#9lD5g|^Z!t*S(70gl}iwxft7vIjV`@qhewej40p-< zob46EEp?lYogQbl#qK0iwuf^RuHx|8?zlHC;ccd`<%YYU#akf{d74tp*jh3!xk=MN zrs&;Q`!O`EbJ-z%{X8&1?mUzJo4kK&pkaIK;`(cd>Hs&nLUg%f;Ta@jn;Sz@EwL~- zvXgMqRj@~aVE2G%!Mtf5&W0xhHYm20(AEQ%jZ_pLg4&_@IO;Q7hjEjRi z$nUd8a9&TCQs&w2xju)J#pZQ87aCdR-<0E2aI9;Vj$K8F4;&+5ljVj~|IzJZj?EKv zVlxonza?c5E*mcv44IQ{WEmcTIv+5I0R4s_&cbJ>)rclF>FS3;GW>4@8BG7~u!T{D z6W5NCv9?HQRH1Z+k}037I~4kRx~1bV_6F%p!_zMDc@_})-r(Nd1Uu=uRzYkRw&S_Z z?;X7XYBGJp$yO^hBR9Okns#t8l$nqx(BWaHN@~Oi6@!ItEenU{(`q|ZR>qtWD&`a( z$4*z<(n~cs1$sZLs2ow$dyDajCNuHTEhp$H|MaJf@QIdo`pC>Rg1 z^`7M9y>5H3*Y)x%tNO3MdVx7Wwv~#=($AgfJ?InKo<7h|o;N1r1iTJC*quVncyphF zTNcTk%2|X_Sm(~5WtJI6PQb{h%?o-_>k zX?>5E?Db~dhw9Z8QS*;;=*K#I!=7_Afig(*UJJCi>rc`I{VV%5syumF!;>ZsQ=4`= zC9?1}VvxuAU-yR)24EextKx(xbBHzs8T0nL)*L zp4lWB*XNrL&XX3TxyKMDFB^i=ofjM2jlpx@K2pY4IF`mFxK>4~sMu zWerFotdZn8-&>ll@a|2PPyN`~sjJf#C68yV`wy%2uA1H-twZ!}orW9m{=?mmC-Hxa zE3iMG}#8OzeIQooIytdP(oju*qg1Xk|Yro5ygJ-US zp$B~qgs~FU#VET4L81yZ+8B;!KnnY=L2RDInoKSt&e_P1+X4sWaHTmO_X1uZ5>*U^ zBNuG$NPLTBCAX4?JrCqvFngf~_Dk+T!CXy3d7P&x%|}#g>MrhUc^R$+GX@3KxjtN$ zA%QpiIR|xg=S`J*tM6)Qk77p7Z9cXrK?@y_8u>S0?Zs$mXwe2XpTK)bP{S)T=4P&m_;x9ZTr#rQB)2(|w!tHm+k!AU<{y z-cii|nGqm(gXh!jLyowUQj@=(JswsBhCHzT-XFL&WkjBc*W#n18MfCZfF&i_o;SNL z&}?S|1g8yb0{8BGGk__mgC6>Ptkl&3z%H)7nWKiP_$dQ#tBOqxQESMod&q;}l?;Te zj)LE7>)HOvqi!*ZqfOuE^_#yUA-ll=k=mnm?XA)AKrKFI3i5x3&c&ap|BvI9O669m zl$c*BD)-#k=t^>{luOu1Uvs~Wn9Ej#BvdN*Npi_;YVKysJ(q2{=Qj5Z!!|S9nECk^ z&f{F(=kt0$U(cNQw?dsir&&wKiBZx1D>LY#Gc|Fm)Yg-l?3N|!Dd7rINP7F%@<)O6J8^*BqXz1cBbnC4T42rp96##YRauezP>+p+O62-*~jn(b_Wn~ zZiHm@k?w45&N0{RK&SSg~0t=3{(G;Fm#MBy%tH`OB_n~md)wD}k zXSnG`AK2ZAUq=q;67M;l!Se`{$p8&c5p%=1x6d5M<>OvNHUKfAM*16zIrE*1vMNR-__v)j+F3 zwHNEVu0;|n!`V~}Ko?W<>3l=)_tbl`7Q){lJu#Gj)2=z5uR~A4n%Z*R)&bs|C8q8C zi~8wO$95ZSU=WhIkvF`M*)6hliQrWWW}aBTkbRXh+PO6if97#B%$&OY=D#Ttf)~7b zi3Hkd;~&BTl4a%IDh;$=%4PAIwbrw#Yx;fl5Wm^3G0XDG-N!kJrC{68X&&5oA#QkA z_aW#`mayHQ6l`LE?z>`J{AG^d|m}Y*}(j`D^F8;>2YB&K>n zLQbjJsnmxA40Lo2EW6vMZr%y~Ch42K!^9_y)T@PcL`_>it*{$=Z}0BR6wCq``gOrg z79!NA+;NB{!k_w95&h%Un8W3mEjT7-F*H0bOrCpV;r=!;`vo)~p%bwaR|W&!;2uIK z?8O51(%bT*xw~mxGhIpf+IwQbp<%c530r3d7FXSEy`!d8;X6eEsmTqO$u(^SG|60*`@7`+Jc%XN<+z6k z2MgvRhj%S$&$%HsyWPLAiI5EF7cbvzuC>MQgU+ zKWK~yN_?ck)AR`yaNpm6G`xuFj3UOg!UEMP&nRPbFhGmrF-tt}A)#TF$pkbJt0mJL zPGIk%>m^8`CI0)Vi!z5`se?N`2X&{ho_)b^Cv{7~_vufXFf{Mi9^ZS0s+%YrkT|vT zwAQ@_kLS@PIHfwB%#uD2r#b}Yf5Yca>;7kZUG1dvd%0HAC-OyM;QxFZGmu(Du=RWA{H;Pw0CueRS2(Y6HK{RSlXFk+anY^8id*V#D3I_rs1 zW4z)Szcbk{^7Lth(5#5Zuxj1CRo(I|*RMs}1fI_}Wq44ZI6s{-BUz+4(=nA!%EMP*mQsMltaObh9|ze`4&2`hNP$4Rg3zscF8@)O*cln0hwl80D{ z`f?Iq@~iu9Gm?U@0t)HD$21eOp0V2l{#1rD314?SmrqB=%dFvW8iCfMA;)7{}^Q zZY8^15lB`4jOy;0jWFsfg_+H3qMo2)(a%AP7hYNp{o7P_?hg&54<*%!2A(WR4xNws z7Py*`eW$3f=l2nA32oiUvsS%0BhdYFvD=~xWhp&=45g%1tZ#=*6c$wb&0NxSADT8^ zv-M5HzfW08Bwn65{}sPBF#ozdb7UZ=K`vN=e761pQjctz(hFrdGu{v-PU!|F<^$CP zr^rIMaGtqyf`|t+Sp1mCTyA;Hrl?l>FP=aS@VR2i2?PoR9$*~~?fuf=P|*gT6J?YF z6$8G({er5)ey7o3lMzvV{Et8duO~Do<7haSvQuK11H#`8(kE~2YJ^ak!)XKCzfQ`TxpwXIqhn&ySFedZe{(C<!VUyr)W=-dZbE_x9G-6 z=WzWIfo^-#;87Fxh#O9AdCtIVQyLQA!D`gB_4*%|!>l~sxFbfr-A#TMZAlF22Ag1l zbJAY1+AKq(EC)VY`}>SEm^D(+7N-=dB^1W!+b;ZkucN@TfQ`? znno>CMEb?2NmCnMMykYfihp#g$aUcngVkGKrB;U=^6>P}yLM|MrtVgF*wH}#a+CoU zW*^9~yh6BjYak2ud0+Dqyyiz~?WY{lin|8fOCVB9?CXh$W$C(K{)U z3pVXDGs3-z&3Tap&f7tlA$pYKc4oSY&rNDP$z}8=-bgC>b(-;q?APYgKilmXzWvX6 zatkKl8}@eyH$q2X)9AnJNJ9UFYTYWkU)pstkMkHicc{E9ia9p=cYQL z3)>qAS}`V7i( zr8VLA(b?@Mn$@}RCt)=K#ang(73<}KM|$y_aTxpS@Ee5YZHaisLVBYIIx%*+m2{}J zn3WxJPA)jr}0Z<=p9WpL)4E;WsFqf>-@9h&wN|cQ~0`-XObv$K%AGNvhr8*) zzSyp<^Gjh`zFY0^E^}b|h9%&E_W?lLq2kYNAjG4yZ-~rxm%D6nbWBDz@$NTQMq5ez zqVLv4I2x-9eCz#NaeLJN^5OM214`UBewIVdGALri=YjT*bdTLPiF&&n@e(N){NP_~ zB5-pnwPTewh*-Fqp0yS?9v(WICT)dSHyn9m(!bEUv~Cz)+jy{%Su?vu$kyGRifG>- zE^ZE$We73vEzus>{eF+LCM`w8C@q9yZnQmP4h#DCK3%P+okuEMe{PZie)>@p==$*B zYpgfD?Lo;gI|o}6wYNUcTQwyc9yINl)cWFw8VC;jQ%P1DV{vWJ#4EGVhu&{qY5gy3 z7=|CmEe-K`?HFrbChCakeALW)fueQ+OW7j=dmuFLKM>Nkz+*3 zcF;`7V90Pzi1#qc{u}kyZk*uq)8+oI4_-1+#gtcqFejQXeUr^7UOs6L8{k@V0fYaB zud7%^=4B{<;QqJMvZ~hA_#VS3-w@dn@s~jh<-{GXcf&{CWTa(Kj0wC|_0I-Fu$;Xb zIfV^Nu;R{BtpiXXLobtAKVMAz{Q}hu9UH-|(%5tBBFmPs=(P-0pBB7JAzdTE4m$(X ztx8Km;8A|j5u*U-Zl0m5nSN&WQP`)eJ0 zu9In7<}oEjan|dM{X%oJ=4Q!>)a-$rr8C*0LO!4Ei9PW`)3KFCkT252>}z9%6YE2+ zY}2>0c2(QPd60Am!bpy*=97s-L~)%5w8lI_A9Rc2NDOMCC{=Ojf;%wBGBC#>vU#rxzK;UEZLl zi!tvt4olUtv7^OX&lcn`ubqkjr|ki|c?fEGTO#8mq7ees_+u7q5RNmLod5@VE<mWRv#9S@L;ez8Oz5?i(otS)wR1|UpIg!_D0mb80I%&S#D0KHDp(#fwP>TvKA|s)Ukw>Z1Nz! znqxn*t9K{$8#&ZN1oWv*C4Y|1H~Tr&!~qaf9T}`qAy>aGV|Z5I95gQB2Q%<005MZp{mVUK)wi ztvib^e4&0@qBbG78oiXT1?@G`Xk2P(yNS6v^b%XX*`)ttOTET#q-wV~%x{Mg?!s{P zI$ZxBY2MS|m%TqEbAO0OT`4Bodvc)Mp*8F}SGq_E*Z-S9n6n(04?KvRL*VsyrZ8{A zo~+3XMLO^7BLbuU8}dhrZ+^;+JmY-o@HDd7ZcfoIl@+l7kG;D1Gg6+>)dyFQifvTy z6c;WUo*o@adx>mC0zoCLbIfmg`;p-z)}jNZx=*BcX^({a{vbdl=UDihDROIvcK#8G z|6bq`rtAvZ2sQr;>s&Z1xeN5hI@omV_`6$*nTDq02A%mVL2)3#s$V{i_E+RT;!o_$ zR=a_IEb~+o}C`y!Y=WD)7$zN zUGuhHNKX^IPvDO|Mvwj1+WOqL8$A-++I*FH4vi67EXF|hwiic56-`1+ZgS>F*6w!_V(t17Fdg3TSXtT&P?CC5|52S_;D9xi%<}+sY4f~F43mME5d!6K86ZachK?cUqeFxgq$>vy` z^v8I5-zK}aa`U)g>Zwi7T+~cWRObScQ4u&#{P_h*;2xKpc8{dr>WkXwa`1NlpRuBJ zqV}!)P;i;|>-K>3+@+yjA($>ml9Wh=SSM>fW?${QI7r7X5&!%{+G`$Psn21N;U3c$ z5eGTngvrWxwsSV=V9$B%iZg!sIh(U`y^Oq`c8G<)g#E4=%iEg2i9Kj7p0g&)3o1O& z>)o**=YoDXSyUGzeb7XWS{4$L0?;n0vyeYC6>z`^n(&ah z>U9Z_MWwuxg-(@?8L{4PvVVT*O!0yw*6s>e#cQ(e_Ic9IckH>K#4oXbJ)HvVna`l7OzQm*H2p9DcYphG&B2}#Xb z9L1*ajrNYD29=g4l|OO4{bfEu{|A{qjdhH?vQo}@z~>YR=Fy6jKX;ei0H&zR4R1o_ zjrs`e&{7CTf;g{%a3^G(bvmvZ&-j8(By?vycQ+I(Ba~QsUryXX1 zMHTGy5+^FRbeQzUBBSZ^b&A>ZQi5 zDR*WRaAF6Isv=QfUhlaZrvI(ZPVudFt&~3ca|>pKxScCt0Me-`9p{Q58yYC<%h}P% zPP@57hQ7O4@0v(W^D1P7B|2EU`ir)=!l50CW^;46Rp44xD58C2VRZK7Q1i1)uq^5s z^i-xupbO)1r%>YM{LFkbZce00Ii!HwIzpm0Jb88!m+Vh26NBF+QmDHY!-m%M>KPF8 zjh+SYwBP|+kyIEyD*af~(ENbArlX0PytA01+u`D|oZS`9PWNiCp0>DAKUs>(fO`Fh zJ-jvwzqIT{Wld*7KBfCh%vtrW7fLaS17JpfXq9%*eBFj9&l0zA?n%}Fo)JCC3$`h6 zaL`-^3(g`CfosKsrCwSfXF7>ho3c>ghnjl40In7yd`|YE&mGNXPOmr`$dlbVS6unm z5Xrfpgzu+_CsTj8GRrB^nHc3bRwhFpkS*ip+!CT@X2IR4Bo<^=$7m)_bYkT`q_@Tbn3u zkB5J@S?u6~HTP}w&V=wLiGEYH7LB{x3d>~{e8aNX^Q|_0h^6ANx>cQyfjt0R#{>;PR;kA~o!h*Zu-s}Z2gHAn9FyVoKgM8XOQQV(-kS*sOR-norr z?5zB>hEY^Ham52Az2llw>!>U<1WM?vY&w@>dN8f4bT~iro=U#jXLnO-pD`iP8ukFv z-xt`*wf^VTHNC$+1@RR+hHdgwAU$3h2|7XlXnzIV?6MpduDvU)D&RVmV!y2gtETfL zc4~}k<(^p8>4gguUI~hX9VK3d{4UDp9Lpun&Ez1iYuNbuHu+}q^S;zf5$@QCto>C} zxe5GUfD3c-zO(br_@QCnDNh0SGa<&5JB3+zt%h4RsRVO zVEi0i@&bYy^qyn>1p*`EjirYzKKc!}J$DvX`E1O1-pV1rsl1*^V4G}S)WpbrGrM090%2B_JFto0sXUrGK_SWb?AvQU))q@@*7V94MH zVTb8kF<%sMI;u_g0qy!ex>uCpH!2U&D<+CM-iL--iq*O4ZPoea}@PFAuf)hwEUkct4jN zgGIsuE>%3+!AgZ+5wrpVYqrMbx@YvH8_xT6SXc=3fOn`QkKNrJ*LIt;X3nHi{4?Ok z;r@8{#9dAV@5Y8KvzuXD{$;yegSnyl7vZS`!J+fkEXl0O?)-Y3;=S^(XL zP6`dG`2nv9KLIk$7MC~z7A|ZbS(4MHK_bcKS|{oCaD4Ux{jsO`|G?~7>=pY! zTASXs8TgbTf%7tp;Pp)mxu;iFn}EMpOf;;Quih_r=pAqCg|Ts_3aKExmw(Afc;_LI zR&`3c=gZuzTCxPCQI$iN9iWB%>5bCVP3)ww95}+lbMV@rTKnx31XFDD2A?Sd$vP$Q<8)%gy!OmYt8+TMxyMQ<+i-kIY-hd3LD7_oBQDyJ1~}&rZ{I?1zKcXG zIz?t*6TDW41gp!dT_GR9GZN=rp|7`c+;3*4bW$VT(HoO=@%x$&#tmBu8NL+LjhOMk zh%73mO*$NC1p(WlGc`G*ZTH8{${+%VU-K?v_v_sVyS4K_|Jg3az^0^MjP1MBJX5E^ zQrLyTGo=SHU8`HeixZ)25!m|6V&+m_q)8Znd^%gQVgTMVUdv&jH`$Yc?P7sF+5aOO z{+rH3ux~aeZaL*VY_|yrSZ@?K!in{AK{$jda|~rO)q2`p=uJ+TkhTaRaQq=J6XYK? zz!$BHkYRCHf))SF)dhXlJ_`4y7u#}tcS=`P4a=^z4S28lgptJP59;a}Zgh}^UQ%m` zUtfcDXw%4oKE;D-%z;@WcynM?_#6lZqxPC_hcS{g^{sjgU&_s&1p76J$YFr|*?|39 z>TUPEZ~4y^U_z2Ro~)9xIx{9gHcU%!XCOb;Avp09@;8(()=tR`=Qj)~sitlT_Mp+o#RHBs8iJ?8p67v5FcL3Dz{|;Xa6yw^#`TjFg^JW<307qTwUa8G=Ii>vN!bbD7Mupi* zaD|A#L`~4O)4u^X6l6-v+V(Z-<~X_KW|-cainyrP4Pqf#_aH`BNT*TvS4FIuA7l-# zA@gy{0<)0#@Z5@vMg56Ol|-Mwl)At%j^qzdU4QSz=A`imA4tsTdJx<=;u6I7{obLd zk9diL@3IWF&flP9OJ;5E!$%JCM9v^kFI=hjHFUl+NR4q#Oh&FV|AJAd=7;!#-Rb+i zk7mv-ICL7$=%b`oqOe<$HAM2f{!?|HSw;F$#TMaZo{@Sjs4IHA zv2*Kv%o}6W@N%F~_=n8a(T8+T?;Y6E+#dbVSt|9}J<*gY8er~))Kqm6MmYNE2;Ie_ zFz*NZyrSt6_s83G=RDW4A=q{`=-d2(^F^B@5Vz!O`237CN|4WWW%_~S^xSBxd;sOB z{nZEvIx&No^`BhkljWRJ+J@Z=TI8?r2Z%`}zYnC_D_>vDjdHcy!|Hx-y(q8q3rTe- z48Dc=VU;`_OC8rf`_zbu+qgFH(BmK35M986CTFY2bl29KJ=3vzsoUKUSCGy7fqtuY zQ|z}8iF9ACyU=PHHm@)` zgN%}<3p*rIUWO@}Uw-j6pE&ZDzUCu^dk~&zKaUTr+!H1$556I0PlJl|{WTrP2=7}Y zG`3age`;F@!F|~0DWhVzEuR|hGFhtq4xM+mKX>Z-73aVngy(JkC@Slm2O~jy1BwY7 zW7*e2WDd}URBf%r`JJu&3Sc9vXt%L5JBE`vT2kLT9AqnOeNN@EgcM;^|CDo98+flB3G$QzI{QRA$ILXuIZOO<(seM;D z_jUpqb#)RVJ{t4J--u=3?#zZB^X; z)h_x$$C*ENt52+J$hYlL$$4On0g{DiRF!%iS!8>qsoAUQ0@yI}Sn~AWn+qxRpr6)_ zo0jgSMY49WJsL5Io$c@$A|x#<@X6jlW{R}VE|ly)1^$G+IrmYXVH0@*tD|SD-z#WN znG+AJ-71@w#{J3VEKe9WWY&ZAd|+W*|0ZFQWJ*EWbnVjIfRvb2x4zMok3~J{oQ`f4 ziJSY-Q=Q(8X!dW(56eiEWWj~nOhLNDv+rw}WyV=o*WPWu&7Z~y#wv-;0TouEe)Zmq zb`~7vzzM#5MGU2Hb@iraUPUuI5#se6by9Hcsf=~L(>#X}G40Jr4+c5?l>Y4$lwCf0 zyjIa@#y(qWehfu`wNJtU2yn`2l@p;7j?{PD^4aWId`3-Yjqg@5|m%ih(+3y z_L}O6a7*x*T27MD^UV|F)6ln$LyCEb*`}9J<7bc!8mfT>vBCV6TP*Y{PMFr)A@O0x znOEgj*5(W}$&r!#EY!v7BA(Q;Ez?fc%JHwwt9TmazV(?GgT`%~w;~m7Y)wy{oe-C=ztO7nYwwe@ebhZ)xO${LQd^Bw`C4Deu z9?-OPRGsp7LR{r0sMb7Vq#H@>*b+}gm=Bl!d!tzGSGH{vx4;>KM%#RLY`0C%K+TAz zD|UvEn?|prvfR+q-x~$LF+SM%=Uvf~k@Wip(D^qIZBhZ)h>6@L~hVqYm8m?%I(94ZX zz}6A(YpHF4gcH$ysI?~~tN=;2o7m?+IFvv8W&SJGw8!Ww^F!fxotP!hvs+(zDgndZ z3xH|x*!NLG20%c2lQc&6gk)KLiu>M~U~SVRl8SSw*=RWZ4c!#^7%a2%isF^-Hna0L zknsd9g8QK6ae<5YcZyy@{9gOVpW+_*zg%;>GcmatKh9D>%eu3v15nqs!&9ABqXR*@ zs56H(%RCFq^ z{W)nyS5$Av#fNy1RV`vfT04LHQS$z!41a+i_e!-+N<4V z)vj4;94Hr_7w~&oJ{_|20~P&nQVsG6cNuXZ@PvO+%4^7h4vNIowYuBZJX8Yd*>%6Z zcTb}J5leSG5tIRkEYz!}6?i(8FQ`!^`PKU_Y_f+R2HqnZqD=h(e7e*B^lz+8pMC+_ za&(o#l}vS-e^-!_L!j8zxAa&Q63-sPMoFTSf_9cO7b_v$*b0wKSr(3*wOsWcMX;}p zVd@@1Dz!lb;G0m^ty;8Qhv_K$srB&A+q-&a$q|w3HmjV92^>dA%n+r6e};ilIqUZS z5;wZd^M&*rpY0%A??!pe{zOI9JAl7!2UCgGr&Cm^21qdf!+ATI)94uaywk;>**(RH zy|MwxmwGFP7mhZM{QW)?S-;C!MInqFjpUIeyUWCufI2Nu7vG(tzUU3NUhl{lE%Lge z$sH_RUQ=W#2SjYiZQvMv-KleJhuDTH{Er@0{C^ZqF)t^B6Q8hr^AVKAv+qF@$o*4S zaE9Zr!LJ8iF#`$wv_@0RY|1(~*^JDy!H3K1h`gZcM+H5ez%(gIWQf&R;kobehe<32 z`X~}$rYdwMScmdQ-d3P-0O{<kns#sn`z4G{9=0 z-PA*=bx6GFJNs)Pzoh9Ov3T9XinP0wU7M+G*@}mF(cRXq=9NfxSXlji+-FjD!nKMl zwP?GsYs@wWpU8E}Ap%c9JgX%8ZqIw6nM1G?7o7$T@uzZE$d0Pig2I8N*6XC>X%+)} z7D7Ar(!d~Nig;r7=+@F5PjT$00L`5DYbvA!`3fob*db$C{yWo|(&6(^l^HPmDic;> zy7(nBcx!21pNudHhVMGUt@Z9^>!hF%a{3U}y!gKbt_t9@PuIp09MmE05Jj>iIx^hnR6%| z@H|SS#S{?2osH5@K~>fmYT*>@ugxQSm!mRjT|+HV;GmzI*13Z;N^fpjwEITt>I+z= znhX{FhiC0u{O}k(7d?4??f$9@fq%(6uyp$VPba!Sj}rq6P{Bflr|aBBG^dr8{$T$R zB^|DM4`t}vG&5kZYdJ!3n3qa~iM~+QWZP8`P%nb2{aYjQ7B_Anu0Ys<cV;!M11=NQ8il`@FI%kXSvt4QxkHqpoKbW99bXzcbs@i z!ea-N?)^<-pnnLqtO78Hy=(i@6Z0SbF9MOb$!-J>DbyW=N8>vUKH0Rve@Y6gpS812 zcCrqAL72L~*0wsW*`YBj^5GgfRx{kl`}8zZr5AH^Ye8 zAADVBu%$A()Ug-yi6#S z-&|51J`JpUp^kgnmkGc2vp=KKofn1*8Z~H6kfy(T=ucz|-z_MPdpm79 z=W&*ve>2|=6cjARujanno{P6p>RvLn7Sz&(6|aUeU1!b=V!U*kKA-=Nn|`8Y{u*HF zIQ{vf#E6*R>q!r9F9WdGj)*(B$J0H5{@EDvv2MkAN%1fBX4Y{!^Zv6Pjphr(Nlp3# zN<=$}GHFWHM31SBB+H_*1xmfn>#MJ0SxieH7Tc}GOPLbSUB!nB1gYGKP4 za28Iw{KMzDPEhZ4#aZv1n^&ZoEBAg9{3QnF=WqPGLuel;BA)c-d4c33;*ft~&AREd z7iJZ5hz{x!yOX~DHly0(Ffca;c6mmwKA7$#k9&o>H2?T5K~I6Lj4NO8(VwM7Y;@W2KmKYyBWZw=BCYB3h_J zh%r-^{Ugt`p) z!`rYqD@h7}G(7w&!EMWV+KW#&Z~yip2iX-edv)P1?g1>8r#09T{*nO-e|$!E_?@yg zNZ@w;>7tCE@&CN7tm~-@lRu<(zocKNUElou*FEFUxE!%zg;*{-_;k(;6X)rK^i1D@ zu!6u#Uzf?N(OLdInj;`<~GHns(Kso8qxl!#Io zQ^jrC(dFyzktG{5_l@9W_|V|E;NDbvc3#J0){=MCizT=9PnnTL(<%sV;v+hV z@O>Kjpmh57l5{FOj_co0g~%lwhlfF(C*<0A9+-#u7de_Yfio2Qq)uV#G|s}}S~*BJ4u>WcU7ZC>N)lhAF@WkLz;c|9CGbn15)jn4Wt`b~ZEKXsv(4ZEWNqvkOEl7_7_CrrIE{IscQS{#IZVa`V9 zPv%lMyXacyQu(O?1GH<<_wd8<1r+shpV1dNx|{b~pVanmBF>84w~!HZYHk|GI;;6Yk6D;0_|(7cV(?59P>gsew|HvQ;o(M*KnoKS7SL<suKap z9=1DXmu0>l8^|N)j5N&Gh4*;yt1ba7cNFwafq(fSaN$)D%mskVCll<#SFO7driAFC z8bI&-_oIt_AmyJXp!}&rP_bN^H#X{VdORt~_)(dT+$-^UtUc(Td-PI%d&mpw8;g-L zN(juTuI`pU=PsxD^7`ZcLp%ic5<{F)kfGluw~NFSl+!w2j&E2kUe!)ZB6HgZFX@Ts ze=OwBjAozHctY!`52id*%eOAK10G1u5nq`&u@~`M7)R6kV-8GZf6*Ibdt2Jd)<RnP^CmD5z!lvq%HjDc9FusHv$ZemT7by1ZB&rC@NMVJJ=d`je!y&7 z+xlpnu3d+WY+#mY((cFP`#lT(y5kHSVyONZ0C^p4B>qL0Qi5og$3?i6BVM#8oT=ecK*|s0@wJ5H-VF; zGLJa@g0?GcY>01CC^Xnw%6KnZp_=UO(OAuWFn9_3J<>4yBlRw6{^|(24c2VuZ}MM} zzvW&D8r2iI15U;m*J_?cFq^OZfd zCsfOQdO6Tm?0*Wscfzl3itC!TJ`P>1&$sz|ETFxTLBa@d>3adqqqI3}ujNZ2Mpk}C z%Qf|W?4YNXN%mK)ub}N`y&`mU9me99jc!i3ov*2@e>ihXZ+}NvXPx_zKmLqZ>KlyU z21;c&^a2Ig_XHFlsovc_qeS=`b*27xRGfd?_}>n~$-nXu_i)IiGBcTjGQy_i`d7e9 zu}%GF1J>&Xk>82*$YWg#Rb{J>Bv(+{i_VKtKXH@t#vd`-T-h4Sy&jdi@E?I|l%Gt< zUsS+yWT7n7z!~`U+&OBB7v<`dj`L!6@5uD|>7THQqjJXxgUUkMSJ62FIk==QRoPMF zccB|hz1UJw`ZzL2= zsd$s5cLI@|6~FN6Cyq_cNLu0_V@bRICc0@lqlE203{xF?mX=2(h@Yemrj?!<37ut$ zA2ss+uJ}oquX)ANyA#X{9T`IGIx%a9*PJ;}Tj!AXA&gG^JnQx?5sHT^M zeY4{Jvmhj4FWXyylF>TmveuQ(o2LP7xY-k}c{E;uWtVK$<&pl2f$X|V#)(Mk!u5Cw zT~&N0{yF%>3VZ-tQ{-rb>@uk)E`D||bkb1Hp3BG(-tbt~jMO1?m&ru5@GLg|F$Qjb+b*V--3AN-I-pc$wbP8YA`IZs^MTcWMf4;I_{hTF6{?b2ysW zF)WGr6EdJ0KnMEPDt2U@e_3ifmqBARyF6!EY)tjp@EWkK$RgrHky(umQKo-!t;c51 zB2qRD;Z>LimfkVvcDvOl=oy7B!=_bzr}oOwo(7tKtbRh z2o&;1pJ?C7`xB2nt5+S$?k*y=dKAV3N}C@KvAw(yB8Z2u$S})!vFuAZjz}f6Dw;U; zE0kLqNGCR4_a6+G4E2x=->X;mFlYSSnRMOxG21*Sq;(bN^3!MU{d3k9f@d9*5>?z7 zf1$QlBSh2Ba2DcJ$jC)=W}9XR*5`*BqCI;ze>eY43wt$m7b~W91GCB8r+yXu;c(Pw zrPuNLaS;7vwl%b6a=AXxn4EGhV#}7@RH_RyeJVTkn)RpLP@omIAJs4QN8$jULADLKt4fzb^w{)93N}hPlxYq_tSkVQqH<=UfVfnTp5fH2baN`8u*oye0)aB zEX0Sj_9k%XMf|~mWxD{YWYR|RpySrSDu}&sK5ocO!Z4V;XL#ot!sfZVOMMZS*80va zjsZVY_Wel;3&36fnM6H_f2$Vm(D=ozV<@zU^BS;$T*Yt}KZgQdgehdda^OW0`Okn* zEltoKMP}rL0?54j*R{=P-^}QI_m*`sK380A0YIo5y$KnrbD#Q+(@R}AS;{z#DhhHx`(Hz!BPf9bR)G+X!+sa>K{+GC?8O>t(8HcoiQdw4MS2&EZfTw^H%7=td8_Lf z#lBDghtT!+i;^$%y z1YGv7w-;B;ct|aqFx+mZ{%B;fhdFPXZ>w1(#m@C}(9pT*NHvfUT|nu|-g}Wo%~m~t zhO%}uhw41skNETn1pi?cV%z(s?KY2@zEW!@Ek^N3bzUBId;Jt-^~9HyB?sA){9C&5 zpy_>F2wwxXlGK$m`?e{@{Ok4{j%kLL8EVki*d~Zx#C<*VYnN~+T~2Tp@&o3w`-Qf4 zIW+Q0Hm!$M1_3&-io=d@mp3kNMmO@z8|vf3?Z&kyb0a;;N@8sWeWw1ls`w(!pq$2h zzb9&}BS^0Y*sMsR1lr_#DFfAX@ocL@X?Q^nwP;U|=Tb{mG-|owzB!;3_BvT&mw#{B zK2is9kXRrFKg`)EH9gh&Cgwpa+^o?e-1P_ zdTq*kQH=T900Xeq5Q>5rJmvo!zBdzdYrq4spf6Y zAquKD#oy1Z=;|LwTI#+`0%>AMLndL8*-^Ujfxn0!U+5ITZ*Hy4NP|G`B#Uaiv9SRj z6&gP`Go4gK5)!sh?lb4GDPoDNQf^z3D_7-a%q@($6>HV&8kV^~IGRdpNSP`F^uzZvI$v|EX>_VM690N2tv0$Z8!+@E`4 zPaqFqJNXx6@C(LgJ`$&pvy%OM9ESo|lXrjp=VHT=wRydn? zu=kYP8CvT(Xg1in{-6tzl_3NU7jr8L;ki_%XYoM zO{U1ofPd&HI42ddhIBVCg|+OfgHrZ;qOM?cM&Bv$#-5$QW&fRnFP^G2a|MBaghLE4 zaeDP>H|idh_8!t4O!3Z#@uQ!`9D!i8w)-YaGYWZ=wR31SkU2NRbi?5NHlfu7I<`JJ zvb0QkSrpOn5KY90u^>JI(V;{f~%bFfL{7ugTPWWpQE>oyqKZ3sysdH-7 zH`sT)SeHPOtA{hjbn^$#Y>F7{NI}^Il?s+bR<%k)<$pyB(;pt>EES=d-t+Mux`!YZ zlkF{Ze@`(xcj)2O=MTCaw4d+VVHaWJ8X2SOY=yOzX(;R60T=eJU2@f;lVftjTtp>n z!)FgWm&S6tCjKDN>`6p-TuhtK1|l8w+)B;o7>h+%wzr>N3&NB+mTQ$b@6~qc@Kh(Fzrx(F9L#OO`mM!n}olh`y$iH@`T%Ru+xpWtQ zvFjUNC|i&l_UN5BMw~h1c5d@>n%2I}p35S3#tp}J{|E$r0!$kn;56EY_OKnY&KR@7ZkRIo~dr$t#LH6H(7Y%K!TgpuK z46F>>JW+p&mGO?$w$!{gb($)BMab{B z!U?ci*WB>4DsnOpGuJb2V5az)N?Z3HI0`ixlwaGs7!nM<;sHee8O?g#9(Na}g#7cQ#;coQqLJ(96Yc{%2 z^$Wrd_67I)hq(A&dH+biNb4o3NQ6{3R!v{cYrgl#%=gH(W12G&Uj=^9h=5~xzZOLi z#v||Sep%pqjnV{No@?rv^0H zgWaEI8xq&JRA|5b)bf`{QuIc~9C>HK0(eqwjTQIyXu#9Sg8ic!Gv;dz&K;sgYxgGO z{wg#`>oG|Zd*Q0|%kRx)K&7xxX%q2B8_w-t<_> z{l>#~%l4yRVH=>OHI?os`n}1Wyhgs8anYAtw^!cOwe<54PxQxJo+CU{4C)}=OI;d2 zrHK6C!=QnUk_Yu2d>4|MCx0H2_Cn@z|0I@d?|0Hi!)?KaICZ^?!0upvg`hzHZ!YdY zTwr6>E7%Yq|7=!aU*-CV+(tJ&e`l!U#bW0@2e=!UPj&Nqt5;e}dSY@NayzxltwUj3 zo8LGBjmwU>E~x5}VSq`h4BW-F`TdyVh!EW>H51{;^;om%YIs2be$ z&0SGdwu*4EV;V7zz3gVMO=Ar%7iR$OOr3)^rEVSZ{3nh%nqoNysGO6_oVz^3ANrnq zXik@OJwd&W@}aXi!^afzCd~8%WqwrVWY<^9z_6zXx?ye=VNURr`ID-hg_ntVB zgUR8AqB(-DDd41#i{sUB#{do1D;lb7@kzL9d3XgsTH$@V*a-vAwME-%r^ieWWQOkX z>1?4s#U($pBi8vX-a-*_ytjo0W)HptqOTe8cy^ATnF)j{b&n_@b8_fs`9*}p=6%Eq zOsw|3s?dq&evr7lm>fXoHaTfp&hN`X**6frr4wI>`7B1T39)zNBpU`=eZ?I96}ZCH zBStZ+o`p3yX$&ebGeX1@2$E#IuYB}9`#wcsiQw-pu*~wk=WBlcf}0Pz0UJ6zb)O>0 zr|q0v^X<9wejLu>&386&xUSxbbUmMrF@+sH)?4ZG!Pt)tH&tI%9#UBJX_{*`r>yk< z9#T_3MHO65&h?sDLCX{W9Iiec_AlVB$ajqt#fH(JoV0nRU(yMmJlNB$o*BC~Iq*F# zn4(6q1l~s|s1h~`C`n}wy)9h+Ryr?9>)l&qhTJIW@t-kh_OA(g@+s&-b@$p1i`!+^VapD?T%lG{Q@_zA?801gkrU$ zysuTGY&lBTpg~B=&S2}Uj8qTx;Ms3!-UxBYcU8Xg(&p)kueyoU&k0=-iuls$+&R^OL*6WU`OdDJi8v1o@-hO$=mk#G^T?%W+Is5Ozf;4_1$ zR}|l}Y>MxYuf&0Hi}&HyoI0pz2FF)j1e~ANXD7gj-tzI$2JsyeO=s(YJyvdq&z`R> zfbAtv_JHbF^&iWyp8I~V>4-(8nW84>E_e;Lj=ljz~t1rRRh|xwZm~XR_DdTa$0zs!hZsK|Ih3gP4@hw!1 zX{b1ip&jxTB;J7{=4OUDb5&L1#IH_oq{dm(#Q?&k-!#~Jt-u`%thDl7;nuysd0U#a zGYQy^r2^kay=6_7Pi;Z}j%*a!<$;T|k|>dS!#qdXWrrrQun6DN(}%HdC-yfy5&dGV zk9S|K-&oOB3uK+0j?pbq#~TWzQ!j9^-bqosu1`cSfnQpL>UVfmlqF8sq{e+o^qpQ>x~ zTOX<;Uz*kN8{ll4x<+$oL&2f)GkzEc%u#M%d()Gbzoc`4pNS2_m|eNKjn2ZhHtiZx z16A!mmu;eQP>D`y$XSvTjZB_*`L*e?x1*L9hySakV>~@n7ky9%!KkfHv)wogQ?Eyd z_-UqGYcxWAcjW1w^+lRo{A9)FXY?p%t#k{ysu=~>Xmu!JZi>)dFz|v4tnD`bee4+@ zHm?uUfWm50Yi_ z$4n|AZej~O@BQ>b1~1Jw$oX*oSjMll4A($>sMY!xqn^sPE303&skn0?yaZpj5HrMn z@0tGOIH}gs#RucMA);p|b#=xv{D6Ewo4};~qkHMRK?rRY>TooK5A^FWPQP^dLCq)R zir_Y}cgTbvs0Swy3Z*@N~p*1D97V*4POEk&1`66`Km z?w(1UJKCzZyf=`YFNSsjdN1($!}7LrzQ9tqyZv8hms^*ZK>WSOw8+VoV(>R$Ma~>$ zO*cVS%z6O+Dlcy0iNoW`n5VhS3&O_elSZ?r(mvP_w=_tn_u5IR=R=oFmLy-Q9e814 z14lkWj+ar3?uD76)7g@^F0eLuZbv}p&ii($xIAju0H06`y`s_i=T(era?k_41oui2 zk^wMM>qKuqtw~WeQSu0pSeBLaDbDu>=2VZQ)?WK+;L4KB645$%2jTq4^RwL>AF$_R zm;12>p{EudtEWl@-Amp)b@&*b#QdF{T1;$pYqn@OfK2cxl!25U44#-Yh&T!!$*;_{b-v7wl0DVGsZCBR&4;xy_7WM7#=G8yNa};)r z2wUcAown7g;fEjiE)1zI%K}gAVYuC)2EJEUE@HcMw)pX4&^Xwr&2{a7hMW4LSAo!S;KzGgIrMz+E>*BF_%{Bx1bbNyE=ya&#Rz0p zfJ-T=MVdAc0o9MmePTY5P=)bxna(+jC+L$)@Uytd>PLug&f{q=2&bQESkzIl0^^^` z-&Vtl6!-qOGygVpdNJ7)?J+b?0e^3Q-kMqfet|qVZVH#+eci7|!D{eiNV}GoS#1MI zK5yngVf^&dlWf#NZV;{G!4Q07>owKYo~dc0h1)5Af!l?Q$>Jg$r7$O;^G^HiKRNg4 zT(I;{yzVig3vCfGXndly&uJ9^RDsUKi8u{!J61@x)P7qSkllg1T?LB-U+O5db?tB- zX&m1X%1CD21I-+d8iZr#9UyknAHw5(tP1j4PX8Bc2+??w0X`J zYZuyfV>@zpbGlVv|5KDNZH>eOO~1fA8do$(*15nf4}FA5e-dF!7uAgM7D@y{mH%G9bdugZR!cGXDu`?lpVOxMGqZ2nSpry9z}hqzCvIYsNy z81c_C`-E;?1#!P?m>Eav^$fk4+j+So#eO-@Y#Y}L^|Z^7%|J&Dv{ZBR)k9eyIZ^VC zkky=iTSA9w+z0BvXW72wqrwk+nqXhCPo-@P;I5fV%PgdqN>MnWBW&DcDT*5&&UW4< z92w=F53}jHt@o1VoTdM1Pkw#zQn)VIL`&A=2UoCxFcnZaARw|kQ$XUcnlYO(7JsNu ziMLQw>FMYw+ql~gNH{M1v5x+0C$MbaHGY%|gr^nz>$KHU?zO4KA_5wMXA9bMs554Z z_d?CrZly@>hcW_&OURlybYeNtA!{8scn~#iG|yjWoTRSRKvMPuvlquEly+==PJ7## z*p?TgW#rwjP4Tn$Lci4M3p5~HE*6YA!1n~J^Xj95hZd@i$UZeFFK&s_-#pK_Nxvxb zdHbBKP9Y;Um3+c=E41HFr21!ZhvndyZD=FG3*J`kuDj9)0fV&p@`mB6{}GvPxIaHt z)J-l2uLxLB>BLmqCNsJH{d4*XoCwx?MslbuSqm#DY_3l*Mn;T;1Vad4xd?X$Nio@k z`c(-Xk65ZP@{#{?DL8izvobJ;s+KJEy3anH~idrA0VUj|^f=itjJVi2E3O%tiw>JO$Rdf%| zkSOi}&OG=ANKK66C*P_K%H4khWBKM=jQpucX{)*)8mT8c7QndYT=TYH`vw%njA8kY z9P?2n=Icmuf?Wabu7OIV31TxSot8s;H+loWS1jaGWs47e4Cc?^(@$;i^jX$gq1Xs7 zQ|UQ$(FT{j8$CQ4r_Xu01_|~Uk&a4iXCdij+yqBHuZN^kU}%FIx2&Qd!oqCKxV=qm zwqi?mC_X>9yi|+zPLZnIY_Rca!z1-$)%{ZEvd#(aBN|{ICDkfHJY?N{>xEZ@^F#Qw zlGt=0v>A3Z{SUlbo}YemPrl-O$w{-)jyI$1qfPqd50Mx&9UFgDYev;K3nY-6?9-F8 zK#G1p+ji8j4c3GSe@pq+cc;gtX{DKI`~sAIzG1x@r^P)RhZ14cP);^(y-W<7%j-8f zs<2}D)ot!|-Pl56V9*ux7o?rq(}SvN|DN98&$*L5IT=N%Eg|x1M}tf=UElZXu37ub zY~CyQwZQcbT7ArD0G}H9PpF4P6z(?ux-ZJlpl;s%OOAggfAF`SS)}nj@3U2)>4+-e zkeMV*9MN4g#<$VCsnmz?`|I%?*$N8SgC}ZqBxz=MY)jRL3i~#ns5w?mRbG>L5FZ!U zXX}pMXauIDP{xPfx+C=sz-0y!mimRlO%lZ1Yw8xH8nFBI-GugNz2LJ7T+gZ5PxB{h z53ROln*e6TK7!*|bZ{jyHYy_#7w9?l$b6Z7; z=93n4g$Tmz$@I;Ckk>R`bDcqq9rDo7x#dgs=jmCYw&=4MZspK9@crc>L`Psu+oaCW zvW4BBrl#QVJE3lqw>pG`6%DyB?GXPN2qCw?!%-6#&+1m)^je(K7u`FMTsY;IM)Chu zTHtTi==mP=syoAs>l`y^4_5>SUi%cJ`(v3g+)__}*tHZMR^2R=G8qk>Le?e}hKhf^xY5P{8FW9K~zj zD(r&3?48t$+FdY09BK(a#zRjZacSLv4!E*U?%dmvIZI&1sO?jhe5C_@ofgPCJHX1Pdt1Hqn+zz_@sF?m6>&%ZrNP0$y>hg^tdpmdMItHzTs}5 zE^U*O$kV@di}wQvtxltn>Byc@ef8~gsODD&Ub~C1vOpP1?NT>$nh{uig?%WYzi!A3 zC`w&43kT5)ZSLdh!_CQhlhM?6{%(=!Z@ODCo$q9|@76!!9CLuDVRTx;E4kmwANhH< zKpB^pXFH;zG9yqCF@b9e+-QWd=~5Ln&wMW3=WROG>|6Kp*j#jk<8Rza_tR|lFr2FH zGrnH+$mnkbHvtpHWX`Bd=B7!?f6WH^>}_^|{^+flyb_|0X4p>3(vnglMZUGAoO+=5 zpH@sS(rV+Vj7V_t2xp+$*|C?UqlcO$teWp_;}*%9-f?0m0M(+&a8qQzOqSoQyO2{n zYvHj1r~#B6z?@a_7E0fvG7{~4A{MPRsvaUP;8UhbLAT%Yhs{U^-HZ1viMFdnlr&** zS7GkqSUm!Dx%-S1n>>`{&Q%sc!yoOO?s=hoE>P8*yJuku=zJY=Qv3+11U*V56V^o4 zjAuIPn>!e1A&_e_k!Sy4U5htJ8#fk(=D!Rke+P)hF^CnF1T6mNQHE+*3M3|+wO6+KlbJ2Y3-?mEit|b4|4pu8&`d52cz|}IFd~Z}{ zBs9h?BlBBFpB}D$Hd{dcDz)E##t^!QN-SOcW6k;z(;f>+baCsg;K*2I^{0!`q|Y$_ zYt!PqIEZhOfT-lgFvLZjGyC&{=4gZgv$=PD)Zajdc+%)TDmA^{#gs4=D_Rbc)Wiu- z7<>%tu-R82sdWU_cn8ipw2<%UC(ms@eSg(iI(etn%oW)3_$BIz?jKTI^u{mnT(}X& zWRjcO=`f9k9|1=?Ypk5-8F4&@U7R0hBx<{x6`!6w?z4AkMfBLbXyCPeD4Z9bP4QM1 zS=}6PD89!yX0%#l9}-KmqoLRkO6k%Kh^i{uJ8HsKHOv&GEPTD#RrzhPyC_aXIePke zalQq;a`%{RnoqvBmXs|qw#LxeOIF*0y0skk-6qaJAg{`hB#k@*nng4t)TPv3Gc-2^ zCDX>=wYNGoN4(?1CnT3zL-BZiC&tI7i}cqa3Zvb}tDjPD*sf3%bd9ME55~j1B7mCL z8Z6D;iMu2mA?7wb(2!q~;s2UTt{C)RmDcq)+9dVq`+ib)Vl}BY@%8G{cax8g3?{xS zi#C|`53Ensa90;UHDX_HjTonJv~7)v{myU~D!*2tG0y2%zce`fH!E&ijmmHMU7>m7 zr!r&^i3ogI0i9wm6;`2^>K)(P+zJ0XautNC=RVnxv@=-|H7laYZgqQfmBlO8g;e%> z;liI-9RLWTTx_lKkJ(gXog$b7ba-7zs}{yw7SUD*w0Wqzo)%b3y4T5Qz0u|In~Ls z@k`)jNt?A<>gW5Y$P+F0Rg zey*utffb-ZuUaSHP14JtPYoJjCxX=ooV2;U%~zdzjt#XQYpw9=e!^LV?4~4h7Te<= zh{p?KK8YA;DWPl1{)T9?Q{3i5UY7k}_ymZqKt1&obSB0%ZGHRMIi*d@ElbPye2>Le z;LKI}9(CTSzJh#;ITWZv17R;*i?dFnbi^@ppIxmuh5Reo);~M7f70{HNMS^eVem1u z1Y_soelS!4s&4mV`sCB1vC_~q_EUuL>MhxJ(Um&HuA#Dz=i_mv*6%8o;NV2Ysq-$= zvgov$3rGXp>UP=-&!m0ku7**hj~$K9ALX=W!Hw1(B6c3<)^pr5ynbxQob`*YRx|f+ zXI)~eSQkD_?lM)-54Y&KTG@fXNGs)a@@exuS^3f=whRbVGCRIH%eG6B zJjS~(@KBG#{t`9phuM_pirWt(fTHoHun#R(cYzkn#!DPMc235amsR7@mM;EHb;vXS z*8~=dmubWtgSypks)yO{=UUQr7kSwZ;pgytctFR%Yqw9FJ|95B6Q?IB)GjDo)Gu?# zCgUIBCS;5G!2D7Rq>xE}|HGhBqx7#MQAj!2=jXl5LOFxQ!TCG(0gnSwkk>6n!(m@X zPL39v1%kZB;fHNmKg?u|{`lYw9ns=zCU-*f)4Jhm(|Qf*FxN73eGjNo&Cy;P9i8=e z$OXah&roT95+O^(g_S;7;CjqalXnEK22Bw&<<2Oll$ZE8RP z4M%FerlV9Xak>c6Ya{#*;xwdEt6~h!D%{Z;9L+4lF_rSfp1jO*q6}A1752=N=$~#U9uobi{q~H=$=d|?mxu)+3R1dkD#JOvK(d` zD%V8U=Pr=}R@RI?J$^p)ik%pj?phiCmFNWnBy?NE+FEIa0yd98HjWzQIwD?n3P1ngv}5gzL4s0J9oPK?50 zqUUzVtex4xXP)72!aAX;8o!|2~LQiDzFwj~#R#wMdO zQ9C&Vh1S;-iglDJM#LwF!aS>&@Y4$UVglM~w3#>S4MJKZ}JIk?>V9 z)z^0oGX{6@WQYcb2gMbT^inJ zC~Xz+4S9v@I)2`dTQ_OG(W9y71nr@`^gaUvhyU{5s=-=XuP_1GE0fezGVTR`BN4n8V?J6@jDhDefM(40pzne4{gX z(>rjoJFCCBZ~B+bCB5=ps9UA86n!d9>UK+0x8AKZ^xneU#!FgK^*qirtuv49x+wOZ?bGgU~+`YJ(nA*QYhEg2YKpsZBr1Wden!j$3_GjL>HP zmA)fgylZ!^=1;s3HN4+pfgdNT-;Mm$;hI88!=3k#w7xNVGLd2Cdm4$l#%gKhn-&CK zw5!2b`rF{earYEIi}^Wf3+yRZKcD_rKW{{<*mrH_d3biMW&C5Gg3LO2U@Vo+s%R4Q zReUdjY-aXFY?d)5SL9~L9w#my_k&T^n05hb`3h4=ihk~~L9JkrUB(idV zQz|P2_8T0MB7vxdX`4hG1&Q*GBUe%mydfi7+wS!P)kPrHCiWeUlpEOKZgG>-e&WH7 z=7j&zR`amOCL=~SjR!~bI$%@6h2CPG1%^XauSg>(C!auOvXLdTJDGMIGdG*f`(rcx zYriU4!3ueGGRDOSpJziZVR(jnbGXk8_fPLX8`rj9@@P6u{x@Oe7m{r?bS%UGx>gVr z!5_cEtV`{iO9K=q_rrgMmL}hw%IA%T%~v%BlmGRt4jmh=L?5NDq*k@h_(@|lu8eRp z%ah-iZSCk~pnl(^s{$m1Y|N_QvyOW43ljNmd(uE-QqMLj&?*M!+VE!$P7Bp>u+KQ} zEt0t+!!=3UeJ2=Ml~d`7W-suDc_>PXt*pu%}%M_ zv?y7R9Ujy4tor!=KKA?B4^kmr!(lt(xHo|~r>*zm*`({9BPb93x256dLTbN!l3kkV z6(tuuhS7WIeR^nzu_Aj7IXgMhTxC%`Uhuw{jh5tmUDlNy+5-Qu6G6-WF@4{#X^@UX zj*nK*GDj7?jrKLHjr9-Z#V&Ey;UAH$yQ)_`8v@BIY9bm6VPzrDeUa|6RDq42lueZ7?Srvog ztXR@n$Q{y&hU;d{?XhzhtpAUpXP7JX@d^i8SDK*7*86!2>0D}zoJwN%_+Z#7t>=`8 zldGIMfbl-!eMBqL(l)<}jdUZ(n&>;7Jre!^AK;x=hTa)-ML~!fOT%qB%!)vl;&PIo z559LjEZ3S-0^L_Wee2pE$Rq0Dq{F|g1?q3q?0HqMwt3jJk{@MxQWg+d!wOHEPG__A zViM;Phb?Z21w*D}eN`g*Yo-w6T80qx@b-BzH#IW?Iqg9YbiC%hh&h@ z;h5hYeg-P(PZ#!@URhtmqPA~g5`j^(BVS_Fgdit;F{M%=D!3p~_>qV6g@W9Q|nTG_sxl?ctN96}L*mM`T zPe^WFl+LqjyC|##{vF9Gn<#Z=dl}L)m_)$X&OumT{M>Uf`n zomHS~IA_ElwYCKuQG4>eaq<0#g))Xd_a<26B{yR9wt-#Zj097K!$)z>>P0TFcKvhh%(RA7nDka`;^2<{}JO`nT;)W z3r|B{%P51V^q$YMr;juq;Q@y$($R(2C{9%gON!NZ>raLzImqbdN)&{HU!J5@>MW3l z4HEr}EV*axC#Ofvim9f1EwcLkrT&sb;=M&+Ikq%lR#43)c3sW(i5-?$m?%a)fOE{p zwddSPC=&~@wu`FS#Q9Njm^T~GfB~GB!~Yq{8}wPtuT4c3x1Qt*mS#;dQlCkW?<6(Z z@0`WG)0Ie~vdSThcbk{%Z~u(1HTLqTr%x?rMq4tBw|@*57g?4zCZ~}S| z`c99bzV$}Fzs1+#*FNoP>j&m?-f59{=*HoHwPg{NxSs)TA$@f%>_BS1LUJK{Gfj{0 z(O#@UyASwZ`Mz3Ei9BPoRH+orw46R;j+yaZOTh`-VhFoNo9URv7-fwId+kQr4IHFNs+7#fE zb~!ztx*1-w$01fOZ`mAv0+3QVlIQR5d%;YM+hx2gp)+x3GRbx^&iZI~8lcG*)e>1j zs2%`)1Ge8HhYXblNK9soNr&Q>vgvlgz`rKLYrP;g$&bxw)1!Sp#;!-Q4navENF?e_ zo`ul84)*=s)V20D<3YUNqY^2XfWY-ppa#qYWN7VSnq*iH|M{`L*~k%6XH!C-EQ~Ci zg@|t?ZTX<)3|n#r4BQ+zuUNWoOYzbpN}4ojjF=H)4R@tv0(V!JpLb@RJ}?8UH#dvF zYP3Xql)mxzU2t8(4}+VC9^TC=(R4Q>iW3vnr?GR=*zh$BCJTNKDnB4G?PNl=e*hnWKZ2D< z9~gof>q(fWqp4||iuFoi@m;iB?DLPUFzD&9N#<({w@2X9AwhBz_7ZnaI~Grq7Gv{}z(z?=nLMTOy@7KjAGUIEYg>$^!i&*fLmzF_ip z`WKZsq@6qTL!8Uo_mv5xJnF07H?|sT=u!()Rf9LB)ho%E0^JDwSn~@|MzQ~WEr3}U z_J*98F>9ym?B-HCp!(qW6|Mud;;C_X zwY%lt>!r9!SK^@2>IV)2cof5f8whs^$=ZZH??xF)5JxWL$PUaD4O#j|i8${p1*v~-$F?&(+%Qr%9Z$t3kF{NTZO;=O0{ zyhcvY)Rfu#&lGpZmC#Y2c6k~~%FrpucAb5lcw?T4Qxo$^a7haez_i_D4Q{~2Tx&xT z1IL*pkF1wJD`>SlMt*i2cqXY!)8S8(^5(Tlfv+TCvXmJ60rji=BwD| zc1#tEiJk$ML3aWj#5h-l&L&6A_%7h7?!3PHnUH(w6_r#eV_tRlAOWn;34$Fpq`#VlkYENTNpe*n@d z8b1wuJToP>HQ92ALwnT&WseTn@V1pJ)vk~2YS<*lf3aV5E{`N~jAVA&XTZ24 z^}DGK?9a2`gvvm}7U}?nf#FBYd>b zc0lnE3W+R&GrJcB=oJTwcZDE^{Y=ZEM5vNmDXvUKA8Cp`DH}DW7hpS?x$Q<;zSEe) z1V1UWK7w6FMJtMV5|^Cj(h65_lf&a>dOk?T4@zDkjj;S3pGrHfM-b@!nXqYjkg6t9 zVp5J~C*PZjH|tm!keC70psS!lH~kxZl+F?gMxrzQhRe4`kF+$N8eyD=^Q+_sf=UOL zxKcff8_?pz_1!p3$c4!Yq-V7uAcvMEkmi zu!*vn^hvIq_iTZ_QDB0^$pCH4rRjg3JW-DHP>Bfa-{OKiJ@y8fKg3o$Z!iQM6(O_C zsO5^R2dVrHd(Gd82a1+gEu1ggEU}Gi8@=Pk%K?%CAgSWhK7~OH(z1KTOiRI>Z*rAF zURRj=MM?S0Soz~(1$hMItl}9^NV$U)G<08GoZlx$;WdywhRmG$13KKnxNLtPmZ>Z( zf|}RQM=e|?o~`^!?RSAldb)xZ^$yO7E8rsS(-=!X+G}p68Udq+rv&61`1RmGdg!j? zqACf9!PS+U@gqimoJzD@y@eI_Zwr4RF6o9}-8k^BfJzNj6hxBB))ysL_-`?@W)8Fb zb>ytEG0fYUIXwqF@uniHr+PgyXyLs4o=tJ2p0-2mv(wCS9$`DPN}V#N5I_I1b= zYO#)yS%jRyA(?&~!Ctc_KkrnW64FLCbc>OS1CYNhcK#QKi)9h4 zMQ!6F5$o`oy2sxY&;RrXun`kEx>5 zIu@XuCw^X~y~gu0vo7>?h7@;#%TERYE=gytGbM2OApte8wRw9VDMCYV>5h~~G+@N; z1oyqaG(q?k)m3fzoX7nh=WA)YOC7NV_Odepei7V zVGCnp#e`^=IEL*?@TvV*H# zIlt~x>a_|T!{R~Ey z^6K>xe<9VMRT8TZ!mqtBFz?o*`k)*wrupSy4vl3Veph4z8^)teR$w#ZrPfj{wm@9w>Kq4&`yvwVd4 zTbSVeDtYNOMXI2#N0}Y8@y^D~IZ7ApU*Osl8a%5jt(+MzD@-k<9ol{+@Ca=u6YfZf zkw|uox50;o>$~`0BkX=>;{ARs3*!v61_OTh>R~_Iq>=t@e|6q2F7$zNmr;D!$tWvv zYde$|LqO$ohH}E7Az@NA_^6n0T~k%aZ?STs?n^sy8LMcokPl!3;DwB?sM*j>wS92S z5rs}!AE>ftY00{J_WZ414tWl&^yV>+e~+cqZ4tlrBiNs1q*nbWckA7b=|FDvw)PLc z8TznUGRK6rI&zBD5*Vp*hRoAigm>g`jp?b3yJ#I1kNeXV+c2rgD>{eQG^yRYj<8a5$434EDI-CxH_j&dHv?Yf2s1aX?qc4)s*jHBb&CncQLQ=yo|Jj z_8ei#@Q^~O*%7qk+F)c6AFo&Hk4VkK(q6i5sdZV0ZyRUbVGd-H6cL?wYx27?S#@zg z6p$d$pu!WS)!p2UFW9tify&+o=i&PthgjO7Dc3U#WUTQt{M`?dgOp19cn*>p z^}yrc0v-8fSVj%}P`N;@>Z+mMV4>r*3g%WrWfi<|)hET;3@7nQz)1F+%k0@q#kGv= zoYt0uyi`*M`)^0Fm{~aLoA0O5=khUj%iOdM=IY|1P2t*%)Z6=y^_Gu^xoqSz4`syB z*{v@#OoN@r@_!0J--DbAo}K^O75>H?AIcyg61%Isc?hEtcn*>k#vJTh?@bWq+};gE z;E~fAa#%L!*<*yTA(lVO6o=z?cxim0xy0=q4DD(I2*Fp2OQS&g`qG$~24s zt|x2jv)>|n`R*60g{3EK)(2r>KWcP}I<@ySRL9GDU>2>xb zbU|WV1YNiN9Z0qQZ$*UowLMu1z7=HBQ)7a6rjgBXqasn}3(nJGm`--*gX&9u4*^AK z=;?}(5ghT22J7vd!|FY*;JP3!Z~c)#%k;|ziQ;t&;QZ8Tuej7mjRxHpr1}pj2K%2v zQ_a6Bb0vGr6W@1vu#q~QL+Ri1Hg;_aIZf>4MR7dPs@PRHGj$s)ocpM1Lw6iR;Vt^t zYI^k1bS~%|@h-F4k%g}(6GP{0<_**bZ?D~VQUOGwqpcrewch)({8-;gwTj9bLtX`? zDI0u9@n|^J5a&Zp0V@FSji+K95O2Gyc5N!Hfm$AYxa;-z4>UL}HKi2Y;*4GE!7!A{ zXXqJd!dkQaz^;RyuA*lnl|GO?WW9ruSgqw>FO?~{|LM}@thdpHn+8_>7|3Lr074H=sh;KG-Hv| z(FgE0Q))5qJjHoxaAxYZZ0z*gu_1taSc8V0682k&cfGAF3rI^gCniq&(*C z(jWz0uZZxH2zKgSde$!CZR%=jGvz|P%nAHW%^FWlUdm&y(vIY{v^SV}HeD)C4sS9*dkhNPbLtOsg}xmFXhQ=fWXB{5 zY=$#mUWGDR4<_f@Vg!k_s&bdT-_W)M1zUu_Yp-WNHqf}?*@;?pQwg)zumuMM6d(RS zL+AaFWZQ<}%F@bJS#IGg-?Uy+D>WBFWo6}{vfQ&F?nMp|#j-SWy=88M%+#Dz%x5;jgfYJjG6BB$K8eD4?V`q7ch)?UIL8NR(bcD;-$dw{m zMdWs=Ept0Mu=|HHMn-vN*}c}0G6+x7{@c&L^O%v{RD`2a8>@sD!{soUwOJI`Mop)S zUzBfY45gg8B?u5oNmQiB%?@eLbSL^llkP4xPWC48uIsO!5-US*)ck$Cb9%0^Pd12b ztDaJznRhp#_xY%fptlc(6TbdNb=>nbs8W6t(lKQM7-@P3WjSWZ~72!{};m?DSXkGaZ-%MY(& zfr#*-${KDi0vJte{A)LKIa+SZHj5gzj!8{BTe$r=62eyiE_q8`f z>;r_=jxfJ2D(Z%=>7_rYlkl%xkD2FO-uy%`R{7gY+FDZalfYg62R9i9=9BzIzfbq4 zPpA9)ES97fVZB|IC_~+6>m<-p&L8{v@Bjlj9i8rYyOQl)azqHp`w8b*Zf1H+#$?b# zC|$vSmF{M5V#F%k`GK!uR1XN7Pwt5{DhMY^>kU<7)*m(AsX66vWH-<7#l?S}m>|iT zLA@5Uu9Pl~f6NlL&8n7+Bx$-8J4XC(4#PUHIScmQ&)7J+ZUtaJDbcn=t{KXzN~b~y zcSg0@3HAM{g$i|RHuP^L{Sq$`P0x@s*G%evw7WDudG>3&JEHE&*vhh+&k?Ct zs^$A5eo7z^zslaLo!glp3@Qy={Qsl`WLuv+1a*<+as7`z(>I*pu@?3BD;)dk(q5XLYt9&nxR|E zPj) z8e1*@*5|?W^x=g#ith_mOiU~8SL*(_={uo|8Me2z?kg>t$N~{%tPqBj?1PlhAh$YD zRPYxg6}juBk>QJE0(oW?rqxk7^?5(hJ2BN6e{ zlWgvhfv)f?f)8`~Y`o>EE2)eW$yp+*%OuyCb+VF@wNP3BG`%bp_P;}L=eR?BflT)!7azjwxukKwT3Sz_d28{AI%y73T1pvY*yY{2*DdK{5`^>`D&cby{MEkP@ zx%EY_c#-Ey*{RrjHQD%&)^;s28>iEHic=!W z+3C5J&1k4vu(h0Zu9tFX=}avs&-C$}JXq0f3+&H* zdz#d`kM!;bf-lXK%C*r{!|}$0<&y=l_@YHu?1dT&h%{sX@^TO9cWigC!LbSzwdKnj z2~U^^M*8RrJiad~ElIdnkXFg9m@ux$Ka|zQU@SU0wgYpijW=`GyULiH3pa z#?#uHQxfAo0*&>>n7-(Eck@?Ih61WY(GxXarO8_*P4~l>r)6;6a<4=NZD+H3b;o2X z76z{6k~dacW0S0{9W#FDMg7BG+f5zQNMY;dENs6GM9+HlDsU?)${A5^vr@SVfIQQs zYF*<5;7UuAEI8*@0a`*|N@>!;^K)RG-gWep$q%&w0?J~jke*x_v%PjGqEI&M)?xoP z;r$?Zt`nY-SKXAQ%J5=_RBwiiec{TQbktmDf9u)O5q}Ly0^Wz5@_!iVCwmZh6mlww zZfK6O17V*lQ~vJ8TIW|{1Ml~~GNF-LB`VnzWOiZ=>cg2<= zVGohC#GS&JFEc={-|QQLr5)!~n$?AG_?8@(-aA5w^U2+xOZ$s51sy&sQ7o_ZL^~|Romda-r)5Jxs18Lw&0$7dSUFmgQ#mYSi$A|CE5iW!BuL@nDQgI?Z7`Mn>}RJ zGi3c3>z&Ks;>C+rv~0sOyfo20k&li`nA2|Zu=%X}deZvawZMhRZ8NSk=n`hh=~4Dx zMJ={D4Wp76mujM=oW*kp|CdcgaN0!Kr3fo8e~OREcUMLCx%;abDe-f!ViQa+Y0QyG zi+Q8xF75o?)RXSe!FxY%sGeRgpy(~7wKtjjn)Jz=n1 zMSuDlj?eFDx#-#(RiLnRmUxCYHpi}7d=Wa%UuyV|bk?>7`$H0Y!Y44N2~Cx5hEHU+ zh2i3+2cUUcX|_R$>IcKRMj@2!Ii*?2Gz|3 zxT-iyrH1q0vapR2s)h6UM7R^G0yk;te8KST7A9o~b0EY($-BAPmBxs&PexaeBjeR#|s6~3QR(*i~7Q!TCL3i>m;(C(|3 zTz(_1OBW+|?+TC3Y6SdlNCrN_9Z33<7^vgIby`>ek1C%5_`$UYG;lwSW;*M>x@KoM zBxKyYfS7#F;WfJoF9`MafP4r|T?|Y(E|#Rgb6-zc;dy9AD2jToFM{IG)fC5;a(A`)(F=7u2`qAvwY5 z&iIYTYp0|DnIAW~k=Wt};J2}?TUV4G57@!9r#%8usiC@1`AJ?Rq{U?$cF_oW-8sZgM&jk~wk%C2KanIBWA|Yvvhd z`}Ybt%+i0?jcg#w!@4Gt6V#H$xllYeTKlh{$9}A6CP&UtZtDO#NCJsFnXg3c$^^~Z0Ts6EIZ=#55)BG4!PWp_Q&$;ZM^ zVEwU=V6W|G+VeD&E8^yOVbL3xWYalQgQxcZ65y-Z$p*WVt?E$^x9c^i1Bo!EHRYmX zKpM-E=+E`f?sybqRDBl>Zh$W9Y7DWX!s?mjqqHL{wIutB)xoms7%~Z8RiH|)+a8r0 zVQj4XT(wtQR0k7ab6$vjsy!ksgH0R-?#Ou2eEjfD;2 z;|(J)f9_RSo}L{U6^zQDZ2f^y6DWv5i=KQt{NRIK-z5QTa%n|L2%YoFEsI)@^4?E) z&y_RAmb+pvjm=m!Sq~AS0_c)Das(D)c9*$V)tRF(SWY>NtvqRXyCSxBtt3MD?O^ zie0>Z=^`>k_xy74vUB_e4xg|V&keH^VF*3f$<)t2xLz=9tx7t*S6dhVwIVAxP;J*3 zA_+Ma@I}7P*4tYC9gW6+z?hI(xv!TvRuw_^uv$nd5H~WV)#ipj02~<8MjeRgjI5cS zmVuX3tE+u#%OWEyY=z}DS}DIBfD-h!tlkTQh}qHc|K=_Lr|c0`QP?rR-N^rCzS+zx zV!%`7dNlH1m*sLg2;x2{lc)m*(b5v?p}(K@$jO=q%Ii!1OPSO~U=UZh7iMR>mQJ@S z^#8+E^}GPe3crCkA^IYSdo>8b{~aDPLogM*zR&rUbN)J0|A||I3*r{Z+OYY8u?uRu zLicT$)c|G+8te1TqXB1f6z88&o6E@h0_(y3)6O0nJBvNOj*i7^{Hd?zc#g9-m4wRZ=RX;`4Ybn%oTzEZ$n{uOgni~rc)dXi~?LS z@L4BgWLH{zrNEwuTMYbg2ytWz#CT;d20}evcYXP29@>DzUH6R^cX!b->OPf^UpH&w zqRJP8Gxy1Psfk%WOLfzAL5$?kMTB|T_sYfkS&rFBK2lQj5esz4Caxu5DP?k-q{9s) z5F;?wxj~-bitYIAwki<3WwPfc_(e>|A@)cMcq~gfk z^P2v2eaA{tM3K9F&d>)JZ^j&Ao#RsMuQX)n#`Pv?Zv;lZr$9o7PF39QNi_c~lRei6 zi;a6eORx`IPo-DDV?&ajM`AvZQgkLYo7hCpdk%^W<&|p`8v+}-mNb2+tz>tjYc$m1 zakYY~aL2nGwMZ7Q;*?rWTy4*B^_XJ5s%@d?7`eWIUFjc$<8L zs1vrCPIpGu=$zpIr{Y0ka7=E|b%tHB2`)e4byqkWfeN46IGxR#70T4aOQ#N1bT~23 zY-a-FI+6lpHU{1pLd09BgN^o`uv5jRj>8b^wpy;dqGA^YmuypDnD z&QXHA%YWIKOegFVhwu3HMM!BihA}x8AMjkhHZ4UG@_2kgXGqFQFXxpk1?_!B(eI7) zxWXHQi{GS}#T6$6L2I*)jlGaAb~GfTo79~fw12CQi}UIX&2+3xbzw z|KxwzWraTv2ThLgG%ps}Q6s+IK!w&gZrwB^gmr5e>So@J{71U89)H(QU@?`KWhy*A z^$}}2SD3K!!^S1Jq3EpWBU-jXSL)-Qarq0ese}|S8*P8uH|NoONai`fki!p`3Fx!e9xJ?g|0yM)R7zli0)C37)yZ`+LI+6d_4*fWU1L&)o; zEuIINb+>wTlE08om0=%dVwky#XT#-LaNY<&yq=;;)t?I#CJ z#Ovvc$J!d(?S=>Ve3131%8aZD5|jaxeWWD)qyZ>h`CgYFX3{^SAQ$Z@$RCB_m1cRL*|zqb5_6s&FlI2M!p8k~d@fL_6CIVWw+SB#$^ze`q$?X^rf;yF4Z1Jq;S zgZyY1IGbO0OWwgR)Fnd8Rms-%Rk#!$ePv7=;0V=efTERG19IGs!`vh5+v;;2!00b+ zM3Ig?#-i)38Q#kvqKsimRA>HM;3@r$g-rW)CQ4!#A>gHWw9890`?QTFYYRvBY^MY= zM{G)5S{%Gp;ko~@Jhh`KX3Cl?u_g|helA*>6n-JBUo`Y+M>%k}?{AwxrVFv}?)NZ{I8}An{#ZPw}(;Q(c3Ddf0AZZm74LMh)prS8aQ&2{v=da>2o&OcZuZf<^25L zPDXUJU8I~4@Z(5b_h>4d1SHTgcMg)*Zq|j)^)LC&;x93209WmZ3H>G%Uuu5nA{2td zr^w>l;h(pDuBltlLc-mCj+EsAqYwv}5- z{q%ZNZ2d6)1?QzkUV)w9`5~}9a>MPOats)NQS+}dZi)C#iLjAbH`)20;I(a^vOe#i zD^>e0Jfme0$3F-XW8MaTI-Qm8DH{idZ@(AzP;UIy%P*da2z;X(iTDsTHH^y;-oP87 z?F5HxqdWc+pET9E5RL<4Z4H-^%w?}*QLuHgq?7rI8p4(a!2ZiYqZ|mIg06y7$K8^3;=TvX)L^fJiWqU1$G&X`-cvH z#X_L}MMA}=n9)qclL;rq4~kAGn*e%F$l>WfMY`sCBydD!Jrd=@da;Lg9x4nTs^K3V zu=7!aCCqTE_A0NKw4J_qBld0lx4B+UyH$pEYD$jT1HW!{FV_-ueJ!Ma=G`Ow5`MBz zA9$5GG1q$OcZqh_PEl5K&)&oLYsY0Xj0RMBR~s^babj|^g|=%g>u*#pm%!1G_n=Pe z3h715{KZkazKIu5(&IaW>c3lMm2fCPK4Vsc+5dNdIz)oYPKxPR=RT@7!`6dnxr2t* zIx2`;xoK`{M*=vj2(-cJy|!;eU7;iKTy5Yj^DT zS@sDxy^tE?I)sms#Ed?OKReV_5Hr=a7RWldI-r1>eP>+FJ+;OrZI|JDWB+TuH&q~)v&IXRg5yij{e%LOoet(o1Ija4Jx5-oSjsW z^@K#Y2#~azMN-R4)j;cxXGspmv!^G=FuD1zOiris1|(=;*hklCyYYF0`O8W-|4P8} zQ0^eeI@5<8)DsbN%F|64PuzN5*8*R;_}*s}9@QiEvMB><0Riuk3xD({#p;dHm=9aB zDb@77m?|b2kh+MBZPTz15-JZF)^Q zyzA@NnZkJ0Ro626e}nE&)`<(SMQNTuL+5qSMpa)*cr6E9iXSXX5nGz%bRTVjbspiL z+xvIF(Wmh-pcP@a8gH|XSw2g|*xN)@&Q%Z9eAUGz>|CH8Olk5-XesC;-%4pDPJN~Z z?C#DJjo1LHyXblrX;DsQH{7|b+!$G4#_pLn|9ke4cBb4u_1=HWE-|awU-phjT6!1S z0w0r#i8M=X?_8&|-LimB>Bm;01Lg~}c9C@z7USRU25zQxvbhuD){w@Z;pm#6yg)bp zw;ruYYJP4`X(&_}9KN~DpD`Bnenf?C97OGh)a@84M{n^ln;>oZw3MqjH5JV4ZL`_D zLFww%FBh*6nWPpbO5IrcXaXQ>dudr*@iZonvgZ>~8+ggxOe2WZvo91TWaJh9Ztkg_ zevJr=u#MTQq~2Id;-&{}o{)q>R@eOeq(`E1vt8-u3}vx1wU4?CMxA>kV4Ax2CK2@1 z5D&_J?D}S_2NxaseN(|jY-i@$bbOk+TL3ZIVSqiMd4IRL-W%GWEH8)GKpPq-1qfdT zaZvFgn|fq@TsA_AGBGG!W@cLs)nF~pyHFlk#~5ZDvH6?#DYbEPwyinmF~%^+Al>YJ z20#+KeJ_vFRxXb_IZKQb6cZ$TsZCzbzp8?CFe%0@fsRh&7R;rka20N~j^soHF zjP$KR%)cW%a~bP~oXY&oB2u;p)#q*opKn1S0Bw@KdJT2w@p5%TjDAGj0-fG@MG;f) z4GRaRTWCtc4aE215n)pw0eW1!3%^|>Zmu6;Mu#L4nj9yfm||6GX52jSXamIV7Cv_v zJ{3FSv`o}ON+j~@-Gu7agh(pK z_y`;X^e1x}kV50sz`D(Zngr^c?Mq3X?Z7T_I)FB6s6{ryaM9C7J|T6HDj+T9=#?ft zj~7M>y+)gCig-vv5+Zg(8dPfcS#~z=vd&K@Yr%9^)BCCY6)Lhpmf~m4SYQ7*LZ1P1 z)_(bTw#)C9k5I-6o{et%8Iw1MpEY&BLb49?0S3xwNZ)&t&3(G zo#$W7v@KDPz##?nEFR+H(*8C0CFqQQvpdW~yDzwV>C=;irsGUjrU&b{9Qe2drR$6O z+grEe9@;wA4q*Z~7__A4g_tda4zothz3zNM(Ek!UkK>TbDchnms6UGK6k2 z!kvsQP}m=QPV4oRcJo)$vxaqN#O&+p@}~ z_f>f*OVrB1Rh_T=7rCOGP43HTK2lkL}^Sz!S1^NpXxx!VsJ=1rODUZWF!aK zseEpw5!EuP)vX{Wb>EPmH>8{rC;4(Q%BOKIvHCG)d-Z0!EWxvX+0 zcTY@H9j~;#`4Mz@sIqQ#F+SU{$#{uG^s|E%muDl>rJ|uO5bA46toXF}8YQqIWg+K& zz($Gw2cVV83;-m(tpajJx^ZSEDV%t1K$N58=@gKHMDU$@th(r+*jaqkN9T?NSSfJr z?=pOBaxq@B=ES!*;2VPXDNuPD=Cl*$Pf@6DPIy+(!cQ)Y@Mz|wuu3toXZd&~-7^1o zD(m>7yidYh2L{4kY;CL-6?ZgVyiK*YG}WGl2Fo^sJ57brNcF)W)cSKbxc5fd?-61@ zV%nj4PfSc{3gADPu=sYLj3LFDwxg#q%KhNUL6dxq&F-uMMu000cMg18s#h?{wxI|b zpL}U^%2&?M$YEMm=&%RJdeN}L#9?h6nYPpYqwWZYY$T2MeZ9nR!lQEfXPG72R!Z>^ z{qNFepAema_7JR=(_7mj)yyNU9bxx2KV*x9eKUWYwlfSBZRwAlp-PGtoS$dbhuhJm z>P|=g1c?}MhFo%s_XEeXNX`AysSdzhg^Y@S0;bM;PCA~gShB4w#n^i z`UU?a)?&;}*cPOr2c$hVi#yuFV5Jic&K<$Eu*y985h4UVoTgL>t9R#ZumDq7x{^G@ zq4`>uBuXPg45|rqf`uM&?I!fM+1i&5O~)dD-j^@M-6|d`3S+4Fe%Va}`1!Hl^rCyd zr;7~4m^~%;hao~{LLwy5=hUVWIoC5CHzkd(<5A1vGviqcYcpj*ob2!fvzSR%F5?Kp zJat^FMp3&x#sfXwe#MF|Ll}h3hGvFIr9@t+c~#^J#el;i6NM|gcN&ftImPKfsfWc1 z^tYb;nBL^r>vetED_B%4s&EWJxs*o)y46v%hHFXAOjiT^(3J`o*C54=w@cMF-K7uF z)3z1R)jqOYBu;PJ6$peN^`*nVb0vJNQYuESYR&C7W*F>p7Rnw)?5{ouWn1@^V@%d> z(^W3`ZVGhbosswV%%IA|Lf3ZWCy~Z|aQJq(KSxyaO&s76AjFyW6o|Uu^LGk`wQm9a z3sXyHwbj!rcKu5p?_?J%IAtu^MAWK{>?0jOPb?E?(xnw?v>+=!X|QXk3ER0#yg6IQ zMIhv=ugefb$7LEkxBp(`yj*Iw4}srQ+k*w*ZB=)I>|l3G-3+kC**@ZWW;U$%b09Hyk{tZ2ZWs~Es?!X+>1zNA@rim zvK?D=?<#jA`4_*1(a7_Fe1T0KR#YqJh;J{Z{wZmDC(tj^`G&#ua?U_)fdkj4*Y6m# z2%(*)=hXbeV0o60(3es8qGkQ!Bb;p(VA=wcCXv5*pAOEv9`J!=sg(cX?KB}?EKo05 zg1T%!uG}z^_yqJXfZ|&@-ES+bisA*z`lEM=3)z-=>7iB3@6$+^z_^k2?UuHSYgNP6 z>xvakf{B3G{2+CqCsKuXdB!?K0c;BDAX9T~_fw}j*|JE}<+s%F7|ImISa08-I%YY5y8OoxAj230nZ2@Y zVIV!2IsaSeS+$||Nq zXmbZNA~g&$rE|280-Ltlsc{hf(HpCwg%>0-Q5_l$xAC*{ea{%i_G@Chs$qQ_R)@iV zYqPwVi;Y!sa+ojh#<32kYz&kbobe4L42p5y@Q9rD&HWxPLeD2PC{Ba5Y%SX(~n5g}ZNj==BJc43~@?+9VrU zL4M{CZiUAnjQ1GMp1B!eqhI(@fs?2_kLabjkWG1vWlCcy>+Vm;)Mtzq7_0kl!{49x z+bkSP;J*hiMX9e^{G9vc4Ck?dI3H-1jAhPDwJkaXHt^3T5}<3mmMOJWIdRD82)5VAME6@( zyWh@_%yxW37@7F^@kgh?rH>xv#jY%^^(I*aK3JZi2U%YzE=Pn1UE+V#vanjD3<6H2 zBLy|VpJ4%NR}w2IftE;Z!fh5k1SPam@kE=8=dI+3!hYqS~rdH}KI z&a{!VGfr1hai>G+xAwpfq$gsu+q%PNL=5#ZI1g;jd536R*D7zZxNFkG|8E5iNYu3U zX@)#Mruc4T4c>HFJT`S5>@FWACCDr^6|==J*!C-ZinF%-Cp~-kOzZ?@dDO3Yd$MiS z`_j`sgr11C#8f<3|4(jQYQR-zjg()f$9Y~lg9&*sGf*!i!ataDDs?8|GGtb-GXmE| zUOV1+b$$^Ea$kq3DzUg8J$- zhsPd|S#m;rr^v36)C;he`62lGxKRH0U~`+KsdQg^)Si=-vHw2?mE z67ai5V7&-CMjZB~_A7G*^{wVRfr1;suQ@MMVhksuOhS=%tk^|)W}@0TE$k_$vo=f6 zBJrj)zM2~n^L=DMF)bs!V#b*OoKSVp%2mGdt*BeF&y+iGqvsgg3eg5hue)B+EWHpn zRXS$8b`pa2rpGu?%Z@Ra7&YM=xQ5EsvRp?Z;afYgOMP?~qH|xTgi3YU zwV2XTxo6TO(t&f^WYR{rT&~=Q&-AqBo&U1J`nt$)d|6$tPJ5j)L_H5KAuL2c{znQ! zgYgD7H-1V1CB0YAO62L=kmKrTBZ7NFC0qRJzs5eVw1)wZa{>q4KIc)x%c!S|Mq_y8 zNY9H3t0$~x;iu##|5({xU+>43Hay6QgpWr|OrPDbf(A4fJ0 zB?3BVFI*o)OdQ~)x!+UHra$@fkSQ;nL!vOecfi|6z=eZrrc1E)jLE?sxoWk6n~t+t z73uO-{zII1wbDlalR666iYhBo;SZ9ZM)qHIyMetna(MYMSkvOVIlF>&QtaSpQ(%oY zsGNJ4JReup5coe7cTwRRHBq#|yY`^=nTAlpaZwHv84~!uLIFInKkh8A{EEt;lk{E* z#XGPvu#A5I_Ex$-tQ!hTF6PeW7Au77lt&W&={`TvlGkwoh^5!|8yp^q!_DYy?yawCU^dm7n2FY52prfde|`MGpgmOl3n@4aN43CYW0Cdp)RF`v*MSzkes5mLWQC)wSOmsGLPVbo!yDC)r6 z+B4QlF8d{?|8I&*@xZGYV(a>AJZJ1 zYm2taOoRSb0C`UD}jk zZ{$6DU=}O6dLK%xCG4&5Vzmz{z4Zg(gx9AGsm%@X&TyDi?~x72?l)WEgva*pXFKxB z*SlVbt@SRNN3TaN6H+S zhVnAW>}%cf4NX(V7sh4v7)>rsPgX{GA(2O%S}L0^2OB3o9*XA_dK8dChkx>QNJG|B#9T`i%xDo>bHbSP+eK2I!G<)M@-8 z9V4HEE;@2Aw&>Xp*=);-EKpNMf_YwAzxg(q_v7M}6SZ{YMp97trY`vQ*k#+u<48G8 zxD)K$lE`#Uhkyv?_C@IgL{ma|~0 zwkaO#7JF%74*3pvu4`8P-l+4*?lS#Bi3mM%q@QRUfx1m2vW z75PZwF!JuV(hv`KM(K?qB{3UMcAkFs2L9PEJE}K^l`jAxX;8{$nYxX|p_QbvU-r0W&(48gCzbP?{K(mZDxb<+dh4xnxr4T60Tt zqt;1-ky$f4M%JHoSh24A&!kEF6aGly8e!;Yxz|D~)TD=QB3&5a_|MX@J-S$x|LO}e ze9+A~B11i1)*Qc=W!uq*{`Ad&>sbE;g%bQ&!|ELG1|l{nN{H@xIM$RgFN0J5fS%qn z+5Zz{O)7?tT4-cGT15u!(KFhu8&qqq1OGErL5t6QbqJP+{L+rl>u*wa#A*@JTM;Ir zQ_8uG><{EnK!(}GusbKLQNh5_E=Ul?E5k5jVJE2L4Dy_w@|F7znoRL!_rhWqg@`2S zB-?R-P3m+t*F*{$^`qS#m_5@KJHz~RGv}Q|OqS&Tu4KP9o9?qspk^8eoC>x7pPfC) zL-dFRk?xzjTfjKt0^jM(T5%v7-RGPo7a$XNzQj4AjwdV!k?6B?Yo{hrffx6hq@S;~ z)P|oBmNdBOJdpco+!Q%+C`>_?8Sm3(TQcqmc>ER_Cx)(fvvVrXeCx`yVZG0m*qT6{ za8UKP!@qO#N@`J9@*u}M2A`p(V%1!{DkXi%u&I`&CaXn#f-~y`SJo%9{i&6hMTh=p zIn&k2OB1C0I|4%;g>K!@TYW>Fk*w+(Z4dTl@12JK^vr2C(rc+Lcj;t>K4dCK1C$-s zsC2<4=bKc2RD?@U@MVE(%14KCc3say%a68p7z{2mXVk2mSbdI1> zY~GJp^!%2~X~UDQJ+{w0#G-DPyw>he*&FWKGSsg$$y2`TMI-|>@mY}t_*h(AkqE$A zT1%&l=fUT;oxAi>`ruGpxo7#;|8}k~b&XxA{BK8$+;0?`w1@UTTvzENp&o&T6y zK2Bd#BMiD8%xM{{u^jtgw6ZvH7yD%G6eIMe_c@pv@3)Rw%zKyIDv(n)3T=;duV)wmw31yZe9DXfyL=W7C<+a}6IU~peS8c4u=R;Fmq4{%J~o zr>7qO^8i2mbmaet%lrc~zH^^(S##%clc?@9jm23wG3Xn6+r2$rjz|5vX;%;gs&&7= zzdT&WT?b<#=~&+I>#0{v#@XE(w97N61KNpy+I3Fv#;c%8Ry$yJ@S6DAEDdkFZ4sd_ zdz8IvonVPyeMG(j$WcE~7-mH>RNWlDxxIKZ70tQU-&=nE(jVf*2nG5*{iR3wanlNa zW#;6j@3ozkKZLtUJ(lWOG?hR&IUy~tD7(U6@L0rz&m~Wkwi=QQaX{K~H@YWXZG}|Y ziBRY!G_@=tP7-AAX!E-wUPIlpjq}yBI*Y_a^>5}!FD&=h);X4ifmJG$X-AZhbloe8 zvS13x+NTASA>f@?D}hb&nnpd|Wj*suK0-XR+rPMR6hGo!a(2#k+f=TuVS9OLgcgQ; z?YHoSXrqfFIiNy^j%o5p(^L4K$X@Bd?k|t)4Q4Seq_NV} zP7+I{hzTza)*jAKNsp7JZwhA8SDgxreB%6{Q*GrBKsmvo(5z12OGdAlM^sskUxyX5V{OXV67 zrMDZ@Mb+!|vpvFWCLb>7kG4;X#n{_cJW77$>bX`!-}ZP5i8gPGBy4XKL&i&WuI<(F zWdrKMk7!RyY-}#PAV32T1(zEXhEBDFxV#yOpS!)1r%usnuV&qNLjW}kDY}PDaRpA`9rz;jm|+;E;RN363Z9cAA3SZTB0id ziRD}tJ8A;tb;95&U6U=c_D?V#F}vu8y&uurUHBT-HF_lO*WgkWbNC;lT7>n6h>02> z6m%SE!2ufe`?}yakGV=P)yjUt&c;mu-3_TJ>d`b)=ThxqC&}&Va9XDud~4g+af|G^ zw41Tw!$yQuu>H2zf47|R5lhG_@Sp>u)?P2Tw(GOGu9xn^zE9265nA_{t48>@DZisG zx^fTgeWPvwGYOA+@_*Czh4qh(x13nvjZI_l_a`q$j9VOH%24m%+U?gL6ia#qlBI2G zHEDkSZ)!u))QD*TDva1UTVNM61TWIDctmWBpZeAI!TjY+kJks+fl)y#A?U7f~}RK!=CI70GUBwl8?zC`Z$3hgnQ}6QDi@CN!YEvF@uu>=M9CDoqQ8T* z3bW%p$!K~M-e#P0tpXig=xR^-ea1wUqpXz{m&O!Sw1#A= z$bRaZ@LH>|6}7DaAXt%|ni+*vy!Njirwyvv{QF+w#1X=Fb7Rf55eRswK9tHgb#ow` z>%Q^c8i5V`L9wv&cu3gug=fm(zxc)#@;&wUr;=7-OErq)Cu zni7@R-^!lwRq@e?n&-C-9$E6MgjRa_oW~xou@^8J$rjG9tYe2UskcRP*;$<_+{fJh ztioAH7Oq9(S;HsBYq?4M6`e!2Mjf2Vn~_!WZS^h2no+x_$!NjfnfeFy#X0Wx)($hT zM$AO86bvqs&3f95qhlV#Id}H=m4fZ%TO%f(AxA%Y9PoSRWNOy%?A}O2)c=G=PPDG= z;yG?X&=z?m&FrdwzRzObcP)-j1F5ZH++hsGyOA4zbT0%$JG|MOKTp)2v-uSUGD0Tp zUFra2uiYwV{H8kOh2Hg+)PBS%R`FE(X~N9lD;)3h{1YNzc0Dubqg=e!3YID9Vw1vV zvZ8;&X1$wU2fj9xi^6fJ8E)7f+ZdW>WzoTmVcYs20{&expJBV4fi;tsP34IPQi!#v z>qIr2IUUnIw?50REbhcuuHP7Xfjv!F9KcQ0@m>>4R|TKl{xwVm#zcvAg*UL?WSN`l z{r<99oEj5Xh2i5+Y&czj4WvG(i*r1yK zQm)||6f;s{H+%Bcs(*GMe`C%UBu`|$poU6nZHEZPb(AV`ey%jD0VjQOjb8gWluw*t=R&+G;yvk%yO`g*?f^^! z0CBzIT}tai&Z2){R}EbW_gb-0`5C~hZrRWeNAj=oR(F!w)s)&Samnqehu54m>K>eK zhVyec0a@23BG+#B69%}8N`QzRNnC!)0qreP;13Wo*kBK3^k6G9=LR$gqJF3-N6bQ` zxh=;W?&Ez3Q@m3nlG=r!Bg6u4dt|Zvb9kp|#fV(Vw=tjF))Q4ORq)1w54q;TO9zWI zL`(Y-UMGTIk%B`T=6-Hy=2RY4n(&*rq%+DRbN5#q#YaV*5Xx(K6&Z9ae zdwy8_u2|TF&@6I4GC6!RJhqIZ*DNz%+o)aQ*cPOy7{I5rtT(P4%gw-U3@@7q!M+Dz zop*B8!yl5oYEayiuw3$8(1V=jLP}x3t-Hq|a$@c2S-1IbMdtPR{+BYGo0GS5I0r3F1>{yC%%vtMUfi;C6?!+VtPlE?&T-%DdNC#CX|~R2@2stP z+92apq6ls1c(*R|Mtild)^>_z8LuxqG*t!bq5V&`uh}cI=8oOWmjQj0!q<~hR~ba` zBV6a4Y0C?qFe*e5AUiij`jtPFN;ow*JEiLL3WBi^sWbdI;A-@G$2Aa z6~~on4K*qpo2xA)lsRsd2PA_((%N~qG!hq4(Asz4yFU5^)78)TGI{KP1j_D!SXa!Q zuoGbelVDfp+pryoU@v4>(-dr|MP#s^}V-ee%a7b7};n zL^?QYZy3|VPp_`elJ5UMMd#wq^!xwuN>MpgKIPa{3Vr2JPIFvm2}#Pxxr3F{9J9?# zB_xMclG98j!_0=C-#_rauJ?7luls%9_w)IBJRZn)Yp!-p zdMw!k4hBnNq{+dO+4PqLi#0vcue7laAhvX&rKs~0r#a+;OJas4;Dliql?R*HFiG2E z*urg$&%NpP%e940C`@@);T24q4sgwe?hx5unB1L;(4QWp&EDlDFiCN-c|Z%qY;AC# zlI&=G`L%b0@nB9Y_uA4i)Lu7+^B3obRuwVs*1dfCm{U2~D0aH-Vf8Luph)%K?DzGS z4^vf~bLBExq1QTxg3`GGS4WBs!yN#b&_===eaKo z)Z)f-?!YaHVpyGlV_`&;4i`~iJDv*6`HTn3eX{jnd0axoV$K^Dr&nGn3wts69G7e1 z9Hys_{TCG^Z5qP_uBqAz&NG}l91=zA+W5=|+gd;4CjfUsTsJNae$>83+Hx{d2Ka~d zkGqecMnheE>}-lo)Gx$aRp=wJ5E{1lDDK$moocWP*(r_-JjAtXcleXbq5T->z2o&A zL1OyNVmSVPz60NO{CcsbLTfRgVDm_TkKynyt`ler{je*<`x;%S4u?xt+(rJHn)}PJ z!_e*T;L0TAQ}cZnd|gA4yN4`KuMEvJ7ZJ#CJ}}hfr+fvaHS3nv+O~%brp8HvU1%(& z#@h}3W7YeAT;#)7&yx=_4_&mBUQ+p1d;X zEDgL-DPOX{lbIPv;UdxICR`IZ8)JJ-hJRx@UF(z^#S8kc0iPmlMt;C5DTmdRmT0|>Lwf{ae)%Rgi4t-pxWev7;cuSB(Muna_5f4O|wh@X6L1 zUl*JWMxVvw3cA|nZow{a!VO^Wq%>OMlYI`v&zq66I^VZz(yj%Wr`JkW#Y1MBx~N{N zuLoahz`)^mMr`k&e4{vd9QEJbAqFkk99ApAol+7~$MddcRhQkwMif)8paeP9gVd|vElYz@(m$;v@ z<#wWE$Mt*|^{p9%3bz%uKrDB@XlXu}B7Qu!*N0Ml$z*>F7YRQAyE~^q`C!;!%^C{6 z=iXUO`y;z%W&6oyI&cx^c#&H18ErSiYwbN3Vq!#p*$V)r@Ys@Uz|H3V^ zmUIKG5mt5S)jhev4LzHO=d_3(p%Jb~Pg~JC&YKLQh8!=(7erLqL*@542mCc^Vp6LL z0p+{{rZ~8Lmj~8G@Y-GefQJPz#m)EI7CzCX>sU4_e)s8r3h*N99bWt~WUH)X5f4so z-$%EhN3<9gSj`OtI1PX=J>d0ZwV1mud=i_fBjZh<0ZmZHs9QlbC5(>tWYz9B&R;=-YWHutU|QS$eznCf_OS})oE9R%iaYl{J$H&Hud(Mrg|7Uyr<71DE`#ivH@5+`P4$*#p*pME;P&9i2Lqd|GKd*B7kOJU$b9RwWjqAUU!r=U6GSf zzxy`=`Jj1qwCanwy*=41`7ZUo^^NPns3g6S@ZStT=X1lQ0bh0Dz@xY(wq~LWNqjj9 zk}Z9ADM>6wB+z~J0rvdx=xs7>6SCnrr$>>gT;5Ral?##cv9*;LtG}R7`I*~M>-14K z8k|*gTd+a>L8+ZRsaF@Uu)ZB>MxyjZ4+TEgJC4m;XbGjfbko&+Lj#0RHqwClKP@-uU0kIK862V(!Gt*q_Q~oUG_NEE zT=J6dS^VuMn7Ot!b+kP&n!a{LIY}|I#ORogC^ThZ+GmkbzuM*_ru?TtLt3Mc0`^P>pC3qdn2d$ z51E{^E{o46JzS1~cci3%np6pc%m956iDD?h0zb-t&; zY~^w~WNmEGb3k>+IA?mHiv{1a)*3HeSFr;Mb{RzSOntBlsOzjN9RWd8Ifz$a7b!9; z?fiGyVT{8L#pniPns38RWnn=? zef|cofXZ237lFnM$4|ILu!`?j>XucZ1Z}UkJPsR|Q!8a>f^>7>`%xwr+#2!EPz~-? z*%5Z(Vk1fKlz*DT22sfieIuu;GOV_9=U4V++P#g+*+C{=5C;<>nni5%}SY(yXHqJua zEPM5lGsN?-NR? zRQJO1%*;aS1apL&OE&-%~nR+M=h4_*j7ChQAPSo$Ya@VSZPBzY(*8E83T9DzJu z2Q9B^e_8s)C`dzgYcB9$=y|vMC#!9kSXQpv`zY|q`&1nE>}ZaHjK3cEGvx60ADPVD zn}&ue(}UAb1NWA_a(BKIUJs~%);f-9kKdLC_#H49RK0jv`5Pohc4cbF_!?(EuxU@N z2=oiV!~Bq+W#s+|d3Qa6b3_b!8Xe?NMidvO%byO2CBjDywj@b!q8eQ3A9}SY^uRlk z7m7$|#?G3lEcfv93S>q3Y0SCoR`TotMIs~*Sqi*07!dD}3DCDAR$pNsM0Mdm*thiY z_KL;rWk&uyqMal4Cz}mQqg&UJYkr)3c5kzd>f^J9<`zy|A)WUBz-S$rX?M{*ik?5N zW@*xx`gXw72TGaE+<6Lhe~+2ZictG$tu;MAIb`H_KccSfcUVwsHO1$Wh8@(CJYt1}p1bM>~uzE;NiY9)Iy9T=J1_VQjJAlDECZ zA%=Jr)BW4KNu2nk^`e*z%Wa~J7*hRVhm3i!b#8fbcqoJQ_FBE&LIK&GtQX=P$^ie$ zFR{qb^lM`6gs{y3Wa5_&y7em8TwdZTq_ga`?VHSw<_*DgB%z}`EhB3^4|?0QWv4w5 zg+Gg@gcuP`@%IP9`pV>^@bB~)2LIU>RJt(&AD;%o2$!G&67WWP24%CYA?$%gd0-C9mM!>g|SlIP}_h@S~oSH z_wS*~E8XDc6MClG6&iTPEVOp;yc;~+({yWQ{fyrpe*>yhWGqUPo71RW9j$GjZMMYH zZ#})SH{+apj?wkav|c(zm2kcq%JR5n7Aj;RVU(@9YImIZ+I3FIAE+!t{*QXd!{JNH z8Mq(4P;bYL?3>k-vIg0nwIQ!H+Rw<(a@TT>MQ+Hp z|IRN+%Vs2)y7`*l!X`Z!L5w|eaqPf^y8N?B=5m%P=7SzCTpCBXP2_&I2Jf7-N%fLQ zbrh>UK|G}Ex^WS2g5>uPfho!TxO(kVl%7&EWtR+vE#dS{pAO;6)b%3p>;b~ceB_s{ z9r>-P6zE(k;4ru0Nx;Y>r=EfRpv4T#cWC$GgyQhPzMPfE@ARRz$br~WW&6>)$!%?! z2YB(vy>KRmpQNT14RvqLoZjA3S&|;N>6T@~0ZO9{`ZCONyS`|hBewEpH(5ov-5rUGxhoo~n5{j) z92$td0S%N6-uxFjG(j1h4$tezeEP@shWqyYwyL7`B3$F@`N{k3*EUCf;9JWM#fr2Q z@+Xuqd0;o?KfjY_KwqHj9GY1mmiZA}MI8Q{@ugDF*JGR9ywrLR!#*k0MQrY_vWDSZ{ zOj~ms?dmjCUuH*-LfI60F~tC&Q7ktKj^P+hRhTU;J{a8L#)TqnxFzdsbb=yqVc$*#)LeSfI68ttxSzMY7 zL<%-P&HU=)$}>{adRkK9sxJT9$ZblljPKx?4BfTZ>wVWP(S?yTe zbEAIMv5#(V!ewxj+mx@NJq!=?z%;P~*kzuN=&q379aI+))O&~gNk}m{AR{or?WX6F zvFYh&@)s&MJl6^EAw7GbW8#}IyT^{PA)GOp_})rWFT^;zjB<7)+$G~vc)esp%Xo6N z;Q&OkE*^}`s>b?bdDea1bx$;x#-=7UMzRU))w-u!#%0MMi{iZFW7)vIES}K=b1`7| zc&=^d6@gbf+M7T;1#?4Zpp3U3>PRV7{n>RM;Oakx>Zq1juKCgKjF1p<1GHD zzA79&-8$+0E>d)-Ep|-)v~F$$o%7rfEx~jW8VkOfKmzUp!_pgn^?fW01gwY^$MQNK zOMs^k?bEtY@7%`n$UN1BipJLZ=#a?SgnIPmQBrr&@CVeZ0`qRo2Kp?cpN(gX}x*KBg0w7us5x|)Y#hnaL3Y+3k!;K!2CR; z%x0v6A*j8=*Q^~I?~l^^+g8GVJSAq=Hk!>tKWWT)0#$?W&pp*kmVRQB`Qf(8M-k7< z5qFEcIwoJTHg_KV3O>}!4GE4QBi~cN(;qsi*7@}yqlT36f7kv|zf+yEOR8h-J9XO> zhdZpWS^z34dSD*njmVJGHf1R(%bS*%k6nU~UU1>xkT7(XI1!0dl0 z_@Viuin#`QV8yCOTGD1Ki3Qn{mqx_^)AggIhkq`dqNW&jC8%uJyLCOrK^~P5E79xT zl)bhI!pQ683g%-18hOLjTTfsQ;zW>PLVY&L{OI^2{3H;QK5T`j$v0TgT078r%B`R_ zQ4!kg%r^LYB)g$N)-#Qo_z!&m$62S}plRv8>|31L-42G|h!mGL97~DaSVwN##O0gH zA*0y({+U$@RTPmov7f5urMwlW-MqA;;w-0py(s9}*wL}F^h2gq44XO4zQ}LuU-y>C zP;Ak2CG>g`=KaxptdTGs$^ADSrXYbrEcAvUudm<+8&jW*e~4hC12kakkxy*@Fp-|# zf`wxv9fBE^n9M~yI6b(!onxDt*osr=_ zDUn>`eA`+v?)L4teUX~3w$Hsm`w>AodGw4wN1MC&W5@HB>1^e^VX8@>Of|?;rY2a;lZv8+z&AHDrL}z*zt{>LF{xd|^k1T(@~{ehFwl zTH+EKB1q@fzXFC0)U=qV-b}LR^Q$RkDb&c1sB?qT)XNisAmZXzE1c-KOoH!;k1pz7 z^V%&B3Z6F|;DUEYlw$w1viFoG=P&xj9WO5vYThYGeO7>0TaR1AcWmCHNQmZS7IIe4 z8HxEV?GA&c9}p3WMNgjID(BpEDJf;Wk<5o()eOO_ylh-6Lh8 z18clkqFTX++F&_* z@wCV{*$qDP@(gi8$T!O4`Z$5hhQ$R}t-;&lK-4dMj+cbHo*iV0quQCbs=C?3>+TOU z-?-|cn=Kk~OJbIL5&Z7=^X06;y3zamR?GwMZ0wlSJ3Q=*T%6}VLX-R()lMekB~ z=7DEMj4=9?c%M|j2OOvjoeuzix7~XpjJk@4CdTLgZq71FQ2y?`a?I#jGr(RqL#6ch z6zNsqEagzLH2iA7oQ9|}JfD&N?*mZm;WX=*OrJtn`+cqa^KW0(F;J@knPRHcJ2szV zZ))=98*LU+Kn|{@NuO1;76$n5)>CHbzEat?!C`)z34ui<>xp*DI5gtS>azk#cyiN; z2y^jtn;z^?G=WKn{Xd9KVrSAb%Y7R2Ya+qB-^^EXrz`iFE_mi-{g=(k4xka-5xdVt zNi$=o&qaf`Jo+~)3c?@m5Ret$;e=)Vb33B>-6jD@*h#Kp?~w{Iw>L%@XpB*IDl0;j zBsLpmD7aR)oQ-B8o<*?7GLz#2#6osisHi54k?sYat@10uSHq&Z-d93sFr>O5J_~X< zmAnq)36k3;gJ+2x{${vOJm88p2ozd{;JgXAhcK;5*WB4MJeJxAUpObm-alE#iKr-A ztGAepsRQb{;;QFFg?q+hd9|LTpf`^33j;nDYH(BjLM&Mom}Og;9ihXO3#>yFa^yC; z%BY_}l4{nt#)+wIQ)p!w>~-C=-53gB$>8`)(mg!BNsHx>KRs%v$q}J*?obqll+6!)4!P!GG)&nuHd;N(?6uep#RQ$E8~r`KLMAW$e?v@-Myj+ zV5ndLv!B(M@Tu;#C1$eN%`pF+!*>UI3hk>bt5_Uv zt0W6{mr2M`o-m95x=Cz*cUPC7=Xgz%exW~jgiu=J$r&85{uJx9e8Q*JXf*kFcGJF5 zNofiHc*f&9=7}>HJAQwo=%8<=2j;+QvtCQ4=l0*(BrDcH_;;xlzM)?Rr9ti(g>*ylq;Jv8 z7UC1fS;RtoF4TNiJ5#)KH^R?L-ugT?10C#Nm#Wwj>Xzl=1Eml98_-L^HMSEiqv-|6 za5Vc$#UP&&II{;ykf-U!QCIdu4-0+AKys#+<5TmWUDfLsL`^o`!Q2dU>waP;d+~~| zPRqW5Ke5GNdROC37ZbG79ooVW7y*WDiW?`)5}V z<7oNC4a#Tl6!fijr*oIa-hxnN!N1`qoJFL&>Ae8+vO|lKB(n>twr3||AVwzq_{i;? zR_Y@iv=EQSf!qJf=VsGHks=dsO{KyL4{c-x6!jB~d>ECPoE5ys+pJCfof&9B_~L^= zK7l;TXsj(YiIOi{JRWu)G}SdJ%gCCoe5X}UOlF#2ZEose~`k&!R}=v}i8 zo;XBeY(-E+mbf@mK)r#DK=BWK9Y~s{HK&EVBTU&uGea-`&(~zK#n8&1%!N*qOAO^hw@fTT(o?{mUo@HL7cID2=sDVqw$k zx6ngZV=1+AEbvo|1wA~abMX#Faa5~kCIqg7&aBR?xM_0*=Zwe zL`=LD+q2#rYu-(qMa!%KR%J*e@N7+&3F@eIli_L7-045sBRk6y5sh2|x7)YH-(SO@LBS(Icu z=3C}a&gRwC(FG2z(amRb=dtHVpu{`E z&(yV&1wrl-FuAu~6hXrM;nX6a?X$n~-3B$Z&n(u23Rrd{;?VijoB8O$j9J2#Rp}7o zrPOvHAqa-!Abh@A8D`_>@j~;)ziWQogy1*{Sl^*sHVSLTFjF zbU6QYdiTe9ovGteLOQu|Gd&Qtd#9O`#lqPMY9NSE|7_Ty*$l&1&L^uTaPHx@`DiN; zV^%*042lCJ8>))6l~^6PMn(#4@Q*eNo>`hyn8BP!qM~euYct)0ts5V1Uv)Wx*79!| z)r~kBc{_2g-GAT;I6tS_{UT-5vUYihOq=y`W&05?!e?CL45iP0PRsfi{#9)~Cub!h z+(G9Q;S+RZ`~E^37j|X%!^TyOF8gR|Zt`5;v0x~aIs?O%4i9+Gi`-W9i3@?5g+uN@MDYF9Rk{+#X?bK(7F(iR<+E)!b!hzPc9Z7c9u_Or zqP_MaL?X58`2;-GHgB9pn%Ua8RVqu8j!fg3894=8i7o}NFAfx|2EJEry5Ih;?;Uq~~rg_#j_Vn;~kVTj6lcWdDGIsm&k?D1RyaG}(pxo<^^Bt!Md zPApQsOv!o5j+j$+`{o|F+U|lg7PUQtUU{1lwKT>S|63N&q82Q5K!U1vYGOsc=kK(+ z(M{=6#5>-7}5;T#yqnhKLm1>~B%fG@`*l)Q{JT>$a z(#;sRyNxldSD;2k_O~LNtknHzN7;&0dl?Z-$rIJXW`BuJy85riJ&89jPFxT{=E5GC z73}5cthZ@5uL1ZD12&5+#MRi`1HLI3KetcB-D)*T(&ZpY##~e?7z>crJb6vJeB3@1 zlzkKQvwhJK=3Lf6jEkSDb<;!Sz+Y)dF-?D;RqAvPs96ns$(*}5CBpHi*s|26C9kd-!f<_7>Vv3&m*9jpOvT+gs+T38Y60qWz{n}H_f!dSR%VC0l+ zR=d0+6JaJ{`o#3XhSrt`p0+TPwQN!v<{QDSEtt(_4ve0L*-Ibs8?W8AV3$_=dA)bK zJ>hL6oZHpA3=;jZCGcbY6vkF}NYlf$0!+!W@T$&nNoDNj-2joK=sRU@zr6Y)HeB>i zk>sEz9oNkc8*+$)b(?B47j#wHQ>LI@g7)BIf4WT0Npg{PT>fA9w3_Oj6|pH=sbyBZ zEW_o>;E=F_g4=@R{y6XRk z;=z&gCzz5x>z(WP?QsqBYc2@-5612KbLC$)2lxkd3kdM)nGmCqVt;%l)=77={e1Ko zXTtlQ+4VAUuVW1zeY7T2hc9RUX3&~-&#AJ1)bR{h#jSvsmD1q4B-A6L2?9!s_YIxE ziof%E=jHtL)8KP6E81%7j&&RJ%9Ythq4&2RhN>^ZEz7*VYNrk+7WGhdK^GmZXL|$> z*N>v4rI5~UJAUm`O(P0;VV6w0?PH~e0s zkBFg+exOwFXUYtyhp21YIfYH_Z-ah+;u>c;Q*EhK(OEd7`hr4=@zs+)pAY&^NG#(7 zp}VaF{$=df2c5>8lgvw~*G3>|t-T-+W-d@~a2Vipp$C9%2g2^&eiJ&A}Ec5xuZKagPI=R@IfN za0wnK5y|r0M_-gg>e4Dbl8WX3Qbc5TU}l_D9Tj>@>@yhd01xQ(sqVJ7 zholEyYil^|Ji@3lZV;Jh$oytFnEuAp7Y34(a$ihP$DD~o!*Z1W!q4%VcA6p&EpV!O z5O5XRG2ANW-e%$A#Z9aW#64q+H&~5$-61|bIh8W`I46=B`PGs(I&+bGWe$jU$W*)8 z;8T6e_|i#>vSZ2@6HkO)e>~aX2y@v|1pZHu1^y2txF4iob{MRt29&le{HrVG@9P#PEh}C)0&*jLhIIUDcftX3o>TfWzYWZa_W%D z4Q}0$t)Lp^HDN^*lKA1_q7zCf6QUMhh?#Ak758u=yU>w+kyzschI2;mVwwB7Y8$K$ zgBEF%fo4o7V2@I4daae@I~g3SQg=S_t4c&?)=3?)hH76|C7jWR46}HcjP*m0Wc53EfhO z>k&?etG!@8MyLzXsC!2CrAYt&b6ZIyDQSuL$vVFGs@@L^gI1hw124|5Lrb@)W!vq$ zdnIrpAOEbs5K&d+gKNetsiQe}R=VFpQ$?j$>N`(tybe5Fp7C%Degue3ZV;o9<_tFW z>-M>QFw@L8N|hM!*jdh2u(6eI_uZxqrnWq5 zYnZ;gF(R0Wo{H@s_#Y(V>D}E4=X{Os-hgo7Go(eu0|E+}S*@*aY}1R%%s9W5&>|H! zU;H+9Eq0ZuB+ZEi&GI$9B7%Q=r6Y}h)+e;I)a#R;mA`#OctX`y1^eWPGw8(KnR4m_JjJeboDk|Lek_WRIl%a|vYf`@_H|5MV{ma~kQ#AqQlw+nQ8p@_R| zCq{|ClFJ*DRPkp%rZ*8h_+4{FqP741s=15g96x#AqSEh%t=r;dEQYftvaa7!eizPr<%z z@dNU5n11XXH=T*barz-TH=4i9O4Vj&7Rc}&?pSHgk3YA|S6%;G6Yx5$L%GGU(ALQ> zI+^AksJzirFf9?`J$tr)PP*4h;1Pt2_z|Of?TA{A8mp>cg7N69u;gZa&V^62(NzYi z*{S;sIeG0#ucAy1Yrlt8c(CQEpfY(sD|az%W!8Ro>@G%n8n;#Jwf(_$c!FePE}o&ie@WWgzAWhM=nP75#cBXXJsjTedXXuxt*7?I$<$dFD@qD zqe_|AM)-|txXZhrOSGcA*XUbDhQiF6?r0iS!v*eBdI$6}$M!xGW2V|Mc+wY91_k=VE`%I0?C4WOd58JKxWkPiFaahv8G zxp2Sfkm>O|N8Q!7=hQa**lNW^vx%x|cVPV?vC?aWJVwtLGyRw%P0ZzG20I&GM$xmy z^LM+1H0{835?@KUwBEoyz)9^48S~>l3qT1&fV$(F)#CoTJX%*q=+Q6`l6enN9m!Ram23oYc)_Q(F@=*lNHD zpS=Dc_a+hHn+!mUOHjEGx+aifuRC);gS00tBDmg0o3XX;n{(Zrw+gZ)CPtT!Jj0HB-o#qym&rv^1TAQ) z$km*qg1~-3w7?)Z#`Z*Wh*qEVBdnPgK2&(_ML$`DB92FT2K;mFzzr3GgN^1cdVQZG zOfPiXHxym?{hKiSSieoGw2xj{@91e$J(@M9PJJVq7u#m)ISL#*NV=++I8KUs~lm;~%7|YXQ~UvVnIc zEa11%9hK--#pj#Zj^tUEY_a zZgyheGW~Tbl7fEWGtsr)id(&_>xnTj-=}+H#!Ao|W50&ve8wLPst)Ej0*}`1!$_~4 zjzAk;cWEr(C=XW7SqZC+e;#x1L{QcKcc)=L%Tl;~1AB7uwh3KvC-_Aye|svE7;Kgd zwB2kmCooS>D>ut>Ulzp8_;Ec~J-5#BMRpo|UV*;N&O>>-=$YEKYFUBWGgaVWOdRIv zZ?)y>iCzG8$WH%%goQq#d4-P~DKfgQ+x~V{We=Ft6+`HbSiikERr31P{DvR8!Lh@S z=5#T6riSJ+$|n*wFX+6(TZhvWKSMlTh6iay4r@?_nl_j%1a~bC_N>E|tl033a#RRa z{iM6Q>K&z?5QX_v;rTBlGXyi{lV3Tt)sI|0<6errGz_p}0IM4+ChNj0>9-eMjP=dN zu8u8FWTz;-mF~wqpTNSNsD7z&q+|%LfnJIPp!L+u_fv0e&5sH7!m=ZMHb?(FASo6( z&bv;*vW^=YmiBRfDO+IwXcS7e_aTjNGNX}*)UbYVy zHnYaT`i6J<%oOfOBX4B_I|q*Q<^EGRVFW%49#_ZHGSC_|A{lV)J;ubKruAcFXPv3gxLM#+NMe7je|Z#u9Q8WZJd1j>%D|oP7q!{Gh3W|V zrF@0TfD_&|36&U<^xB!2%wy;Py%5>8(9t#oE%l#JM%=XlC!J-Dr>#4ToPfXd}g zjG2(i!gCF(EMBgQ=C>|*IcCN+YP<+%rblO#Mb-9+$4x|2`4XQcsaq+H(i0-!*6dvs zJD~m1m)5oej1{I`59F%@pY?4C7?K z_N|ry$YIt$I*-R3D*hx_cPmIb;c`n4?}r%H+=j~UFRu<&ishqW4@cAaH@(_2b46tl z`I{$~n5!luv3q;|dFp(Uvjk5Sdq%CPw``+EV@;+X+u3&O5Ico@ zS9>3JL{XeDOgFLPLcepn$kl81+ACg!z+ctUthq%73;&g0R|mmX1~Yk=&>!7>`!Mnt zoV=-?g@V!qjZ1hJ=B@S93g1iWFbVkA-i?MHh6a1AU}`7PlfkQEts-77wbGHy|B`~t zVL^fSD)tz?zd7qapXshUy9;eTPQ%){X6CA2lQu{WRW=uSz?y#(h;&2J}$M zidZhPd5}mS#EOZ4hD0`n?BAp;xwQ)nJB$4)_;_e5c+q7S$wYt2T$Z za9mY9iu@gM1DWK$Uo4&K4KCOQVLjJ=4{dIm!u?*f2eU^Rl&o3(Uco=!lhU0?LDSbZ zCqz)ADb~g1WwjsJ$R_Rgs`avpWZJ}4>yI)R#afK~4>s2PV{niy|JK|9Rs~d;K86eh ziYv+De+4bihLVHVgI7hPdpr+0T6IK2`la7g4HmcugF61QcbbO9xV)wpO3&-cp5DcY zY&?I4+vG34>kNNNoN3Vgw>!K1r<+}!uIPP(AAWQBjmaNs_ws*fKdMVXoe3ZX=|t(W zlI*{{2Fp4N;pwgP=%Lkb&EdRW07Y@|JZP`P)cJdd7*|z|P}eM`D3mmCORp zSiMbozeWL>rUK}o#@cfvvL*6*#M{7m+b!bTCSiNZPVWpYyip;lDM*4w&1*~o_S!4} zYWd~W4%_F$$ld}YiJP8q0ml0 zIyYzYaVX_8Cwrr62FN?zR*=sLp@2o=`Sf(m25V z+f}!C>qyl&h7>DqR=_u*cBn5kw_E&d6W-OWa{I^HGr&2LKK8rshp=o)Ib0^;+c3tSf5uD(yzaZYQvpYtMqvcw5}C z`o&|h``fyeS6xqzm%x2qNUYE|Oj6H{(>$I@FqOlke*aG1`r4@Q^B@)JSQYZ|Y28ft z8U%K*cWFI5!&2X(j4?pOIU{wH&BhP?zGU?>+hv=}eU?H|lg?4Fnusy~IhzR~2IT`W zt}WsfhToKIwYvG2p?D;UYTwdsKuTB8~sQib!1r*k9Nl&!CL` zpqg~`)x;`MdIRf`D$3ojCA>YVgrXPqI$sVQY#WeF&1;cMeb*CAgbhz$su3^ii29C> z8aQ%uVC0520eCUxwuyy8`=64!KLsy`I*z@y)@qm;S#`B6 z$apb|+W(kyk6YRJ1EJpW@k{dG?4VN#5x2M)gM||l&9kemqYr=$+-jtwnG-{a+q7## z?coSvk{HQN38=pGG2$D>AH`Ly+Zv-1G3W@_rulC@XJHGGr4Fy2&%iU@!*82P>m5`& zCyfrLi1D=K9)_sjO{t5RQ= zRmvrog>P2Ku&~XLc#~Rt;>=D~b8|3Z zqereG)nH+RcVh22@>sdrdr@eZL5dVZYi~BY-4~R$xw|H9`tkcPBIvPSnE+}YNPzW~ ziVG4HrPOt5=GtBPm+aRb>~D5V4Yu`;|A9M%9D`XUePpvf^o#a#^d@4%h1S2Lv<(H( zTw^2UEbgaiKf6at&H30ocm`wt`9XQ!^Ed9#6`&SW8gPts*CsE7HJ(xKrElsIEqggF z{u=M$cq;!1Y+=|+rcoAy;6XSZe;6wa*1H+@+^5I+aZEV~Zu~yEmLZuoy zk_txC>nzGQuW^}{MkbgAu!7(WVo0Qt#z@AGQS;dgdl0HaD~pj<4+EL__mG3iT; zwLn&LLSe$AD}0@kqQ5J!)zYcv|HpB50lZ z1atNoe|&Co>Rk$obTHpTW;FK3FH{ZP;~cD2QD*pAopN&KaDIHv$AVdEhtD)=Ii%oB zgS5NSvwLbs0b=`mZAKHsE2yWc#}(gCLlo61cp&?f8G@Lvu!~WBV#e(2MjLFLl}!F} z_6rT+H}S1QIQ!4ngt7mDypzf@jkgY>?N1-l-^}dx`hB>VmHAPG@8u^Hs${YHWx-%Z zrYnl7j`DZ2CPyOH%+Mkm5QMNRxiRF~9qgcRN@{TX$vOcgcgdpC_E^mU%(`)2!oQbz zRFBl%xM3LYp?j7sGJKByjYZAczux@T!tLC4L-=>g7r*-~-I~*z+D)X*A1Q}QLUqY= zAMP$nH_Yv3lTKS?dJA^vjKD5r@h;Buiuy4v?DaJww-7-}kU}PX?{R!EI_u8=wFu^g zDDIlKLdB0%{Sw6(p&oM-41p#ZTJ>DaKkXo*`W2k&Yc&TQ|6`*cJ->PI#unI~d5h&; z1I3j&;??EEmeI1#YIgT@deuhAU^?e=$qmw>c3UdWIDhc_RPcT-!J)hm{d_1CX1ak{ z^8*@c1dlf1^pJ8aW8G`yEZ~Q!R9(j$wd4!sRXM%VTji7Xu8_uPgk@r}I(=x~zVK{z zW+6NkF-*LfRqF7>rV$4RWrb(B$kN4H8xKw>(RF4I8+hCV0OO{&ccnpU%cIIMaFa3k1eRVE^8gUrwyi|e znABB1NBA>Q8}1&j7?YgR86A(licQM8w*Q`c!^74-E24j?-6JskNw@arT%e$ML%8{4 zm9Pb01&kv<*}4*X({%n!t2bL4Z6A=GE339-m+-@U#)|2_nO*l%%~URY)bxa6%2;jC zCUs%@jYD42$1}@7#_HTzfpg!1{JVKZOyJrK-lw%*_6+`J7*vYA#*A+|2tgfMs5RXH zM1hXO)-45dE_R68Dy)syA>;vCho=d)Z2YQ=P##+kpielqOf69&YM6h`P!QRW9bQGn z$bm+&s#o&Q1=Vw=Crdxs=vpKNwKBT0^YCJ>+qaff_ROkZ^W9M)m5FPf`i1q^$(eP^ z7{w8%wLC@V(zngcY2(uR!>|&D!*tjFpYTuNKNaZJ1C%%q##sVlAXE<8x9RvqvGxLA zF4g4KV;`#lypUX$g zKetlAmvjF19o(KE+6si`s=`9yn+u%k^;bumlF@vY(Ryy{`3| zms0IR@Il#V_|Z>C(UF=W$jN9uc$%xZ$2-{S->Q0iuQm1b@StK$%SxjhXp_z?9jsq@ z^kKf(dO?d90J@DX&lSUIsG7^aPM3>06#lvZQ#A4~M*OM8sPM#$F~cU|4nF%CP@Sd~ z)?cFV&Fhr%#QAQ=zQS==l?vocpM{Cu#Qmukh#d!J_TH)!dnb05IDvV{H21WP9V0rI z{T>snmqjimgEjW0f_@u(+Im$I{sy`K&qkCoB`q|MCc|9`Xz>ck zP+P!dsS&<`_+d5we>VO)P+y2UWHm!q-jMwe*jJ{`7;Apw=78y7nelB2!*iTi;|>tW z3DdZ#9jDnB&u_(2mI3k5x$Y5*LSS5YtFO^sK**hi62z_j7m9MwXP&~)6qB|Tsxwoe z<*U+l!W+3qZuQEfESM6`MWe382*D|>+{n*5!>_rW^FXY7Zc0BuFjM^VlP-(592 z*3^2aA289lI$IDGe~2wwzH4Nd!aW4#_tAG$K$ljo+2>a-$<35+-z)cwUJAcAF*bW( zKgb%(>rzD&+0YszI_5}?FGB^syhC*gO-!)AhpC0(ZAD?J#cZ@FMs{KJ+x^h`fTMuF zZ8BW1R}JKE4km2;2tUK?Y?u*hVbNZ<-wfV-^XOu5W7!#XP2e~w80odMd(vW|%j=A? z3gT#U0(p+xV6qSM6(9(n7nVF;iO#)g7Di%zhkYN5-#CgV;{HP-{X4PeYn5_L6K`rc zpGD0!4Oecly7A9-{-mbIX}C;nJ0<2WA;757&TQY=Ca= z=FFsw{9E8H*RE`4FztFfT3L1a9zqV6WbrmBqM_n!r%7Q5d#|+{n^k-H&wEG&?7Cz* zS&G|3_^9SsuA$}j(SFZKkua@d_^|f`glPvmM)3q3RnvC9V8bK~G@(xQe%4=)`~HgD zDjrw2DLPpdW`cQ@`Nu10`dvrB_r)lbE>2AkvmBLudA)W!rThi}hm98cT~!(^q(*=Q zXKX(!X&1%G92jkGz0@z+KREr3SC`#-W4gt{xv`RdOyM+OwulnC-e!>~eXNWc4t*Bmgj3X%WUU?~;0Qdlt7vseuus^kD&HBe zXoollI7InW^~>o7AupnKl<2K{E>IsrdW~+Xnqx0XvNM}AdBtmKPE6CSK%#M}@|s|l zk$a*_V|=f%GOMe+JnqY~)*dJ)XZ-g%olH}mQVD}pEhQnsD3)0nT(6+}8!CfG41U!K z!kDj#r^7Jmo2st;<{J{E!aOcDNlN8DRK>Zarw8$08Ytm|?1ZUt>m3>GP18h^m6Z78(u0im^Wzq$0o4CHl)U51P+$_@vf3NlMJ8)PXPt3$xh6x&}C( zX%)Uq(5n(w$>x1DH=52Dd~)K%SG7exo<2PJcT7)8EqGh1Y_?-~iN4!&!n1fqyIA4B zO*PIK;YZ>@)LuN=zi>Wa{UNSntfkv4OdiqPE?fO!(oOYX&CB?y)t8^u%uRLUh%i^E zu=X&9GfA?!R&Gras%#ciHJnx<1b)~2B084gXk6EmAQjB0YzMM0Oy_`ChLEz8fu?nh zXEu*#eHwc~w+;8aZzu$f?Qv3PolqS+r>91W2lh)1><4OwWvF!F=XU;>FOaFR^MU@> z`1YrfY9Sj#`bqNDfQn2Db4FgtqSiCwLZvsf>UpXKyPgIRQ!M2N=oFno%q zWvNrheShfX01{7e%;Ld%^S<7_op{84z#^fLBHbGY{cY93NMt;xJ|wOSf1RQ)ar3)j;PqTglO( zt*O-C`BxpA)RB^O1-no}SZ8@$jHg6vUu}KWkK|VCvS|}XcwCqj;&*y`i3f#J6+svTjG`4R?ZWkp^e%6_Evi!a& z1rNRW)K8Z3eNXn!|5oOsIDMpmVQxfuS99!{?E>_PCh&zT*;*C1_6`t#nRCS?(WnzV zxe)|WwC_FlgF1&lr|${_snZIwUp6j)v?cLbpD0sD+uC3*c0Rsc0AU|ha9mzSSJ^p z)VF@7d?uAN7^2NfV4Siy_r9;xx{Fe*UX+a-v_@ZiD&an%@1f^?Yf@L-TKVJ7z%+gJ zchiHt|4d9q)Ue&#UhSvg|H4{>;;t>vm(t$)@9Ca$^?4Yp>ctb`zLeH=>c&2=f6cfB zoqrH{dt{y`Tj{Y(y~%f`q>oDkMY0!8TX2gZnHERZFZ`ZWfBG0D*DSpj`Mo`)Bl!vW z1Wt|su=uPX3s`%h#QGBk6eR39ptkGUy{n*{8-vfE*a~iJKjKk(^(Y$hcdgYeh7J#3 zsraRk(oxi(*YOln4xCn#f1c?}`m}fVn=oi+_{jGC&5U>#=G$qN>HB}uyJX~kK`U(B z3DZuETJ-s%%0*wVpWz~GR_c(Cot2h7-q71}tEVRdG|$im3AwiJXAKAuW*wLV&An)C zaclCLEUkoAp@D4bot$HDl1Gm~myxrY4jN=JgO4>Hihzw1e{@JyZgx?-xm|&ln)=*M zmF)A}Y1ebak7FWB_p(fU3Zbo;kxzkEzLBGT-?3#|_REWvu>Z)us~$8`zou>)JV7%H zSSh?lZ40w!DmErrpb|H4_nhAr=84txfu^+mDZQG+kE)kkC7jczIu5FNpPX7l1oheH z0WFq(%03jeG}s}F&2`_W`^m3BA9IUpP%-|v<#TC&c6td>KxxfI3sh)rT4#4U4g9A& zLg~17&I4D6=5j~N?S~_TB?rb`Km;-p^2dOetnnZrb^XcN8Q`w0dYky?m`QOQynYMQ zHhkV=-lD@i!(z^7`D{ewqUx46EotE%@7A8!u9>IrA9G8k;fX%b5g7X+EBbQ-zs~=- z*JZBcej<531T^%^_W?T}Ck79{U+cuTqSTV}wlWNYhqaD?e)gKa2<&jF#n&iWypm?b z2dxiZI+*(&%!%)ginAw}cyDzznz`Rz0KoY(AW7q-lcJOL!OVbT6A0nIdim!UMxObRV8)**yjPJwbuEIR1Jq;nS?5) zEz7xlpnS~K>olfWo{;{IGP3RtJF~9{&`LgeMal+Zg1#62(y*)is?lX&MV5>@+i2Ic z$uMJb+A%{Ui0`&Gs&TS}_5>cgMNi7EY8B0EUf-iWtBXSj%dNm;Y2>Y66UgUl(z^*? zgx1mFC5)zpcz-PpWFvG;?ubErJW_p>#SDjVj1Trh0_%!+!7BhNr0;ppp+tMEy~hxT z|MMV3bI#cmMs&U)^5Y7Dc04<$`T=2!m=Q&DWIKiESA1=fVYM+PJnq*XhsSy6!FNsn z92&Km-4CsyYsZajg9{nj)IrXj&#R3gM%O6crz|}2swctE$`-C-M5uZ@clqMO7|hMh za~X^1K(7a8hb!I$pR;Q@)O?Ja-`A#7f3~7lVfz3sa~%P-ntKr3g-WNv0_&$PswM1u zm-Ie=3h%O!ZJH6+gU886rBk~?oo2T0bt@4=XLhDri#Prv{lS*=v)9qy1XHBk5j?uj z)9ACm-x=LnvZ(Y#V*Yen6_2r{kTB{)z!!SHRh#ti?=+(r)jiM(hx@%k2hsJ|Da-&? z9aWV7lJ{@v)rHXzF3PS*K>9*mYhz23*LCHDhsVRc3Pq$4 zx%5(1(+7J@1CjLUlasAOFYyJ5{V(R9PipyG#-Wn4&nFeBbcKuruZ;~Jpy1L-@J~uJ zCpjarp}aG!IJl(*cb#cC)8W257|#)&;iJl*0%8B=d{cT^(^2|JS+qA{^nHBC&FYu9 z(2N0-Sr+rM|GAmjk0dhB3Hil$Mi=x(08;|Ve(CJ;k#SDtLsQQRcoA137zjgop|?ZE_S} zsx4tlp)!W^kO^|>XDAqZFVpJ30N=y>a56-QYFu#q-f1an#3Ll9Qc=e4Ac9*`1@CT> zSdUJRUN@&?@5Hy!VLFK8h=WWA=8So#=qGTwAQ@g>@yU=a}aMFx(Zkgp$#`d{8Git+1hDV7>E~|##tQ)H{Af`mN@Jk4dJOuoJ zfJtJIUbhc)yv6V~`01rVMsPhWpA8p)td&XDP9>Rj&($)K;*1GP@=aklGld? zIrg5q3_UJ;hI%>l%yVzU>#&VT{_f_nY~)JQcic8>#%6VqDoo%O3FD6;N;NvL4y>c) zW$JDD1Bw%2DRCRS&L_ew_9ekD`>O7iWB+IPDA2_97C2a+v#@uOw`6VPl$~*Quq@XD zgZN^pIx{abONBT<@c=U$wM^qF5Nl<1dW5iGw1WlhM9~^rgO<$TZJCwfch*AxHc~>I zpYFF~*5VE&gC#ygj^IC(n>Xk4AIAsxKtE`41Uy|5s$aT$c13|@(lh2xPwKuFpz;iX z(a2V)HY^2*Sha7VG9 zOg~znyC%<%izp{)Y!Cf6QrPz?A50Imz#rb?X>x1R%C@*3EAMlZ?M^I%%C9%|Z%XQ@6Wp%CWg6Qno zg7I_cyDo-SeKQT8LQT#Fe6AndX%{Lw!I$F|Q9W@|EZa4@5>5Dh7wW|ns5$+h8M0VN zPii#H-ztUlV{`u$O}(b;n=H?~LRv5DN4`X4r}YRK%Jd~Ree+><-iRx~ynu`r?ZRfh zWF+iIEczWSEB7bX3NgCt?#6_vbDcv^17;o7Eu#EML-~(4CR?MH98C+R6e-@|9W05w z^S^S;J#^yI{`JZrK6;wF<4Mwbd^B&p@y*xDwb_%#{{m1K7p_JjVO6}@payJ z>J`NTP+~~KCAd;^YvjM-C(fEmn`%vG*|maRMn=c@|EsNMYLpLCUQlZ2c*gvzt^s~z zr~!`ce{O)kmYj=gN4`9}nDYGJz15IdFnSK*wqK{h(W)-3NWsEzM)I}EKWvnE~wvU zp-+$+RGd944j6ij&dU|o%S8ic2(?E-+Fm^WyZ-1}1TH^lOfyRupa_ZGN#Ndt4z7*3 zHIqU<*=GhHlWy(z0)_&C=ee|ur}tM^I=X*&qCAaUChrk|*~o=nw(pEQuZxv2bNbm4 zfVO>kP%PD!^!vAoiJsj!tByY=5Mt(_rA*JEj`@qz=M;vJuQI5txQ!$I*kS6oe*$@j(3HNo48(L3 zx_GThVb1gz=Az$4@3x56R7(cGUm$P{`_Od~%2)SKo{A*ChHEc<1Myf=?R`jm@5@h>2JaZE__MkI!<} zS+m7c?baE$ty|Ww0l*OW@E4WFe*p6mER{GF#J^Tujy>XnpGy-in0d!H@ni|t_h%Qh z*33w~37>>d8VoyN&Y}NuQ#O&J=2XsYYKm4902*cB)RfKbaYrdjmGPpzZBa~W2^P#r z#M}YaHesA!Djvl*+4InWm36w`(sMT$Pe0H@@$#ex%IQNiIM!@665;?D`qp$Uq)V+| zgXN%B<*flWbdcf3R<+s>3^PmpjHLE8(tT#9mbD#6eV`?UdG)stI%>NX!5yoQmlXJw3QXn_>kFN&5rLX76>?S6~ zG2Z8|s7u>F@-zh=l`*-N0%isbjwO zlv3SN_C`d`-B4*mAm)ms<(ff$)Ow78+*+&Xpur>%jE1?dX4{(3ZJGA=cJMd!$m#`L(Ne+SOhkKuXGtOTm7~20s^U z>sBmnlase};;Z>8U}|tTXP11$0-O%t8?7AFoA1~nb4z|R#CZQz=uH1uxxIar0&cuH z^A=nII6cq$6?xcSjgCI;jU`XpuYm12(QMD(#naY*jzA-7 zKDber`Ge?$y^L_tn2CKa{Hgsfbv&ZMrjWC4^R~*=xY)I-*2K8RrI5;{+PkY5$m6fP z{~R`oa-58C2OgwJalIOTz1R8BkJ}ekI-Njh$HXPy4eQXW8Tq;9Ms|PP`qXWvAeYL| z?^fuea=;A6DKuOW97s0JLk{?3myaith6S`7HtId1txOx9N*o8r0f3a(=|et6VyIJ|ZB=RMSxG`;UmB)i6by|C-xfjarbA zT&82wLGtRm0laKNv+Q|_AIs3-p%f5ogAcRH7WgsWIq>%x0d2yh@SO*QT1f$*FK;SX z$CdwI5uKeRsrkjw!d(oJ%bO3SeRq2UyrHzk#^v!#g%(Qs5nqoD06m&E~KlPwwN+BCVOQg95KJ`x;7owex9R z7i)&!=p;C_o2LFjHYJ;P$sNtvQ2NPKUTZU z;mZ*FN6ay~c$w+_weA#C4V=b`g>dfxGdqdN;@HEjj z=SLYMNidE)UMk@hwDau{b?y}7e<}s`lBzS}_m)X=y<2&DpLo@OL48LV`n0fXfz? zuL$=EdajDu1I(SCh^-RXl#vXVehhZIjoaw|+E3hd5UVOr-jl2i!tCvq4EaAIE}cU4 z3Bs$2=5NTu*5=ubl}^}X(-6nzigeedXVO*t)BAGR!tVii-uTMK0Em+4`5)ziZ%@)R zV+a`dkgfMt#Z~vJiTvo|Z>&wAjudX)-nvvRuJ3=gcP(drOcgxyKb2oR&vY;~_!gK| z>)6A)0`KLrRohL>T)Z?UC1CM&$NY|$9>Iq-!K#LPKXj-p=cBK}Z@Q)dI;>FRRUadl zMqXUwd}~efx~u9#EHaYT)c}oS*Ht2`Mjm?tH};DUp^o@jJqzza5tF5({1-jxp;<0e zmksu!ecM#vP5ou~XIqD+P!u}IRj+inyKyd-5gCUf zELhUtF(n6nFWS=&G5=DYDmQ*(Z%+(6AD*t}9hq|td^oGhSRNm-o(*DceQtNw({h>0 zBq(G=veNF7GOq$2UM`F?Jlppw#5cVJ>Csf$AOgo4!y_4!%9_nel;W{Wfie!5xbfSU zr4~>SCdwU_Fb7Evt87AfYKWQOdyKt2TlNw3t+`EuSNqR_D8`EP+tEU}Mlp0jeobi= z+E`YE&0UqgJD92A@8g9voeQy(IkF+FJT!OS`88rl@w5o1J#%Z|kP;5mPT%uZ6s(269 z^0r4E9WI3lVN57z)Wq;6u+!LLo2&Q{u%oM8pnP~H`+xYs5I5KAMq{s9%jk}gHrEXm z--z`{dcj)yGU-m;)BB2?raAyGPUT&j+vBVgcn~oXBA4CkH++^{!`NeTu9y|OTo6?! z4Dp5?crPe~FVkjZET-$d@e4e?H}03DUksK2ySbb1I~<&+`YK{Kgmpg{46x2xdZZzPSc&3GY~rRjWGMH;t@==@2IYlfmz+hWiGTfD&Q82VBhKkcCXDyqPyQ6L#NBYm3eP z(HhL{sX2{MRgu{Jr@T+nI$AyCKHC-XYMl5@Ada(g|)XxtH>&(u-yxmFWDsQZ->FDDtxDvj7dFDX|4k=oW76;dvqsE%Pa<{ z2LnjC;@=iDcR1Vc7I>U*we|cFpP~od1 z{2%tQl~{2@Q1FBa)&6(P=cH+%;Y;w}>v5o6fD=1sjmvs%=Q%6z;B3-JES*54~&kopJ)3li+9Q`58E-Ii1rb zwSQ5TX2<^|`-@Q%ENK(7zu*Wx5}BhkSq_+*n$`HwmC+Dn$9wA?d1!dTOEW8FyEEZ} zacQQpi2;|+EZT^iWpzBLUxmJGn2duJW%4bIqd-p%&<^{NnO?}}%WV7`a?Rrn9mKoDb^inW2g2YISQv#XC+w__ObQH zSn?6jl4GVOU(O=T+&ypIqi;68Eel;r7K7e2XhkZIA7rq6ar4}Ij?bitGT_-=wfb7| z=91CX7WKQ4V zV`q9yUU~$njP#laqC)S>>ET(MzWm?w!3~ytAk$7%54QevPw>#TKyK)w+by$q+ET!1 zV~5>d#Lg^MUGIeI&B?h+|KBKiEh#%g<4TVL<`a}8=ol)y7u(V?yTl1>(D2m3o(@dU z`e&6E8bYTBEXVzLked;b2q}E}s_n$a+ebcQ-dwsxTy<>A zf+kt!BJWgTo|00_>aKkA;)paG^Q=`16K`=-^++Q;Cjeb7%0D9oxmFZ-L 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

    Cs?M?DRb)9JshecA4& z#vxl(N>iz}xT11oScRkjN#GRxWZxbn^2==7=MIUO3E7Yt#g4u)E zZomlZY!RAZ%)L&#y&pXYoh{>fu-Tl8Ul_srG&VhFeT7VORo41+_5%u_GE2m&&e{Fv zi%qmcRd4_N)LU|oYz&xE!0I4=albl{tK*1nw}d;!9#5Ox2UFq24vcb+L}urmwP{&w zut!+H2bLJ$J;97GIhKyt=9+A!PSbDF;=8-@P6f_)Bp430OOQ6cu~%vvN3fO=+-d7+ zaXL>6&Z|+zDm+9IQP9i8S&yNCa>>Vau{GH<^+N2v;Xs$X8M3_|?5uZ1*oU2L?%#M? zMdRsk^ms+4U#_2b9HEA;HJ5)4G)WOpBsZs?X&_)BAou1U`8h2mzO73!eB5nvVAN({ zslVk+#{Vcf^FSv2|BrV`<*FnJTcuJtMsqW(RO*v6xr#~3Tsaau3`LQMO1W*75OVaD zkj*ecHgn6hnPYSAFl=M^`ThU?|NVNuU(e^`!C%xgExuQ&yy!%zbco){vYEaVDgX1( zvCKc=LlqMT0|)`Z21)tlFXRpx#sZ&Ljlm<^!b$x3dE;r{9{;J(`IBIh1%&MXqql;Y z*nx}U=r2Y2c$j6awFSpc$if_<4)o z;*K@h#yYe(t{J26ib|TT3I8FX$KTTIDqDnm@p3C=CbAyBQSt7OiW83)CdaZM9pFID zt7GwblOC}W&G%?`_><5>9`9XaB&Sto3Cz+-cz3I}L6z}uVJJEyf^IAG8pqK8DBvkq z@8xXZomGIHM+_6Zczj=fE$cnbZe#-2E*TQ#7ca%*3rnb!)Po5*WIA<7dH3Hy1; z?IX=yWR>)}SA4Omae)WiI=k`}oM$lc=2;$B5`V_*@%B~yAQ%mm*(~gpOHDWP4{IY| z<}GS*zMbWyojvE>m62`>&;c_ln$1O5w145^TitQ9FA0BF=HOw|ogy>uJ>wRAa3M%# zN8lmbUDejo8i7le2`$U|@P}D-`K~sc%)@GoKyi#xAG-{Hy?iL#g=P%%GnX`aV{mG4 zNgC3l5%~H~KH#AG3Oj4-(XRrk1c~>%OB;2bO5r?HZ&prd$G&sB>ecGpKwEYNJgAoi z9}-;*{_9;Zskq?xbdZ;)Q&9H;w@OA`2(A>r!|XKr554z$XXyQ-&D$bq?_oUR4g_2w z3!7i=`&eh7i`mP$#U~h01RlCS#@}rJk<5O>40wM_)bLj0C*+QmLaZw4MG|7^&V%*; zxfgFa5?)P4=os61oJx5|Q-R#tvSBM`Z+lg)&Nq54U0nh#m1VCtS@Iw1NVq*J%pAR&w2R>9psI!EM#`w$x}6_@3jlfA#s??i%%wLx1j+FG*&2 zUh1eSB;#*#+NDq6zeX8xY`+WdE@l2J54=O~av%Sx6&ueucb7kjClG!+2QTbmbeI44 zIQV|&g``h`hNf33oApfpOdHWOY(9;xCW{oTwT}7MJ@!o(p4sr_&gUnD1#1WC=EP}y zf-v@uE}kLDareC1u$)5Swdf8UouJxHJzWXlFYgLGZoYG~T*S$??hkORTv#dOHwI*7 zFmqTbV_FSjB$}nOL3h;9V0*Fe`|B(nO5lV zWi`WplvPaUwBRZrN=flmef&HG-cu@X`3fp2*n>svY<9pt17CzEP3mI46Wvy zJ5s~`;Q4J8nK$;gW zMPM_gUTtbQ7jC{^w5L3lvj&J+d{?%TiLQZG+)9rbS$YZ)`+TY5S zE0?39!7Pb#8+zSY(QR!;%9ti%05VY*^L*idJ!)PBu|~3rBu(Z$ZbZ`v{uE7h4A4qa zp23tHB7gbcV1nR!J@Mp<#NuDnlj}2M8u78~m&;dICdQ`1O=upW1_WKLN&+4SY<%?8N zY~GT07IYfb)x?q7OwF58gC}gombcg({^8#N3n^W;5T6EQ%RSMg-f&m5ob(>Iqv2)& z!NZ&2yy99S_yYTuxx=95hz7P7|0ryO8r$A{Y3+D&=P2xV>~IY6Rx%=d*`jFwa@Tkc zHy~Kmrd!DsQg!Tm5fPD|V>ql~TQ`P5-mNq8jjVhz`0R3y7P#WR#@+n^^`Xl_90}W- z8q=2P5u#uoNN*oswDPXuy--gVkvIxs9Vc4d%Rkg`cXelX2{)BC_O~(nsTN%L9=3Ql zCOtgeScyw zw%F&{;zv`j-?Ir}In&b#1;XQ%=a2qp#-!TeIHToJ`sV!b&i1P-BbY~bAQAZ3Imf%l zDJx6k8g*FF7Ao3Q`KTq!cv2_|FEy%(-IInsVbV7c(vV{~Yt+Edv5WeHJ$LOJdmb zDqOvcbQ#6TH}{)b;vM4|Y|7(5gWWaW`_*^x$=P&e#S=DSw9D}&XGwkkHh6(4C|58Z z`RXR-1y$OAb&-&lbcU^oPp%LcijOovv|Ji21?V4L|nljf3?4vf;@g zp-4Lu6&!H$%IH*3*LoqX>E<`3<&jJ+3uvo9cbtoB$XeS;<^`vVq^ggnVaXactapOo z_rW^@f$$D$arre^A#O&h!D8ag0{yc@ml4v)Q<`SVX;Z2wSEYyeuvO)pOZ1cbBMY6w ze)n_c%6iRKR7)<;rZV~CONuhI`d=ufdWv6q9E3>wICO@cR6G21k$>CpwQh|D#NP;H zmS^^jBUl#8cK&p4NMxEd+^)G*b3AZ>U#{4P%X{>SgH`9q)bA+^XMt>U)zTPW`*oI$ zMvG03v!`(J5%+^Oh<>-JEdc2p1GBxhZK>G8j3`9)S}XZfs3dn0tw33vI@EY*W>D9{ zjWc^P!B-El!QU>rAJ#vOOapQH@%BuRU-Jve4nL7) zx%8l#R!H3=0B#ptiKIG)zVqbLU6O>}C6hkEQtkZ?eyaNN{!Byv&X`b&^FnQ)O5k%F z&E)SNT+XE@_KHoH&Wy#tLM(NlQOWgx9bRx?nza<{^8ra?``Qr|M_vkoB7RXRueN-X zi|Sqev$WxKbE9j(bR$c7R-j`$g|My{v9DWi{1bCbuTP&m%n3?7%CJ#2u{VJNa-(+a zo&ZtWCR>EIeh-Xp*xccaW(z-;Ur*}3^{vnv7D7*FJE}A(aWB1cN1j&sC=Tju{MQppJ*|(2*AjhOwI6Z2lW}b?cETlLWNgj7T zQ=O2n=fJ@kZj9vqU0;*;gqdH8+PiVe=v2sysGA5oxeS)CV1Q{2@Tf+W39S3!b{^5- zjHa<^aG^{u`MwjMyKr+Ul&rZ;otE-SK0%EKYeIW;gtmQ2z5H~9OyD$Qa65}rnR$6| z)sH@$urU`u=vCq92aGaD%amQUT|G+3dY4BRKPL3>xQ4c;3$jD};=V`ibGr!IRThw! zqg53He&Dn}SvDmZ*Tmv>dMM?v%x53@!!2ct_Zq0F3Qlg0DO&ABtPzj`=O8RA<@(CP zY?IE}NF__F`Kf!2C%P)~MIT%Y21>fXWY5f0nb zN<*Bg+&o`1XUzo%#awg#w4$Y_nW6@=Hl_cK{5o#{ACGsK2J<%6`JsKGrUeG8D#Epu z6ALNvSOcM+ooc`u(Sv2^-70|LTKnfBDazrd%ab53TWYV`k}iYT z@62@?u{5y%e^SM6T)SyN!Iygfe+%&_OEcNJ{QBE;v-IJ1s?*@4PcUb~s7%@;53#rP zYW9RFDYtg_l1bEa(A5AIy<)w^?S-5=j0@vm8k!Z-`lQgRAzzWY=Hl{~axZ*^%HwBr z-=(M&KKOMZ&^hWwrLR%EAyxRvzW?J=YLq;9M7RhsthLN7vsGFBa;QXYMQNgXwgX)d z>?8CG0Z_kiB+VzHyIUK#(2pvLLjvg6mH=Gm zAd5Mxeng2OB|ND(N}%7LS&pabc?mu#8k0XwH@k zaM5k8w}{gItw{K2ex{s3t-b+xQ5$K1mnNE0GHt)*il9!sBZJRkzuwE0Pmd)dPs?2dzQr-0=V<)yc5CFL zpJ8B?WmJF@kSbYNY)H|*5-AgZ1~|b9v7PIlg`hF_Cr&^wY)NkJOG~rBhgSXkcTJfw z-N@r#Q8_A|k{9b}I5S{1I#k!9(49XWBvAAy0oo=tY-DDiQ1AMWvKM))e6xO=6KelP z&Z6BE-H4Rl2#C6Ae#nHTXL!=~)eucyvn!0IIpx&+B#Q)Z7Kq@8Z192p^InTo> z0|$;aW*he!q3U-)8qq`y+g6gK@)%E1xpl+%1erz8c#T&nxuw-HMRui0wn)+z@-_YJ^C_;tC7lVv@$lbY$bf zwcs2C_WWp(xRbTuUR)BWTz=f0h^MyTnrwa3m?y!Bg~sQRE;bH>{9b-5>^(eR9cGrd zTN{h#58Rji(Vt^Pc(taB9OLfuHtb#+F>WOcSNjxn<|lx?;qwunytbM>UL9f7rYxZZ0_f`kBh))x@0lCbt*02v5v80ASW?MZ(gfTrfDnK zs(L#AxnMdVY%lF&ygT_%DsV`v{N-j%-IKldKSnM^_UDxbm3n}8Oxu`bE19l-nf(#F zlY1qqUhHLXN_Hg2GPFz#w!Ue-$CPoac@HOyk5?oZITskjQn*2@(pk1&S>hCt2eG{7 zA6q3?GbQ66i(PcB*_Uv%#xv@;Zm+h6c?8z5UK0C4#2;eIUJs}B72-!8yf*(4h5mt* zL_Q~GMp*dAZMB>+Z}W=KPaOZ#m$DobnI(1*%8MHC@H!Fse*WlCh)6F!LV(}3mQOk@FvB9K3Ldzn}2)JgZDYt&zj#^Nt) z{VOB&2Cgn?)G!KDFjnDE&kNG?fY0R3d}J>Seb27BmKd)kYTGn)GEPs4W99=4ONPV; zsur|riOjEE9nPvp%P(;nHraW2YLU`9K2cV%X?VML1%NTd6syZHz zJ3=qqih+^&Ub&8HFWJ|h?jqdTD#3Un;MgzpKd9c-ucF?lABsbIW6F))YxZpf1b>A@&!;$+(SC|HIl#1E zGpaTB(oYZYn#G_WBbuMX_clKaNtigoiOJc;DL1j-wAW4Y){f$7zK&AAy;HkGqgd^n6Y1miFdNK7Aww&_h%vuX9FSfo*J^rztCW z$#G(2TA@;66ot5hdo?8aG$VXq3dtC9ctUHwQdIz;Pe+8U&e|ad!dc0zo>C>P4%P37-vK1&K;T{5e0nW&Z8*u7|7H0DuRX)x!sFt4614?xYRo#Gt{+jM zMr7F}eA}BlzAAz`d^(VH_EAOJugitVSy$f#B zX0^&sXvvNJt7a2hvmCs^8mHOdhfO(zB4zjn1O{es+(1dFCN#xVCHI9tb`eazVb%6W-?%mBAB1o!N&xjBn$g7

    y?~dz@$DKPdN~dQyqE$nLVRPVBL`kiInYJ(qO>H@QJR;;6g^=iRbBTGl!W zSld;v1VEBL(F)OP3-+F;Sg$-R%xa86#(Nuo<&8UFjlxRBk{w)9aUQ{@ock$18 zR(ig~6#h*p6MUx<{l{{(gR?`qjUv1VQLd@K6)=oG>IR+8r#Y(5fhF8EZDt8~h2rsSo@?cVJ2&E)Z8 zHJ27zTNv|ruc|~NE$4B3b9de0bwz4ji1)yar0MOEx2ufY)MAP zHM_`uMZFaJY-m9lb#e=h$h};kH z0hqNy>$m9Fo0>!TI>MP;MX@s3l0Lg<_Y5??n~aQ~_E`^Bc_UXH9UVFtlzTxg+vH%% z4pMPE3ed+4mQo>kEWHe*JiB{gWheXZ)>5-vXi)Go=zjJ^j=W)WNlNRxLD9Yz*W>E$ zB#i8O2P25U6(8jr@>o*^fpnsX-WtE+N+=2Ev>_QDRp~=Ev=k~EF`;o((Hwv&R^L^2 z7`T!)uk1WOalF$%Dt#;5kN$G=)Nd7{%3}xMId*n>|ETG2I%$g))jgH#_(QqyQnsT- zcLVP)drg(pB+*-EfB!_*adAR=)xDc;U*v02S6?ymXAI^fezb{qh9YI3##^pvau@X6 zhhuV&Bf?7J(^l(zbXsfMhp@(2cj|lb6FV%lv}+--^6ivb4Jk)?Wk>lNkcre{gDIiN znLmxuUeP2>JjXk5>=*hp+Aa3oo2W$&`jRFJDy{rUjS1<(SmNqm`Eo<5&0`qyx2jeO z>vd;=WO=Vf{n3FJGE=G%XUdNC2g=rxInrJ{Y@;6fr0^p$KPBTE;2P!^_WR>hDdgZ( zSg68=60*x`FIE$xu&oT1CBBLd*2BhKw-My~PTb+{VF~^V`V$tUf-n1}m-s0EY&7sg zt&Sg^)T3OUcCq(6y#yu`)uc`eQGJgI4ALvFbm70buWF+3Ca#QJSrf^pbB=q3JuHa~oKp`yn0rs~JUO4}?;Jdwi)eeW<^yl&Npr(3MG zM0C{Yyxvs*tqYPOI9pAn7(c#K=P4ZNPeog?_WgQi>9aqW2rhBb4Uz`kD#T*d3O$rL zpZ7Ks7;{{%FiHQtRLf34iRik1_5J}nhq~6efZxYFy3=E-qQ}HTwU+&sf@%B3fa<&( z^n=L<&oa}EG}da|-;1rydoLH|l3h*j5ATNB1GGj{a%Lc72S?RCx?au@y`wUBPGpkm zoh5EYCqK(C$jl9m{j-8QYzmGT>{Wp7U zPv2*C7P&3umfWofS08a$`H#(Rsy>d@RWuPKkYhI4*Ti~Lzs>V*_ziaa)(;vpJAe2P<0?f)BRG=MJ>1JBvgR9J~TQ$u-}nw)G0`5 zWOc?tEd?7cop@}4BU-@{`I~IYTUeZKmYR$TS9RKwh?==YdhHuLte9HOJ79D+)S+Ma zQ|2eObfa~8 z_BX1d2N(x9oKy-OH&kL=yOd4zO50~WG71rRjA^D7*Woz*Rs+^gI=SUFn!n#i$!%7W zVg)=u?wfkhaG{xIbx*#pOpROB2iOswYrq7xVV;j{^q^(`{^)%ou6QxT8P8*@01mQ> z!WB5k)RyBb$I1?{Ng9pe)l<1WcSL}3sf{<@c@4eZKe~1!jz_qsMxLzSEk11C7=Tf! zRYft$GbgvjZ;ibmbX0XXW8vuca_@`PSBWQV(hY7%HB$KgvudtKu)Z{UQ*KXb@I3*- zUz>>e0*kr4_@PC=R}&e!si658G>c`ri7|H~lR9y=C(8A=@U!GO)gHB}sDJHeEK9aH zx5`MZIk?dXN=5jMnyooUfCf@LAG>7HE7wk%Z%)8fE2W_i6oVe|m3nARo*<RW~R} z;A#G<67xW(V6)jj71~$gjV^k=+>|l64T*=-!6bokyixdyx$MO9_(in%LOTonE2M>~ z!G~pRSVCbJ_2Z&4fig`TTPHKp)+~c>YT2^2 zWl;4z6dBIeExj5@a_oLI+R}Sll2?K;gMWm^(T^}+x{||KL?8HwL~Ik(5BTGMV~-7- z1P+UEfF@x$;x-QWu`(1skw0uhdl3{|BMxJi*WBd9miQd4k=eK*zWfAWE0yF&g9Pm? zyJOaG7!f @e6_=jJWRjNj-Z=>0CW)CU4=`l+7UX-fC;i%(4=VGj~en^<+#=DJDi zKa)mv=vPRhFBb0;Wl1RXenJkYM{jHsqSPl6YnxXSM5=uvGYw{b(fW3RF!LwmN9;nX zTp(*}=*b=aGhYd~zK4g>fYL|xkPG1*bCY+}Nx?Php~se&+7Q?}?6tec7T^531Zu2o zG?_F1T`EdoZQCdeS2(}vKQ(I}vZE+UV9O9RV2js&Q#dUZQ!1=mo~fl`Oz>%#@+XHo z*-iJoh@j3aXNz3@TyXH)dy*aKaR0L&JlK-{(tXBxF3Bhae%$a&=WlJeeIOX|0eIOu zJisXQ$9_Z`E4eZ&;(y{dYk_@Eou7UmV~>Fa8-tC0;>4d(2vqf`3^bd#G{=36mwNCu zl$w5j(~PKsWxjdJT{h0N7^g0cWlb6^9QCMh3*HT(iB&2OtXvvzW7<-lfufv=-tumT zlUfju()2r1aR9@IfYDZyDvlNLUxzh>IFdBH9S-BNcn`;MHpew+*Ejy$D>sj>H-@(w z=puTH{w^Xvw=5!5`|%e;%PHp@EV4O%?9mv?;4oq7$jr5F=+*St^X31+9Bn6ozOT4) z(J}A_sWOkdGSY)Hc`j$@BQ|@Hy((YF;`5yo-uOXz&*_b*0U#N;LTC;$zfqGD_l(2P za8aUnYq8_wzS5k4b8mi@AD9ud_+l{uB;pTcu998YRz zT3B#mE|=NL_NLxYWS(r8=jAc-MK+)G(L+KCqs$! z3;ttUI0r83zq|ERCnm!Xte<2a^KuEba&11IRP{{?RT0d_sOVtpoe95mHjWlaEffEl zLfSY+@R~}k`04D`+8oC)(apT#A0p%|%t(_kInno6v@wO3dy%R)e>G>w*AA>M`au5j z!Zz1^IPv$LEuf5QVCZJwe>F00^3ktNOAr<^FA!TyWUf-!7u39PAu5i@v-i>pnuy_nK9em#5*fE(aY?Dl5F=<`7h`2DjQ+fbi~RI6kte-wfarawRf+ zHN#&1lk+dnX1y|O)aPB~QIMR9;=2;&gSO}CC8Z&a-o}5ceg;q*Ol#Drxatngztv~x zq?0-co0clOfK_74*hZ2l(z7u;v`h%W&G)-0L2!P~l}gLS6BBan5I!P3`vNGxW?`NG zCBj>L6+i7~Ac+1h0-G9mSjxOsoG#jI{1i^9iRg@}wJ&V7^(|{MZnS;6A`tj_9|LMa ztjW5AbDuG1Lt6*_GcV+4y^E7XfWi-O##Ktj#L08Um}e%tyr)nv)_n+1>P_Y{xd+2% zGbHnpTjt67P7qmU+i*ynMRzb4vrl}y`79c>d`={ z1#ivw2XyLYITfOdmzx`U)`n6N4O?=yy@%!&mEg&+f#quxq5Vh9RM)(69F1Uao+Z|n z)LK*rb%{rn^yhINdpIZK$F;_DmD=Ud!(@q8I>|N2XA?sdxzT+$+4oExIVxSCt>zAf z!u=CSQm&#p%G*p0(ONlr9!mXgz@G?dm6A>@%=C5@-=U+YM!(lZ=bLqDovJ8u$ zlClE)g5ZDh^4FbkGsdm%LJp>Otx6EENlvm~R9=VIVC%j>+CNqtjI@&;7u*IlNThsa zt`J%rb$f;kqu&tYaVeGj%U_U0i`iZx%6)k_X zpx!a1_;R(90%Df4^v`Gu9n8ID_VnjLd=el!LZ@FZTyiF_*&{QxWAfrhmj_ht;;dsY z{YrJU;g0L;GcLRxopp$mAct(D5x6-mdDO;#gD-BbW^W`)5XJqf3 z=k3kReJJ}3Hae^7!Ubd7pp!)-V`t>`?;S4pKdK7IwOt#6F(ie7txSPi_#NFp3oy>d z!F?Vjf3UQ$)2$O8A-E_*A~E*?{vPW(sE=wlgY;M$2=E5>hp)KF7WkmRQRXCA`2eqX{2e=QJ>AtRcrHTi_}!s zTtEM=-pXg!Wbtk17pX|IV+XHS&mS<{rYmtg{$VKe(oJiy;(a5SXO=Wpr68tU#2_Df zk?w27d{`5-7)7|;QaHGG$XVYt=V#Vz+2{)NtYQbSW{;^)nom8`H)^#S{qY`q(HW;* zh9maLDnxpToAs&^>!#Pgm{tj%;+gebM1(E*qH;3RpY_IgDL8fg*?QjYZ2f2DpGb|q zoWEmC!lziHx=tTcIvl^5z40u(cx`>+Crqm9bo6v%rKa(BG|;e9 zd3IwC^5rG>skH$Q!K}bsN!O!C^p)f`+{#ZIxL1y7Fqh!*p%h$n?;X^G98b=3?;;jw z5e3H*sh{?Oz4i>S+7H{V{4ITNw(?-k+}t!I87I?PHn>_^)Iv_JIfF{Dyaj0lu|{8~ z4xYtM7Elx;w%gWF>|c27h{26O9tLT*?Am*RcLck8a~zBkFiU6B4b_irNyS&u#O)K~ z#2lhrX!ovxPSy9$EzbI-X8FKZhHf|-owx0t5jQ@g>DCWr-obs_Nu{dR>($zm9h7_T zEURP{eWpqf%eQFX`{duJP?B0Ucs>aVnAzoH9&;Isq1c&(l+$N3O4Z;slUy0Vli!FW zU`F*dl^0d8_R8D4|0b>ioAf(nh{XUqeDb;g1~@-_m!IjZt?)nGba`Kjf4v&{KOl~I4tpzi95AjBVt@?!7X$j#50K1PSmIC0am5%goR#wp zI_%m;VYz&}S2-~QFgpTXf;At83@?Wn_vLtEj{?jD@2Z=PU#JPMY!lcHv2!iE%uEOh zdh#L|8F|ZS_b6EQXq;h3O6xWY4$|`E6=VmqayG>joUuRpkzhEt(MGJM^Cg0pjR_1> z-AY2W&Ize29o1(xd%jIcjE;RqaoC?DON@5@{_T1PZdkj(unECpOy%@AlT1%klB})F zi|vM;sAu^=(&1ZEyJ2f%n^AV!l=d3spk`@9?(=$qSD-D%vwHUPoF`Fpu}=4 z=M-T_VqE%6;pW?W%NuKvqHp8(P^r)+Tq-Woh8MTmG;$d%^kZ+C8#_Naj4Lq7BtCi{ zpD!8+hhg2QYGcTv$E>;hW`m=5lKGT{mBN0(S1mT)Fl0N>BFXm$D zZvuC*X0_f?XIhcS&9~txY!}LjeD!R{$ZN#4xPC9pow*_zO9lVsbk1-&Jr?wbHU(Mg z9C7_u;p83hnqzbuAS+IBd*q#O}8y9d)8syC{$#Nw*Kd%gL?XQY%C#=@> zoF~VBIR-b&xb;R#hOq!#;j>Y({qQ++jX3{sw9xqdP{2c3l zZJpA_dkbxQ?b631$B&C;LHV%w-owra>9`tA{as?sKUs_`;7{ul5+TWR@zbGET)xqT z;od8m{(d$xm_X+w)9;({>a#w~5LE-mmCtL8toyt1giw;Lck*mp!U#gH7{;s;xc2)X zmxJUw1nV1~p6}qXh0S^GIcJEKXt$)#Y9$GnvzvFY@{q3Jw92p1kAGz5Lnj&-5{O)u zYwqc@T{BL9BjUG$eUNUVt-8F4`^%Lxc_c`wl1j{EJ}Yaav{i}y$F_*Sc*uHqAQW&M{qGDy?b{t{jqN*n>M(?+?fpU;t=;!H?sv$Z|Cx^{FMynD^t zKWb1in@YI8%4T@a9u?1StwYUsf}LlMZmL-CA%2BDR}!PB@1)19 zDQcZvuYqCeGsBRoZZhn}nsL_+cf{F(x!p(LWE)Zkw}^XQ2$*|duC}(ep8^*K^TWLP zVHV|Lui(k@EKb$Pr%vURS;L5xqbLy~dvL0vYVrGBrN*N>TgKbP6Zz3jKCUE?aLwU!& zLS~X^Xi=1T4!S3~e)>eKh8)RQoWNEneI$S}f~YZaJIZ%S{p){79h0l8a)4uJ9GLwX zKvEEhIC0Y{FpA^6y*2A<7zfnn-vZkz%Egs52mG{tQ%+tE^*h zey&QQe#|^{crm6ub`4EtrbR3~2{9`i1|FHyd^HDR{*gZS#}id}KgRlY zNdOS|_nI-s4ETV|WL)(*h%rV>A$9tOA0!!vGaqnA+u-Kv6lKf8)=szV`B>iAW#QGa zS9x}mHq-+~CIVact92oQ7XQfQB^;Pl);-0mW{v~XVG)=Ew$BBZNyJmsv;kI9nQn2t zDG{{jobytVDO(1H-YAzSKU>;a$MC4^&4sbyh`N@O2|u_@cwE>j;!W9p^~t*nO`o*d z8QfYo|Fadp_i-L>p6~3gouGsch=V#Z4RHL7%zoRKrp}28>t-B3OWMJWvQA@A=~w^; ziFXw~mb#! zS6i>57K!|fZzC%P7;W4v+kWwsii#sSHNkN1aM7sEVo#j1J}zkbj4 z^zHR~B0d~Ra|;yRN=6%RGn;n}PJQo1a%VTSRY%MY8^s3g75Hqv5bVAO!-`ui6MGLu z%$ipgXdeN3TB1+L$wFk~Zz5Q@K6q`cdnCdK9XY^O`+e08Y|Al z8?U#_mh9|1ZMr>l?COUh?LtkK{kTUmiOc!p9%hZcj267&+L_!P%so>@FBP(Qz5E|Rq2BD-0V{dxKERK`UDS^F zZ8Y^Md^~NxYEP&gqT@%6GrF`s2D&}ElhF+8@rzjp%wBFiJCBMG3a5TA)>T=2OlC;W z*j9B2L^g|0D=T|))bScN_o(`j&4lsH*ykah?24R1T1)ke>-hPvq9S+V$Gd*3W9y5l8>1>r}Z5CZdJ)C_$aU$p>;Y~U>L1|jzOI`+FojEQd zXZ|#mfIYoVPX2^yQx>uYZ2K|P^!S&$%}LP$4|-^WymxYkT)d+i-k6%3VqYEuW&`FR zOtpMO@yOKUs8I6@h`j~|lDTy0xP#6-7w<#eOp4opyg)R1^2cIFZOW5_EZAkjE{_s4QG|UZYku#pp zjY#nHo?JB4j5dirsEsvv7!-GWo1lmN<29!Dwp5;-KRr zZ%3lv-(CFM3`E-Gz5-uNOyNw_i6X~9VV{lLuwd-N)~FSDTlIqjxaP)MWy@=MEozZE z8Se}Mt!=lOq$=(Flry-?GyZD>_m89VFa_-H$#2&`YXs%cTfdv#&B+?5!|l_y51q*y zpibCy$Bz19;zg3c4)C+YSsSxzj#b&G$%S{wgi4>PvG$%k2#|M6?)=89&C=~7Yj*5C z_?osmzRUR42O!{2K~Nwea~L0lN%zy^N31+)Jccmf%$rhjMd-p#IgSqPfHQT31iJ5m zKmL?AD#zKa7#lRH-vhShwAi;rphvwI)1&?a_H30Ace6u*qal!Lzg1wEe_A!-Of))3 zaw_WEU_W-!tDG9{TyBd1q$hZ23DIecr|g7`^? zKC=hd`gx6*&ny2W42i?nE(`-|G1NSMQpkp%3hz4T^{_RqF|W9F+zotqhB~J%oDwxF z3HKsmOtbu5qU259fm1?x>qy-4OO2)!E|rIy_~G*cf6~YREE#;`rxt1kn`27QF`dqB zx5iVJ^^N>~crvWFXm0i{icUSf)s9OVw%-KXQjU+?NF$7I(9$tCT_qJy_yG#iJGe4) zbl&!8{bb$0YEkaCP3d3bAPfHQyuj)~GMd7dbZ(@LfX3h^qiKw90PM)H87D~j$6Vt4jEa(j5iZ(5%YogIuAgA@U@dIsnxaT zz{)k=sVw~%`H7dGB)i*N^53lKbJjlgxiH-#&Q8dfUw`ur=6cdav9n@#O!~7z+n|x3 zDKc@-w1O4zh@U|mtk6^q z-{TcknUdQp7RSD8oVEzvXlv;%mQ}Rd<6?XjI&IvxN<$oSyFR)O`0&ddgirEO_1Kqu zJDu@!dZ$W!)SKJ={5Q;*((6X&+-O(Lv1YUQG)+%hoaVCqo-w)x1~nfPcV6hOLN8NuuH@t^*lMIkgF#K;cL-}%lrQE z0<;O{S9k~DvE{$kmt`8s5020hy<5GS4NIN!I!63oIO~{RqVnl=Re5twnCqd?{wqRF z7a)fU^6T8;{zuggK`J&nhf1wyxPEhAsI`ZqgSdx?3Ud0|9gu$Im0$OFR9@=8%Df{! zV|3L$W?jehjw*AEbaL*HxwdH{O{W;36v1%z*%Xz`%2WwU=FOMS)d5I2O>Ae^`pV_=Pna`hN_ac|6mP zAIB?2B~&UA^DRZ?thsG;t6a%_WayXsY>v%lLP)Mkxot`AV+y%ujyYpna*Me)x6LqP zv!DMz|9t-WJhs>S^?W^fE=Z4%RTy(JUDDe!m+J$&x1J6$%tpP~Z_F^&)0jBRKkG}o z3r*}5Yb`4d^!u**T>FTz7&fQIrYUlQ<{f6&fw`zSG@`?O7q03t4tI=8~ zTL^y^21GXmcnwYKz!m^@ezK3S)ihf%khNqQ5~cNSH69x~^EIEP&@HV=%uHsv+wGRZ zm|IqQ=@-3He%U(ozRA0AoH}}2a{j>a3;h%aW!W@k3=OaopjgQis6Go2&gy zBx8rVH*3LIu8@`zb`g#9|EZY_krRNcdkoPs$-llz-Yy*NrxxsT0#ri|>9zvi2oi2& z@?0>bz#QX`uCUylhxn9{H*%*lw~~A^K#C;ENvuxji`Un=XZhKWmjt)O6W{$xykB=2 zHs{TLvEI!_X)~U#0D4#wo~R_SOA6}FdS2&L{eTtd1zx%QaFU05g|)DJA8FuP&#~Eb z?zdnGW&Pprn919v7jL<$q_Y)vZ_J%V+$8>ouv()kPG3b0Aw%7)L8rr##n1TtMD*$x z;PW+@4++LdiPz0ffu7hRSZh*D@^d+QRzGJ>8uy+1ViPW*uG?SN+QNi)U!vwN1<#yU z^%PEuS&nFMyQKPp6^@NoPDC*}P=oC*Z+N~LdxB!l_;Ovju}HW*vUnyHNaA}t`Bi8` zeIq&D>VPm2@H>|EM6Xe&7V_d{!6ylQysF8Fy$!$=813Um+G}mxh{k^8guM2Um&j>Y z*P0pe@ACVUem6vI+N!Am?HD?QJij!?qOKrsz!P~r!YXRg%IdgR7f7xd7=JHjwJ{T# zvh;-|A@V&x{iH}c6T8-#@T>BoY;h{pjEI07jI0&2Ge(h(p4Q;p*I1idAwu(a0YVPK zT)fK9UE<2EvHS^FtALUY;BboGZWIpcn%OzCo||#)M_+|XN<$&a5>uO0>k3Za7V9r? zl+z5EcN|&VH_y`bIyJi>M_8qM(ivUdg2A3*5o6~}3LRR+LUr}{QtYnNHg#H_Q2(Bq z70q2lXRzX|bgqpUW?8TZ8mgL-ZAHZ4zY`mC?=ULq60_(5b1I-EXGvqH74;^FN3h;X z=+e+s)fAU*7SQWMl65l1>ksZFJV)2js_@mmJ|!=xpb&fe$E>jzD1-LdVPd? zmTThM#!qgQ*I`1!wq8{=w8RYRl}Wq&GKG&!XGES=CYg8h1dT$_1NNf;76a6>>K+Uud@2jZ-!GC8Cevv++e@fMgwb zOxX0r@%3Wn91?RdP1dB*bZq$Mqh-(eQD$QA0wZ)Mf+}@RplA}=w|OXzhKml60;X7s z57_q^wFbu#kU_}b2L-YCh7TCF*`^6oYf6|7gCzdyc`38anz_{`HnVa;@X@TnH}S3? z$ljSBcpHiZdNxi!Fq(ZJ6$v}F{Udq9w?&2;G6r_lJ(xGevxm$Xt+0dSrt=NtbgJ+Z zqX0X+pBU#K=o{{{OW`t+`cIt~9dsqNTiJ?cQ!EYNm=@&3p>Imc{{|;FyhssXJoO6? zWlnLtHNWxWJw)spY3xMZNFk12M<|Z@NAzfBMp>_PSKOlTZ27`*q{FV9pT%Y)Ay+K^ z7-Twh0IhsgUy*{{;U_Fqf9*%Q;hZBTjnMO{9Swi4Fq&(vB)Of?pxvU&?M|T2lP!3~ zO2R-Qu4vb@W-Vp-u^zVZ9QEp6Xg+rtq_k>J?{3|XJg_w@axxme#jxHwYD#{Fzjry( z1hwXz&3e<+eg?)L@Bk_Tc(V32p@eu)lWD~@Z;Q;X6aUxl)c26yrNYHVEP_QqWm-s1 zg116?DfyN1`J`K9rLgmQr6YliuOQRSKX*mut9VVgNl&uR! zSEsl9j~cA_5&EF=cEe$E;rbij)=7&ny3kl^sqdt2jl+@`Ct^gBSX_xId9*GD9Fh+OuZL#9TID_5G z2LZ_eUT26u8#vZxrqGr?EQRt8Sb^hLft|} zIPk1Cc!Lr++eu>*!o*qfMN&tZt6)>pBy144{pe4;@zYYZ$yjpmHeF9&E|q!acT0$< zqksKXt``|KeNN&y=2qC5#4iQELoMZDVvxmQloYuirC|S={YVqY{w;-5u05t+@S-`! z+vN9yY%Z9oFfYgf_{5X0$f1)jnyjl5DE1HF4-`B52RBlaqwX%AVjhLWzSPxmNay*E za!}|mqgIvktb&}4r|Aq|%JGTm6}ouHfHYD38BH7O0UGn zObUCo{{WnNi7WIUCf=;7?UB$PunVQXtdvDmDI_>i7MX*n8cmZHUB0j8wq)`*xF;T z>xHl60teuwyO^J8ZkSuArn9`%i{TFf)OMBhQnklzfCNKKV)~J!Ie08Qz(z8a5;B>r z8K!Xnm4nlvkJXO zi^8O={}TR19sQuQb9eJY0_&z_-!qNwY(i6s9lQ(9^>6c2$5f47)FAT7brfd1H3uD@ zY97?zecyZDjeCeYBRrpCCW`Pg(gm(dkYhN8aUBmCeAyqzyZ6eHHeHFsmE4&hL~jiy z>xZMGmK{XLXZO3`HDtc#vtSdU&P+v(<(RKluyW^<#{Bwmy!#AA(LY$0qyc7Ofh- z$S57(W-5fD9732u)U~1But5IA#TvM}imG983~B8lI186cxz_8(I+;x`7iMk65SD0w>vbdzZN8HO{Be zr!^GN)Bhu`FrX`UZJ@<2Druqy@-T!bCN;Zw9C3#tjU&l>ugN4HGoICGj+&LafT2!x z6kkxkG>AL{7VLKjZOEE4tG}Ssw{{vcoId^X?I7%&lcoQY1X96O3jJ2dkn?ejARsk5 zk4z8Wx#sl!S6JvX#$lK9yeYfgx3GK5L4chjxQ(_>!nYj={ij} zYVRn~^qUvc?7D$RgBQdt^f!Y3f)-SE+}V~del|}9N{!%6ew<4EI)pe#MaAX@@>-Wi z*4yO{0n=ko_4gfANB6DJDtt4`qIn66-7N@=R%u=1_IO%5o>Ca%NIIFcOzO{{cUyl? zA_x#!;g<&FU#4C>*y~$>&Uc$$`X}Et`(RlmmnTch*OHHPf`8o-ACY-bl7^m)66p+^ z-EQ9?M5b=G%{*!sS5riGRVu}3^?OL^g|X+PZ9h(kZH_MjBv2nQbB2X=^c2+$$Q!)Sfz*$2G?-V0yx}A40N-Eg{@um%pg;~?^DyPCwiqP)g(&Iheys5# z%i^VSDnur+!fj2Ohji$hLxhN&?r_#~l|65HY z{3uRm7p|>di0;_>TkTKa4T%WP#m%>bg9rHK;w|uV`hG5(x-&*}fb;vk zcZlx@!qCi74z}P01P#yixCg(JRN2tpzlxl~O<#cK4L=6ugVQFjSoWRYB>o}(ga1p; z<4&vL?6eLg`3#96@941b@X3Yis|v5s#A^=@!Y5aR<=9uHVf=z+H&T@UF!8^4ZPu1g!S~=@Sf4{KT3aj{PSn=fdRIy}0teWN42+?qA+d_-n~9Kso84 zCF%L=2g<1$r&Uejv0iV_O9nqvdfrrgW;$UgOx=NfGD#SlKKj~_8EPy!$c;p}-*OIb zAUAm95A*)>t<`N@eg1Ohy(31Bf1WtSYl~xU&m1MbBFxUju=Cx+J@`FuSdMYgt3xZQ7RtEigQ_??15HQzTZOy@6OPtI^tmTp6 zsfmTu-6H>Tj}wiGRiNEQo4XY?^{ow21?&R?S{vj$f{*Q7da`wPzdv0}j_unfxpf>9 z18s}^?*b#g=-9kS;G9(B@B0BWov-zG$i_Z+ij-a%{Phev>v7NXxT5||>U#)9KzJ+5 ziJ@6>#NZ7t_C zk+c-N9j3(0N@8El)M)RQBh?$#H_z@LCf8-^IBLAdJK9o#aOtIT`Q(?`iowPc@521~ zH_04bwHxL7+^to|*z=k7o&<3<-l@b6U;6PKsZFeX*5nDp#aDG=0Da~G$<{Y0`8q`$xZ(-jS zwSas@M;e@kAZ5A7)|b9OBsx8U)re<=GlsY;gn@!Yk(uQE$JlLNtB?ygbJAP3t}d$9 zIZH9iczI?o&!A3*Gf-8hcDAAY$(W5!i4Sh)OS`_BnVqqD7-<-5A1h~R)trSe8Z;K5 zCHoTMpYEOjN4oUBd`12|Y8~`=^`kvWUfx8@MCE{?pnt@dO*~I6qsS+9IJdNi1P*-C z6bSr6lN;`d+cr87W3gRM^*!x9CVKyuNtWeal@2tM49vJmVVTWVcRujd#uZRzW+Rfo z8vakS*}pglNhy3fK7ZYDnd2aLt+P&!9*$QCb7i*y_W^3t7mBjoRsuYsr&sS=l_-9& zm(%SL4S0P~qM*fuER!gbB6IMCN=Z&Gf!Wk};e%Ezq!LQ!V-Cws0~z8@ zKA}dMRDli9{N2h|Y^jMxu31c>e3n_QVM4xseY;jAo0ZSb5T+{DQpZy^ZTh3Z;%d7hgyU7!Ol>nm;lti>&5^nHJ-&nhgSU=BU`K}=1D`Ytk%&Q!R55L z6?6tW;K9aCpA;WbLBh)+!Qvp(p0waN`IfrbzMVD^(w;`ugxFl0iepE*PuPHN{HPzhX%Ih{DRI!lxK6;(ux z;`<_@ANjCI)NqGkg#P$rUFI;zwg>7<`=WAmYMop zgAwJkdT~a&vPJ|IYWp9doen>VT61lD#@M|0 z8Bbi%p9mX&{nYtaZP01>RNr;-soYce^p=~&b^MK*KCI?Eu0LiClQAv&9Tk#mlrUHPa zV1^VypObWVwc(G*KH8M6+kOI`9u%RMB8}21-6`vQ%aYcJ`nOsj?4Y6*9{k3#yPzj7 z)m^*8m0!WvykNAZteywNa6(3Sr+`j5ldC`x*L0{K1K-Sw!V0CkF$ zuTgT})<=V#q0t%NDc_Li-|8In^6$3=&5-j>U$7lv5BFGF3$f0lue1!dAFd7{lS&%S z_q1Kp+nb&;0t|1xrZ|2ur4(hnqm+u!!{@@(PJ+{ZwL;>ggN6rcVDh2Hq=@v?;TYeU zTRF<>U)Fh(I8V-(19#!q#>~*h(Fzw*D@XrojHV#fTFWeqEQXKxMPBwbK16z(^1lB( z1SX19ub$j!nN#&0lTfn7s3h{q-ELf_^$x@<%L&x4zt-uMwc@I6EtzRGkfJDVh*PWD z`GRy0#yJAoQVm3Ns>^6TvH+pkOR{8f z+j&|u(-S3-(zW}?Q@xL~RtQg$4iwbc7${M;BeP)sPj(UQxSO1$YRY0u4mT%l}-z}4zT`|{EuIE!Wi&IbO5A@ z3i(VkR_>Sfc^SHfr1hh?>QX&7_rY$A&Pbp8s5z-*Y0>GLF`g{}AfZ++QzLy|*Yo(w`5 zQ#U=mF!3{aGrak-hzlk&`70K!mo59%ILgVbfm*bv|NY;ejkZ?kb8?9RMf%k0-o6(O z`4g!MliHg_J7n9u5|$-j#!^ZN8@g>{iz}FKFG|TgZ3N{+(AC;gsi- zD;iQsoyC?6POn%$L4awC1zo#zET$+tMd%UTw|um^&lpCA8~Lf@oHS)eE+$rr42Y{L zr~wbwJud1M4W)x|%~xKw(}-iGY<9+QaQ%6L-_xOLUFo`hXv@F;6@SKS@Wg#`%i&lZ z&@GI*^6N)LuNmnM{~jH}f~JefROLY6kUH@hk))BE%IDfba|iHyTVrSK9tHYffKFCD z+I}YPt)34tsRaW&&c|0Df@T9-2XVQO@dP|V%icuN_pUPFtmd9K(bY@sanc@)X!u$< zW%Lj75^j83gfi@PwN~7r^BPaqdVOu~Dc4O?ZeIYZNx$uU859GlaDV|9v{VC-uMr*X z*6e7vI+um1zf)46Q-H%_2zZ6fvLHYnlMVonY@N?SU_*-L#VFlaS@l21=_daeSJfxC zhNyurMekdAJN!FUOqn~ZZs+omet}~Ucg<>nHY(%UtDpkz@Ecc;U9ZSl&X(U>_O7GM?d?D5Z+)35z6p+ua{+AYp9n;wtC2*1DIych@Fb#%9d@rQC@h~24xMmKK1 z*Ze&1s(Ok3-~*32tyY~GbvmP>vmpZGC%2X}5<~Etgh{y9sGKO%SNbY9rEo#gl6S(Z z{;A&*?Ndyixx z^wD)QojPBSyrwywWf{Fncv*i5MF+s#UhniI>eL7i(d=sF8RO7zrVHX?xv5VQEv5e{ z^HObv5>+sLUe{4Dq*WZN(}0%$rPy>!rBBxVUf9A={j|S2fZK4@|8#lc6B&pZ-aH>pDN89Sqq?Ir0{Zo(^}5TI-NcYobpt>fpQIznt$>;l zSF>|dGt2i0@umi&j;Yw!;|RAl8;|hM&LrsX4X(_B8H&U`MbRXjD=ws9e=X0L_+0xk zt)^>>v%Gm-_qFCfoHttE`Zqg9g(cdJsl9RWPCVxxmUJ^b-0d7qR+|2}n9oP(!a&0y zTK|^i2qMn0eEGSI7P)n_FTl$|4e$^ruPm;VoN`22VYsByXdn?Z#ETa(w}bm?l*gQ$geUWCduU~hM+u70&xp7AtGg$bPogI`}eE=x-90@x><(~t6VJq zobSH=N0|*?@Zy+~lGXTLkOj(8Fzu2XRxyEVwHNCHRiY?2Mvf`BuP^QnSiip3bQOEn zSFl{tD#!zwFP|q{kT)d(do$p_yU#CaNUpWYAercHMx$>krToKv(eT)M@a(H8^rdu38E|6iWB)r?DBp#V7kc@fnO) zL1U(k#WH%?uvgiC$Jt@*Q(HrQO1;+x!;Zxj^7*~rC9s!z4dK@jeEc6SrI;8MraDNe zAl3?W+1n_i3y)NS-}`<|$a@*6=NC>z^>0yU z6_zI7BfZI7@gG~y{Q0XhX1;}RzE5zAQuYV8-km+8zi?djB3t6o?BRaMPXp(xdduU} z{|#R7d$)BWxz^I*2-JLmbPzlp@=(NIv~NB;u~g7-vpOChgfh%187-y?GN0E8OQ@oS ze96Fd8eG5E^^1VJT;_Kw&mcrd+8xaZA}&u7J=cARJ7ZS?Cd1#hhgrNI4%y;zlwHHI zwr|}cLn7>;y^Vh^Jvulayk~iI zldOpk8860|u;=9Ti9>QW2HRMzX=uEM%Zd1CPukx6;By``dTHXBhVBLXSe{={qD>^J zvp?)9-)z|Qv^LC|W>Vc4AZpRsb)qJqL{6l@kQT5`+%NE)RUu&tmp>8apNv?65a-GL z%F3r4jKY3t{|0Gtl0!_4j@&OMOg*)Y(RBhdmrhgkXv3L&{)mEI7e?2=Iqd~D=)Vg5 zt`V4iS}1yRm&$X|e@G9`Z4VBd%KH*qP;bX>)-rzc16h|>7&A5psP!H+6$hixWO znJE$$VV_2)E2J_1f!~YWUVfNun8;eD(zlpV z+)?CB?{tVczM0wI?=QyYCP`NSFH4AH+M#wYe zR!JaiZex#5#J|4Eci48monXlbM9ZZ(vn9D-#RtV5`Wa<)1x$}@WHF!Ln}8FDOD2z! zBO%k0=(i2uQr{&>pSr*`Tk<5|jYn#+rZ`i7O3p&Z#QBm3`<2%hXp#4wgm)tx&M!kt zsA%$VS>5FTFI~QjRfF86`TP?Lx!)(~xjORZ3Ku3B1kKly%D(4TZNTzq`nRc`-cz=E zdszsrNQ1iyPOf~XOu34VQ zRAX;es}bD^Hl%szM-1s(7z;Q`cHRgbjaiEWphDeu)9rkGa4K=>ezmrND$;2?u`&T+ zsab{lqRY?AdgYGOW)}v+NhfXx8*q=9Oy~8c0LdKBiND{)*1ib8QomZ(;|1aJY5Frx z3;&T5;H5L2WCfG*vvTzlEz9_0Wc*o*R=TEJ>VRS7IWVR65~pgcbtSjt(L6%6sm1;o zUJ(?CpfX{MbGXB6dXSmE#^2zop1{38{!>2Z}D15`(2q_TjcC_3w+-V$HS`m719|cW1gSayN_$TNq`?{g5aAnLI;uWR4&IzEI77 z`Gmn;QTW?AuSttWjx|%fMjcz7!NUW=j;v!e0)itj^9`=ycL{w|#Kn83ChsiN4N_}i z-|UKL=S}}jT(^|kOfV)+r^s>sJ#0zZ5Su)uTc;;@|)`M=l zlB3JJp`cXTcF-k|6iR~EdMRgUy6IaOT}^lLM$+u2xXR|a%FSL^U$UqH5$`jEAER)i z!oeD-{~E(dha+UB4XTfT)WE=ATTltRROqKHx9%R6N}e3WsV{wrCLn_Df{yqdRTSjS z@3L8X{qmE$5B$QpoXNJAxM^UE>GoRYYpkR8{xje)@O?ym_FzAU!;Ng^LvoORceS@( zEH4vS%)_?IyY#KL%rl1~@n;g+(nDZ;_PUL&E26d<>vD~8Xjwgu&T<+o6<8}?ONH+%)SuClbKs^?DabH$f1iY+B@tENyU7kb=5ZsV6RCtBK{N<^ zK28!sg)A5S1IZpJ?Azkc*jF)Uwz$mae|~SGrr*P(*+@5SdK)iF zZibMr6^m7^)iKL0xx6{ne32CXZCKkkD=d0wfb?rY%(A_V*<#ER@=Xtw-S6@y8P~lu zcTMxYZ9&Ok8C!6Vt{2O@i`TBVpT#WB2RtC3hx>#RyBzj9%|UJRRn731Wo!lO+pSMWk2g&IcW-(^LjPNFC?l+}1u zb+FS$nbzIyL&&zCVvV?cAt*z(zs;Yvqv&9bGOXS;wFv{=K{nwKcr08tz+uPC=dQp{wR1>9Y7Pjrq=^_qq9&467%h$ zSgfNZ*W=W@Wc$Q25Y^nmkms;#Q&Qjy1>3&~%+)y+$$aZ_;ej|#PksleypHq|@ddKE z$TTazWwRwT2@wAD>o+j2vg2VtkKr@9X2Gk%@yTT-IPD+xetL>9{JVv;5`t%!u4WF0 zOuQFWk@Ss)3*h=^!~j`V`sk=!VtHHa6g_`e4Kj%zkWul)*`d=t^W*yB-QHy`OZ)0B zCm3(N<7qGiI-9LpT_2k?=lu5k_e$??mVfL3mcqrbt3vER%4tU6X0x{8pPgS}%C)#q^ zD!VeoJVG$Dfv(tWvY{ybG0i&&7uv?88YbC@nhkaZz-&wQFYSJ08fH&>%0}rPqFe@U z`Kd6YeRnKsTo(TB4Bn`15QtdJO80lEhmJsg+S_kUkWZ!+MVZyeWL{tcXx zQ!}}Nl4{g%Rp@_QDZfkzL{;C66hlim9RzR_YWd>QN} zd8JVEoqKwxbz8PF+JjxT6%?(F{s&=fZ5*8rW-o41MtRO@5(enDi46==8A{nypzE{@ zEh%V?+eQ)?cVK*ypKT4Xh2qyjjt%z5m{{6ZZEsE#>C8D)D>|4MDXFhYQjVB>m4lE~ zD2ad@z6%AW%;l({P^8XU4aIWul4}bY32&;9L?7GMy{*{=pXXeiNlSMH?U29kr}S*W z)40reM*s!s%1r+la0go+<9k~A9$!I8zbB(f)f_lOq$BLAZtg4oh^om*dDRrVt|t^d zJR1pr5HPTf>%Yq&d3?pVHm!Z26?Y7Ygx|ky^0qwOb?{*7y}Jqbj5MO9 zv;1YflXGR#g4^h~BhaV-+E`sl`SHGFgVNxipIuznHu9s*j5X3|4fOAZSN7BL7dtCZ z{?M8FI+cn-aMRvb5>8VaCPa-fOX=uW#V{G-YBEV3u3*Au705w^;vLEdP2ysk+EDXn zo@xBn3#s08^ZGN@=$heai?F_Bt@uv4wS-=kE)=ZhgR`Ru+9v`ldyU(Gf4%6Wq$rHJ zRZ-8Ph}dSF*(C+vDQCP$sNl?&DTqM2(sx7S?9u(P(}q;LNfV*=56V;!7m z&qbHyJn({dr$v9c-KtNib2OL$#aS>V<%Yb6_6lpCRDWPU^tdc3BK?ya8TU=TSpnHk zYMOX$4g5LqT2qx00`!ORmFZthqDJ=QG%Y`z()xaXkA!pyIpJ11^dID$@_)vMl72kb zUH>~Jk2{|Icp}C%*A-7^1mjKs%hOL$cM&6=tnvD8IoXX^DrUO1Cj`e|-xA$Bms#YTw8PK2oW4utLt; z@keRdi(wD@*h}+|Ps0_@WrZ)>D*L}vFA*>k;ny_?8;)$rQA`vs0j_|TgXI#J!B%0@ zC+13hg?e~2EoKBGZ~PMSR;X;2=frIUN%xkHJ<+gdwT_tRLD=iOH{u2j(wV9 zl@Af$pgsNu^+aNOuk~=Dx9$Eb+|XSeUzK$k;otqZW13+c=};k7&;2|4IhPr0OQ}dD ze@jw3W><%Gd`%_QKq#Mg7#n)X*R00l0^%aN5AmA&KmTX+vcOfHk(vs5@LiK^-Rt(a z-B!SPGX2wL@ry{C-VqeEW_NW{gpt1^b?X`V1Ld1c1l#GDq~=;SIu`NlJ_(~H*MtXO z9HG@gR4p}Qgx3_lHt}Oy{?Wr7yd{pAe71ipR=`&}T$0x4wz20E`{RHSc}E%)LibHR z?FsQVuRKtlj@%)AXU@*M6CxejgKzC}V}nC7tqc|U!)B~D-%5$D{v93L)-gFD>8^XG z+=De>v?`wXvK`u=zf}?>%GcX7n;wX76z}qV(sUx}MAD75_LXx7v&6zE0*F6L$>@l{ zTalStrqGQn@EK0)%RJN;H{Ww%qV)`+yXtU;BjOjdsRCP@)U#`)`4k7lo;HaB8 z&AuuBtfR6(DzUuVoG-af~bvDcE@o&CO1Coy8L< z`Wmc&T&FGdUX8+wz2r`UZt&0#TN7WQi9y2$fV?D)IwWyx$^Is=5N_jsmD-aI>=gvM zVgpLyqGoKrox^JvKR1b^2`w|#?w+awXop?CMsxe;b}hQF;QCSu5%aX!FnJpSO zC`M%C*2-Diok@lfOpErt{8MdG@Pwk~MHAWzORm9!*S|TR)H}~88DpT=b1@A{$rv;}F;D@zBz-)V9c?^HF;2^?V z{ThXk@ihT`E{lUl%Kcbt9`_9d><=oO&Zv`cWwcS45w~D;_$_vGuWrsG-&P1$20{aDv4*Qj1 zH-FnHcFc%7J_wXimTK%_Ma7IUH#?TJs3?tP@Z8)P@bpo37Vkc)^)Czfq8$$d-p9+shurLuZIaH;04I zttjwjLx+r&VkQReFGnkP4)=dsJPd;4UzY5}4~l1$6SV_TXVNi?Ar`w6&M zC}3QheQzj%zSw(ir`DFS-asx2e}m2>Y>OnejgDG{EN$K>JmK^-3uqtHFwk%d7}~i} z3G)V!&7IYK*t?~^Xu*Rwdf6o+kH!Hejz}x;(?=HSA|~DM_>~3vZm%T~MwuTneEpCW zIlGyuXQWpTP9*>Gf7vRq-LzgvclziCQ(LxcBZ@=F;lu@IsXc6isEA?`H3Kvbz;Q6>Mg$N z%!6R8bqpv539+;Jx0VC~qRF;E`NWnpwNm4sw5_u&WtRFQirNEqzph{D@Rh}2?O;vW zw7wGHVgI9~vb~qiHEKQ5M@0+&5#!&!=%tv;1J0j{o^8&X;SQL9h-)7!o!i7=$=HpC zmgtJZ=#|QDMGuMyZFJ_p!ScO!fi>`y4eGgM6+Xy1-X~ftpS{S6PIhv05UaCEm>TaA z$xCS!n^Iy-?3`k{5S^P#77hGd815}6hg5yKOJ4v2p|EM$M&eRRP<~KTt^fGw{w%Mg zqz&roR_~*&2JV#{zV>=@2VZU&Z)S!0P#bJS&qBmjre?Y~uN_Oe${ot+h-FOv?FC>8 z>r!#jR&xzyn5^zd(#t%#knOfi?DtMX2fxWhu?7LLK7Ar$AUN{=Pk~;K(f_m-Db#h+ z>R{b}OMH~`^}>4mP2WSLlM;Gr^4ko^6M%}Kw!|n{LjKbDWm?Q%L{=2RtW)P3HTO&Z z{FJqIi;dtmHp9N`vGh07rmT>Jf;H)G8JIpxpB&ANO>Vt~yq#uNHsU<~Bg50VF{6K8 zD~<1+-JfJ9^pO{nl6#(!dvil%kSD_zxq+oO{?5m0xXq$jam@0kRFlWabR0wbATFIu7>h+ zFEwPItVdJ!8u!}s3X=ysH$8TLux>>*bDUgRyQm>Igb%}dP)c(u;Zr88ksd?R?B{Fg zmyMR{SH>CoqC?Hq&MA;;x|TgVs^GY7Ws{PSivkh)9VbE_Q8%*F0y(juhM}H6C7?AH z@h%g=c@={4%WnpNRq7KC>Z%a+IqcGJFSKk9bShha=V#$TQ$3p@rqSk*^$Mzj* zstki^)XoLih1L6<$UuEP)i9UUf%=Ua{3+V`l9$3F)aE_H^_d=BLTgm*qe?Ja$gjRu zs#=YF9^28RJqRofP8@Q_M>88NiQE9ok1X?=jgv4EC@v&rXJOT8tT8miPxaPVgzY=I zyO43`?nRgYCqr`o_gB)kYROrv!-BtO3tXiZ<-XSSd2ILUdXdjdDmUHaLPTN#fi$pf z(smBG2jgkf-wr?KRM1e_$(|Mg@Gw+eA{Zmy``1VpqBUavLZ89~ez9|;3514LCm&fW0l0A5t7(Tfc>e8W*^y=R%$LLRE zTOaI2N+SgOq}2>+%MF;Isi*tTB|btWr-m*0G8IsFbie+Sx+4#;#A-=81$}Z*)s@Fz zA4zCx*&6Fvl3reZDI}a0?BcHKCtUX2zAyQ@3FBxV>)_z%J07+F1b&gf$_EVLHtZ&s z3z4?t!%{Qiu-$vhKR(+f8t&HswuELHiG$j{&-S94q6)HO?l;XoA<3i_Gp${Sp*c4) z+}D6g1{01(47X|VL1dNN-r(rv)zYol_p?=ATVs~41RAnCzZ!8*4lChecmeJg_q~9?^oJXs?_UV4y@AT$y@r-!;=8DxQ=w}%-PA4 zO_wI_2;Bp=mc$LJ{>PD^eA2s*`f1{Schf8|SGq+vic($io$MO0nGes`LP7gN`XG?l{VAa2>(-+ zrA#(Bwp=&tTvczhUI!HSl}uq}Hlh(wQV3zF6?x<^xD4hP(6FI{0tQdseI&XTM%3A!U^oz`>H(P)E=}7v)6+ zQJIr>C;o?Ov17_j{(w!8Y5?EK?%$RUOK5s`Z!H88a=k8&1{O>J&m?UG}a{o8IQDKTPC;@bjeYVjXEfemk!mL)AJ3BnTR*E$XAusg88G-gDb zB;!fh<**{4-{;y9=7Bxf+qR9w9(=uXqHW)Z_2$>&?DF z6ul?c+EUj^`c)uZ%agylpV4$mdRizeF9${F(PF`-eFmSr?$V7lQn}vLYL2Z{r%7f? z$A;w$lEl5JA#7VVbO33kf#7b)rec~Wo%f7O!dP>6LRP zFNM}XP@ibZ1@C@Ts7NYFr=KvG?RUK#yd2yHpV}l7p||5c4WB5uCjj&QhRfov$mpJ1 z{$yo%kd?|%yD z343oN&6(R#fhPG^s-9rxwkz6x!eNzi1Y16a*!lp@Ydo$Q15GCA>h}=zcg^gl+*Jfy zy+DA|+CL>eq?|J7hNvE(PrWX~*y8ezON|4{fHdFZ!v)d1UNbTxM@v0@XSLdYu6D|o z|6Lpm@Y~(!hU`|;A5~l}?}`V829e}5yshEyA+3#hFML!=#f4o^Gx`inz)Mt}RL02u zsCXWvS!`RAqZx|gPiT?s0KZ=EO(V3t_{9Bbrb7P24g**$^OgG`W;#9bZ`3+i0{xtZ zST-%lgCxki?VH9%?pOh_#D9IsNtc4v<3enOzUo~NX*cO4JMN<;q&p*ZhC4S_2dE(o z5zNiW1hrM2*%`FBvcm~q4@`+u?^JHf{~0{0pDQ`}4lOp08(`$?OCN z)dbYjITUNk6!F#iB0U2-o7Jk$fKQeU!5-a8F?iTKWHQi1LoEL)S1was2XwJeTP2#I z_m~i%=9oVDnP0w#n}eXpx$r#0*wKHLSaNU$&}$MP`Y+6PLxv=xR8aLr0MH#a2rGAC z#zQ?ZtdMNVxn7a3P<*L}4XerE+oCmjfVHXdT9!u_tV+(v`dY&P#;))TktSAqC!xT?AIMZg3I%+3y%X^x@xYsUh$kFqL+u4)s6 zqRf!yp0@g|Y!la=(;0r^8F! zn);v31hA4Zg4_v=R`^CO$eLTaE^*dps=&G_j6;;2NJ{e9`Ol^;m&g=Qx2JB+t=XFV zz6p}+eHY#Kvfz-ga|b3&K3kt=d}Nm>6BZNmTiMO-{V&g3Hj7iF)G_f36l7?ze;5Bn z!HKZLo9m`1_F7CCvOYBhPd7s3ag=Gpfc>T5?XzQ7z_W=9>Zr;If28b~%xJu}v@m+V z@dyK8ygJG^{cm0#<5SrLdA!@iyh2!Ms~k#ozQuc&)?mL=1}awiBKk%`yecIigfncr z?S|Adc(~3d(<)N46!`9TvyQF9+l+tc=MMiwZ}ZBgim{8VxO*Xg=FBQTG7pL^YVlxM zz%yRwVcR-tWv9jgh@~ipboCyKY+bJK-;Z~|bTT;;&VKklNo)G% z$qz4Ax~-YL!!bx9de7Q@!@SOSENm@hT;^X zC?EY=mA3^&TN6Ek!2dQ1{tjwX(BJtR_Y+G-wnVI&{nT&sG8BT~6Ka3j<0OVbyLRmr z+O%EwH!H?E$!L7QJU2uCvVe}n(L^f8_B$!yfg9(&h?MQ-U!-5X{hw zUXCtpP8zH1e(>AP?yGw3nmQ&dU=QoH)tZ|N?URyq*uoy ztYGChJHE_33w;wv#PsEnTBgz(Us@d#t>aoE75%OtU#dubvG~K~)9`LcV>N}U$_iN! zzlnXwL#XWi$d1$Gk<+(V02$)uv;D7{b)pZ0;tt~48Co4c&rJy@RId}JAx0i%j z7x*|+b5^0_wnF7{%@X8D?9-&pV94l==17b(;YZ?8y=-4$vxZ&UpaA!cPXJ$Y&agZ8Ep2aUH%t`FN^!O(WhkP#A zs-0_S>$LzABO)?bft%?^?N$%j9WokN)+^jb>WWqPRqUI}5KAT-)_XmEdt$K}y8g_t zVvlB8h_|HM8-pIB#OO!+=y$Ujz-x*{W3w`=r<0sT`@;!i%{kocp6DO-%yR{v99)*! zAV&CH0~NfYtdUAf!WS;P|5&-hd^{as<2Ze2jsT|x#kD_^zg&^AaoQx`V1xrsEfd}V z>-lZyH*WcvW9K%)h~~Yo&E-nZ!XC-w7{`3_5Ze93%>=Q@XR2(zLe)q!`B1kEMQX zj_~CI3INkG(&>$V#NH2$UzdyzdYg)WI`ndTyk+0*GvzHIeaM7Ae9&!JY?CQiU}^4s zux>`M<7_=U>NUU9K)uD)#l3L~#sk{S6_N#o`IV3R6ws`K#d;EGV_g%-P8Hl0b!?Eps=E|`}-XK>%yyTxYR%+xX7J9Jdii!em-x~lid0lj2r z2JwJE>CcGKXeC@NqI_g<6j&l{)%KX%!~@We*c%JOi=ZNyC}~ut=6_6HlAM+B_0(1C ze)}S;i(-h45?b=-F3$H^B?BSC zxnN2V~cB;%J zmF4e-=S|#)UjQjvvp@UJlU@JkIp>HNgHQejlFXRujIJGMXkX9QhU@FPDC!r$=2CfK z28L`z_}*t3hmS9cUkTMc?DUdr)M*g+5I#5`KwcWx5tBVI?6pasXc)`qsMS6KYCs!7 zCj&5_vc5tO8j2Dkn8WgDVy`l;eOta{w1g?Y4L-ziaYGG@%c=CPbf-}OK#qQ?@9kkq zc)NV2cE}J;+X6s;Y>}P#1@=JQN^r@~;Bsih&$7<<%G-Sf1_aFKBENPIes)h&5F`g< zI>}ETY-+vV=k_Ei)O@NvbsptES(ee-6a{5OXq<-qWz-k3=5C>Gf{rN_rZQAsZ;TeH zKixN2{qgWqvtKcCbn_p|qt&6z;*2a}^q3C=!hPQ!Sd$Dk5*_h03e^zUE@|9qXiYvM zj0v@+2*`S#Ja*NQzqgnYLc160$$1EI zVgBEezsJozSG&xpgpewD=ZforHqb!Tg*6z`ZGi|2C`X)N9ndeDn}@&6AWbCfMl<3X zToDG+pDO=CuV7pGZqu}_AQBkWMv=`?fW9WMX5CV{Z2wqzftnw6NK-cK8R0%|@!Cjc zB7o+KQelspN@l#P<#K#=l3dQi0&e-;HGYeVN&Ut@!MFocnp` z;JVB_VG{I!}h*9K{`o2MVr<_7t$;F&mk6LmA&5tSH!m z5JmvKQX9i>`}BjMy99;6#lhN{6;{_onwqCUf6cJ%s50R4fn=Gx=m2%i5Ec#|ZK%u5 zFmR_&kv&)ezaBC;n+NU_5*GZ1TSNw9=)QO#mebZ>-aLF_{ydl-&WaZn{)_Yr+ z7$_3V(B6I9tY4@;!>V7Uwc-Zk867nW2WRNsWsCtp25kP8EZ2ScUWspLY?qk4CfN%3 z4H^BD8i{)*HanD+U0VGmZ;=*JIF|?8-`6FdQi?G;;v+kj=p)%~(1L~D*ugTThu$fi z;T?beL!B;L`8mgLIfGNh_w?R0c^o)^gdI;G#wtscWqT@Ag=w%T;E*bh*O2FFr~97x z4*G|zVTkgV08Tr`{3H5p^##6`m=-eVGfZ?SEu9m~zn7(UGd@q{6BSPC(ZU`&EXv#x z>*f6@exTOP?3$s94;z-J*;%g_ku=6U_!H|w=yXjiW4?R^!RrCG1;|eo*pfjTJZ2FE zh-BS!u@(frfT7!S7MMqkDXPb@xv(OPZ>UR` zX9D`h*amu)K+Vgmn7!qmfV&25DMg*&c`f=-y=QO3{uZUOPWPr8v?=sV;U4?v>K0SH zrxaAJq^rQE*ptP8y5K>Xi}d6D)n0EM8)2`*Hp9h) zSu$cNi}^=CPxQt9F#dHA#7UjGpi2s0?MZLv6>j9fl!J<5xq8sm|1k3to7&6S4B1zY zL4ug<1~Xa{hy&Y0K^r-o<8~73X^I6^c{#1wZl(L`EW?>J(a(?svUYF;DaJx-fob1_ zc+&WK=cAo78^U-}YD?1BP`haUn|}#glA;3%gHiU8-3c`oyG-AJ!+EQUX(0jHw4ocv*pBq=n1@k_}1`! z_?m)li*C{4I8^sJ>^D}kSU1S++a@fn;6C(y&u}DCKV(T>#tNtbJ{?^GIVw6Bn*|uO z?;=LV7k_ulG}Z6V7u!jic$XU9mmLx7miYOz)!0Jlrpgo!sHix{kGR}BqY5~4&^mII zc?{?N=~bqAhFxLTjYM^M5QoI4YIGr<56m5XY#7I@-?{3mppO{@@M4e$tZ1}i#UzcO z{!}k2tp*Nu<*uE=2vx@Gwbd;yK=i;RA?+3>2-#YHhLQEEu1L(fFzPSzHiWQ$>-(qyXxka?FXUS3Unn?F~rJsp#tlyVW zq27|6YV9n-x2gs2Z^8~Kpkw++b!z3iz+RCEqq+7U#v|c5DPfuwDOjdJ>^)VD1FwBI zLW$~ggOj6z;WsT}(cs3vswp^4!iS^Fb%Uc8oZE5@ZKB6a(mYEb?^d}lxzY$3ziS}o zYbQ3K37_pgdVPCZu;ax&41lYJq2YyegEhjUZWw zoX!U~$y1doNlsj~>u{yn|8+JbPVW1apFadZBY3}j{ByGwv&3=US?5_Zo8i?vXMJN_ zw=ckgi&%g&DHP!3t<_OfRs`bInEU46_?6V(7PFqASawXRv0NF=X2X+sIlEZ?Nh8k9 zV{oedcGjK5^P*ojMzL#j(LPpvP=H;#;l4296mmDJ^%rXXcc|{EKJ;a5H^6x@ae~?> z^qQPVn9K=oF#>&WFh&(4F|XE|BGSU$T*!20ymo^4;L3XP;n2VEd7c@^WBSeH#m+C( zxeu9QO590NLEu%uQNz5>p*mf!FUmK1@qO|U7o*mT9! z)--~|STC((2rNhFR{w0@9>~oU4-BKcpN=&O_D03^{foJ+{$}omWaqSmpFq+N^Y`^X zX~dyK2tmDVfKtIIHP$o?)&y8E?P@{{VCKWm7S2na8`X#~flvbm0-StQK-7I!eHHUq zmtb&u-t~jkh{3$?WvyIKd!?V_ChOB#3_F2MIWmp?jyY8;8{%r?!lsNyZ79^9l$6`u<0D_k>iMR;@xRd6SRgP`&JA& zGNnw6G28Z$jt8b$>+mew9bS?P_fW)-UDxmf|=Ci#1A~f~9Y?;ZHchw4?t(;?b=ZTgrFNP3`p&w#JaD`Ita; zsK;^Q((Tv>Xl!SlKc&*){m@tXpzW*K6@P;f9fvWTH8a>g;jfZ_z>?ZiSnL<})g2vj zSOJ6(GT7{IQ}$YGHiD8>RBW}E;NrTcT=~1 zq0J4Z%TC#Ed5;J0oNI1rQ}5CKfxXo9F^`c)DXxrCvd(NdtT~o-j(*&*5lsjRI(#v5 z0bW>>PbSxb;zSx1Mwh*fO zLuaKJ0adh(#Idl-py}kYQ&aiwo8yQFdN?MsFXNWb87zZ7E!!Iva0ieGI3b^h|Dax@ z%RW(N>ig!n-{%IU6&J+%r&*BzmrXrw)2>h5ZH$I-l;G|(d}G59^Iy=fp?HexW~k1K zv3oKT3ZbXK-|Y9a)w+UJ)%luX;P{ExWmsz2Z&{dII`7HH~i8Vtm zHRB#@Zzg3olAQeT9WHWjSh+8~-q%J~ntnI#D=@BPD{A6IQzo*zw`q_6IjsN1@H6Fy zc^c4D(65PU8>?`ii!)=mJ5;x>VrN+{(9)G#&-xtgrbw@%$(cU`oN6u%cmsE8!iP-w zF4EKUe!Zl8puh4i4C4|?Lt7>{U4@ z*ddmbz0SYTF)&ozIcUvawsO22$Rg#tE|oMoMJ2!MneW(<-H0tTw(YH3W9$+scZ>SL5TvQ}V!v$~2|bjLkBlC|`Tdvi zjl0Ix?~wZIx%ii|UPd2|7jJZEQbza@!4LZL)~()@`@I=~ zm>;;RY|&ASt2P7;ZMZC3;a9z7S1+#UL2t7Wm?!rhx~q}@8L9NAHh;s{Dar6BZ^ap8 zgZPzKy>kw$aQTWw{B2z3!+|Z()QqLQ_dro#SG^h3Kvx$l042Vae;AOLCAZ-qGWjD! zi_#29tNghFy5_*_ZoSn98;mRO|B7hw@t0_h*C~FeHDruQ)epI=GV7W7lvkoFd;k&B z6csi8uos=TZLl`P>jh?D_mS1S%g8xyAg8IM1BZjMG#q-u2XFga!v2L;SvMoWn^wH< z4cCSYJ|p{gmdD6p20AB6?M9T3*wa;xK{jZ**gKi_5Cew92g{j^PwNeL9L^-zK^p>I zaJK4Nk70@?h}qqgHV2%Y%vij!6`o2aP}=8s`XR}_PfJ>-W_O35A+44gYc6T_{vW>g}3YB8z-9-dMb5X6v_ho(@?mBR= zskDjtZ@woj3o5rG(ky$e1w5JhRHrdfgM2&!6uN9DRi?-Z#G4n^&7H8%_4|$-sCvh{U_`|1F6f+Xkqg-@Y`* zV?Et!DGF?VF|9!_LsGxB(*$%+f;oYvs>DMUodirM#4;W4s zhlzO74VXodvs0u2?!cKJnK7}ZqlNL_H&zyj(^j>J9PO^(+5Nhszi#b2#|uF>VQc>( z3u50`T9Nx#N3u704&)~0aBoEpnflmJqT#N3ODrR9pojQqn&+>| zJJoFlLLmd;3p@o6bKZGb*4qY&10ldKqsUwexfWslaU zbIV2VXj!YRVlTsn=9d254rMR2F77qubqj>Qg5+)gZO%cTm+>pw4yKLk2Y=}ce^3od zrQ9SuG^}CebR}uu4ZmrcPs%aQ`e^VbPMbWe3m(!O7wf?UQrzZsy zsUH`~BI_3g1go)_8W*3xm9e)?P5}l#ZXX*wZ*B^@;OfYC;Ic4lSYf+Qll@=AXY@H) zX~-G2GNvVM@p?vAyC6`sFtbC5bJpVS;XE4=%`6)8-ud&4;fgw@ajh}G&t3y}p;|e0 zH6pJkf38e~)D9%ct}O`VD`(LB_Tw`Ga*4;HIzl$Ne?vJpahr%~SdUOg!CDx30+aic zf^mPo*kcyx>6W6aw$aRNoK~uP!{jS@9yn<*_rFbh9gEsQCRJEZHKdR9iY8%ZrSemP z;t4;l`W|$~=&-c5Dk-R^zD5787}wQBTO{4u+9B%D>BWIPY-$EslE zQJk-Nmf1fye297kLF4a>-(p({TT%eS_10-QnpiDurTq-1zWPd{^n)r7j7rD(bY}AHCs|YpErLpK+NrQLGL>`VX zxlB%B$m{G&RIlx%gqvFRN;>z{$Oia=%!#XsnPTvR^1fe|0pS`p>4`TE^Ls+}5sQQl z2AlGe`x>?9a+9cnZUs|hBJaKWiV9zxT282r8o7ZK9y$Noj&*O<1bd5K2Ih&1dYT{H zY1J3d3=f{n@00%pK0HMWyxBA><#!d?ysboOS~hoc{WIgA3fThjXJ*tm1i5mL7&2wpH68!#PV*$S}4~ zW%Y=~m{1BR>*_{tFwvnAtuulF_lNCx)+^q1Yp{sGq~$L=uPiddzBh{;v>uHr0?!k6 zUa0VB>B)_b>U7?CdvJ`T$9qo_L1yY=bSy#_r-u`oB9MRscjDNGRD8n;g9nFy&($lGUd|7 zmH9K{W~E1>&{kyXKTXMdIti78{6#uJTpM5y_^7K&UK`PcuLj+ujRQ+% zB&yt8Za3Yfe;yYN-UKi%`wW#x53;R%iy|3&xv?3iN+kr0@AGZ);L|$Nrm?)Sd*@J!$F4bn6#a#aH84*4d7~Z*A6DUF z{PoPF%qtTKrw6QqoXS5yR^@)lI|tM$n7-dL1Tl_5T@!Z!bzg`hx}^Yt93_1EN6=|O zMNwIDdtBhCCw#x|5=~qFA|TYC@*{);=*Co_moui~FI5diYk7{QhYCX>BPHO|dzS0% zF#O(+vWzk*6+BFLbt$*OX6COo^3rkz@;TyBhfbxWP~21(l@Ye}n~~CTWF@e_W$@62 z58N@qXSg~lA8F95i8X2N&fl#ZmflhW0aFI1n$EAG%`tJ{GrX>9Bx|1oCsfhQTEp7# zpf@!a(fSz|NSDUucV`1J`UjVF_yzQ&frpjcOiBe8x!A4i+s3}b?g&$}fV0~L(C>+E zbc*Plkn}qeA^_C~7^eSqFOS_7V7K+49e#U(-XQG=Wr~A&p)2_t-4bHqBVaavT+D;l z=K}{Wbw?oXfene6GD#IAY#R`0crfjt5^&#HzCkHr3dC23Lz}7(hFt4qzhN##Hr1mo znMez%loWPSv2v3<=+>=O19xML()uHM0x51R`iE5PB?%Z{U=41kyjVLcyqvL<9lD2w z>kG10NgJs(y@q*g)WTB&>ua!n5OYuo7{zVdd{rk@rGOXS7+Li$r+)6Uj9wCr#P9yc^;UzdQXbgo0pUt z3q2Q(qo0I*RL#;=S^T;r^)*aROvO^gvS;hrz;brpb@X7-ybWkACl&ylCk>%P zDBXVag-e=Oz=P8Mj*u<-ORkhoXGrt5xq&;fU*&J`h*C^mK!T3>YDUoDBCcHnm*mz{ zIaqXX4)n{Z2E-l+5vRPXDe8(!QAwOtSr1*c@fE_Ly5`S%LJjlf!GURdeYPHb%WcQE zNd37XMZ-D%(MX4xny2N(duOK1*_nU+kT*ts(L1d_qjvvg+SSJv=x6Q^6hZu%DsVu< zDL3yAFEuV`UNgKO>gK>y?_vEL94*FrJa`WN7I+oQOi4TcRm(3NUc;v8+XU#K(3jBG zcEGX(ho29hMlAcj9T}0>`43@|JXuyt8X9#!@P6nltrsnwqhBnqtR?__k9%%Cpv?n| zo;9qh1F$0$P`B9phHdy|*zktE*)WotoMSx+Ye-so6zWTM=0^HG0MSYSufH8Y4gag7 z>`(9^zb!AjC>r?hf~p>D)$hk1hS)Q@MuG8Hp#A9H0oBmO5vQkqsbej{9kdB$WI&1I zbfn#1sjSTjqQ7Xns>2DxV+nRy^VcG)Iat6LT@SbNHuypETe;yFURt?k*oV|7z$D~h z?dGi&GvtYVS<#JnC{wB3bG-MK6-+Um;k4f$#@d?n?K|NQAsDn0H^ipnMc)~5Cg!9A z*WMQ7E!-z5NE)pxRx?sRJYEs5c`*l;?>ZrX*@cwqbhQr>V=}Tf=az+~V zWzoHnHMghK9q#Sj4j+O(H@s>V)XJ3d;^3Xc8x-W)P#XJZJ+B#43`PZsed<48 z%k+tAN(GY00!)_JZm7!k$sYDn8E`mgomLLFSWIhs>hcrz4Qm$8ai7T5cm*rWSm+|R zO8mnXSDJLV^EB|nK{BliGA1ymyY+-=`GMh<84KmuB52+1P}ZriKe!+O9JKk4q#4K- z4b^Op7@Jg|`!a0(huIS0wsD2m!8Q{7CQ6AxpO-aK{*+2IFUglTXJs=^6tAXYN?^tP>GB2{1=RPVRzKqaRCj_E9CaO{E2zN?@5Ncfig)sQS!F|#5 z#p9TIwWFiIzQBZ#>h8Bmhud5%Djd;qE6X0vhhK@CUmlq%hKU;Av>uq7^{NxP&DZru zw9J_I6~gEXrGc4%)<+!V-aYaqptM)q&>Mzd($<@h2fI#w2AH03oL0!mkq3w;dWuPZ z)MAU=21`;5JZ{h4E4F4&${IIu61GUMp-p3s4+A@Il}bmSCQ@Gx|KJU(e%o!+&E|bv zyf!=59?}GcNFl%A0y)!3XNhK+U8h#??}(cLh|}Y3TwsGfUHGuu;y5)#1n~gp5n__{ z;|eWvjMZvRsNM^!-r7Ut>Fib3FN`fxks6GSunyX2z+4 z2g9lou-ij1!?#fHK}{|>4IxO6i|h+KnaZ3Q7%utypH9BJ8i1SI8fjuNzNi z@baP2DX%U4wM9%D{XHm)Ka(TlLOkH>0E>8P>LrDRKK6Xb;HQyJkkPibtgtW{@~NJC zqaEn*tyah5T&)pWtNxLN*bK#@b;hk^)1^;N$i$@66^Ys6Bc3Ff0fpn&dGDD=HthO$ zd7DS=QuQOuEr9kHuQf}wwcL4 z$YuXEbQ|VqT`F2`^_Mb#+xO#VyTaDW=5NNs&EU=S%xZ-$18myN=%TBpXpDG#IOO`C zZ83ge4w~f)`}v-Pt`oO7CPbB*OAFJkj3$m4yIX9@;nR6iNt&xJ%Werg1D)fe)5YDM z;cD#AXZy9H*CZGn>7j*C@qNYzQSG`DZI|QhF{===Vzm0 z1vJ?2v{kcQbsF>B{HxH1q>fWX1B@#u8b=`OL~|7V2N=Ilu*Vs4QYN1gEmZs;wD}WP zfdckv-EHsa58UuM@ZnF?A*Z9ikvxfcQX{(8Ouirdwq6@DdpDH*^fHi<+17)c?NF&m z7Fm*7(f#OZ?MqtaJ!RxCk}{KwdMqvR@KH`6fjQnBq5@qXZH(|cNB~G4;WYK7<_kle z*3@5w(s`qFCD!>;aqD*aGDy+@34hP6bGy4__=<>?0ydr%AjTbUrbs$;C3C?WWp)C2 z9r)|!1!ho-#7=x{ElR~L2>~5kD)Sr_H+@jzt;D)H>dPC?HC zDraTe`_H|_DX(l$JfG)kR_x&CqmY|x2qhv`8Tq;64)b8)Xg7ei41F&DPJh;3vu}lQ zeJg(8qaQ#&s_4C86Lxa4c%FXEqV-1k>(HN5FIZ_G$h%pHHAKwXbM&!*nr(}v^R4@P z2FOmW0(HQ~rKIDA1$?u2^)7;kQFwH9U-Cfx*37(yL$l-yi_NXVx9B=^*2HLf72g43Kl7x7}J|SaRBV)XfI41erFkjD9 zuF%?H`oa{PMD~Cbu{_aQ7%13EeJi}>Ji@B{rH_aG$j+$}C#;MPlJY? zUtw$0fw&V(3L8JbaM?(Vavcu&X%vrJjlUCic^f!>GCFeTJQ2Q%bY%V0da~50dA@S4 zjFntf@e2wAtpew7EWr9I!{?dsa8pkeB3W^$TY*e;f7n} zvhADPVf~sAz0}nx?cqDSuMYq7j2>!#Auo!x$Sfz001@Gp4Dx5sY1eRyWjg|bR$u1` zW;eGcUH2`ZiV#@k2>GK0G7y5@1!y1O+C6wDdd+AY z_nm@0-%`V7(cZ}oM#Z2pYr6P94v}gc@ERNi-VZir?o-Nl^AUfY?z2Aw?#+afwl$NU z-)?R0#jZFg@9~Y+>2W2n?v6t-OX6;2#cIzdkHxP|S44akgU{>;13*m|<=c`Ndz(W& zWEXX;tgvs6)1#2I<`kbWTK>v)u+{VppVNT#cpDmK53`jg?V(zT%sx17oEaGz*LFkK z*tDUx+!AJbdq~-0&LmdX<5s}`VcZW60F9K71nB_rL2<$=HX_4dc9Lk}@U=Ca?^y1D zI)Tx3kC7oa&Fed1`CK4lZ#J}QU!D3xCWH2!3`hy}yTi2a@-(0ZF~EIeEdxu+zYgGe zZn2Eb{Pd1{XlYiOx~{lzVn@#qfs?rzy^HJBQIqjSnx{y*cH*Y{EF**8SH7A>oYcv% z_#@V zRdunZMdx{aO5n7<+TF0PowTlK_G}N;G6`X*YgWcjOdjWx$pYu62abL{aA~raKYB8) zOTqU(R_n2ot2YIU2Ej2R*s;h~bKatd$=+boC)leBm7as5C%j^Amn>5I(45&Ring2qLw!+md^d5#k3f`+4Qpc=;P| z$-V4hffuCw$xMkw;SeosWcZx>u;59{fgslN0{dZCoWR%;-<rFE*NeO|T6`0=7C>Mh+^crm-@NxH6jZTD)5#UL9yYuEwR1ja zr@@&&>jNwrW~*BB{4k<+9)tsG9)>M`1qrJ1NVTcz0VOD1x~SqOlkD*CDOm;~%#nE? z=BZvEb>>6I*yv97G$w5hGy8|Y>LlhXu-s$q`~GqG0mb~Ynjk6^6rH-HvPzp^+^nqQ z*(}3L`NDgY-q#yy>dL2durhKYqAicUh2OYKth}W9uQ^8pl>c|lD@3FU^7Z!4Cbs2_ zvLd#}*5z2Q+h`PsXnj@ScGfDbSx2v8s`vssnSWW`S#bZ*t($+td@_jdi?;j~yhJ{;BamFGyAzLJ|U zRO_;JdjE?OYG#p+1{WTL89))o_SInXq16WVVjVIoWDzpnyx{fRpuV(*E}wHe~417wb_4cp-Q(+isybt zYRsP29BPVKfky5V1oZrDVD|W*m@)^7tcG7&UT1L^K%2d{u}GZR`!T@K&(CYOudul7 zMHs+uQ-_+e)tY%<`!b$DnfD7SdriNFfwStO$4(maP3ht9-5O8_25o*$`|+b%zDix@ z&%~1&<-NO2m!?8087ELTn& zl(`apyc~9A<4@{y@NRttqe?kuFRpEk+!XFD0^U zB-G;+$7@&ia!AI;zsX(eb-ugJ9HVt(PtVl(EtzD?snEe9@ICeajr5dY2Fs>TS}(Dm zW$MwRs#71nB5a=5ZJw}w;30chM!uAk54Q5%6mQh5{2VgKd9o_#>)x5zSS-JI#&Q*m zwTba<-HR!@ZK0MguMS(v)-DG7PYN9tRMz++j4Q_1)U$+zdvD#;eMUFLmWJ5==3{+m zP_~#Ts=rDecmQulozYPXm|-n0rM5+Wuyg(1wfN1^p8Wx#e#j$IT;4TJ`0G71WP>T-2;B6}*5Q zQPTLAw^G0bQ>rKTGLu=hqZzUSIO)}2m+MoE(vOj z)|g5EFgP@!kUvPAKWRWUgwAS5jROuCGs__wrg}TC%T&w>D8&P9wiG)ziBZ37cs^-+ zIW0E|77R5|3Y$P48?i^7kqGuYSlnJak@ns&qx1o>OJYb^{;}+HV``EiK&WkRsn`MW zJRzETG|Lygbi2}U!g6+taJ9{Bi?OVb`@CSHLynbf`;<4b`zwq@>9()_Nvf=x4oCFJ zpKo?j-Bnz>o>8P1oHD%ESHj$np)0R?QY1wnnSax6x6F4{qVES`v!TEhQA9}c?|dH+ zv|*BU@PLvw8DS0eL0`+@+b~J!BtFK`f?N4|9Q({Fv_|^ff^`mkx_uU$G*>+e2)=?p zyAD6xK>70cktL)-W#63D=ShDBK?D?hV-Hl@MJZ8_K`gUQv>xt6Oit-V`&O9=QNnj! zNn#SGlKynOe%6?k3*kyL-fpHJ_`xRA>MtiP83bZWE-@0dXzCn2KQ`w4hC}mT_PdS} z!dQKWD8p$pcPsHP);~hN&&TDo*}vFJ#B?x-bQj|ixRXc-?IrDz(=V$s&12&bR~b*_ zayNLWos(-cuLO6)Z{yzppA7#KkjuM@U83U>mj|}M7FUVcB$qk~gEWb|;d2Z7A2e5< zSNP{Sp_)#C2&@8YCENkc^j0hW54G>As-U#b#Y2m3B2#ZxhtXgXo!pX_<{G&7V)>D= z=-K+Mq-?EX)=i8E)AltC(T|S$vG}OLYL#PJBh+`XXu}j!Y3;LWRfdtWcS({0c^DcX zk#i%>sLuz9!Lb4_2HC^gI5%=f6gJ9}DYPZ7AVzbkV z$GROLn&-@8`3bNv)14Tkgh+YSu#HQ3SuMXd@cJn4YD#np%-C+!7!>QZXXZ=J8RjnH0;tACf=ZjbXFe&)9BNE+r6HHe3csIebWn%K;y z8uxNdg9Iy;z5#NFNaH9cz@QNsM6gpcicy>cZ{3^~2uXJP`Eb)~S+yJ={;P?VMpnIU zW_h^W5F6Jl+;yE^_&EHdL8NF!AH16*s++9cjoS{WF_cFzvaz3jc8@(4=qf8x--h7Z z+&*k25B)m~$4ZW7U0ao|a(r3n*1!3>#X}y7c41$ zgcZ{YZ^g&b8id>~%(}vRUpI|iP?(ing@Pq4{4O>V$qeQ6z|!#ctcR@cyC<>SAH{r4 zPl#io-9w`SjsPV@-}s@Mq<;8E{;S4wX6+u_WOJV?(d_KJH4NhKFlDPocWCn?#|!;y zuh1=7ol&-RC8;9dT8I-|&*f;91xc%Kh5-=q=GUOvV@0$WXrQ>nvc{BEvcQ zvbrfp-|tBuB;wivKO@6eOxsPXlZJmV$2a%!_Ey%sV*qzaWm~gBr;Kb>o41unI-7N( z>`tF(>LZ}75`$m7WvmZ_6x6!Gy2wOfhA`H1w(D+1<3h- z$7yg*RzGT(dwH%0k+JQZ_T@b_&--^^zs+(mLR?;u+gU5?7Qpy5;ILh{K?Ws7)OFm; z>^7>d1*KVHaar(}OfpeuWjf0-D$sl>8a65=xO z@cW?Ft&dH25MoLT4znhD3(Ay=w!B%c?~3@wJaGp#eERie4#Y9qxLPFW5$`|1woIDs zLyNh+AKt*}hAzLEt>={Qg!=<|&Wg&Uhb7@om}+@`1f1#g%x}_8OCoc}E9kq8!apM8Z^bU0ad0b}j0jKOz!oC!NVdQJHB0X{C@BJp3e7~se`{Bz|x z>Z{~i(arQ-b#rgbo{MGW&N4e78fQ7xZ{?n^5ytG~(mAa>Ltw;&6_YwqztCvCmo)&C zkJ5VAJVdJtR=uopyvf>v85Bzx6}{a}j*IAPdm7!7eWZ-9UvNOc-?p>4$wS-(gz>DY z8l)7WTk~-Lmi%nz=DATd5s{=_XD=F-6zhx|kc$a6wg zyrI0d)7RafBuiM`GG}3mlIenEYG}8g2Y;HNv9Fw$Za&1>j-ant)P9zj(lDj zY+Tl=@dGGg+fDZglv>$p?=L2FH~c@oO^vPg>$+x#*Vj5lm77TEyi%Wj_U`_g+Smj7 ztagj@paWw3|0y~TwRbNG z4VmT0S?+;2GY61+D=u&gA_9W=`TYgYaX-g1?r~k`88pDu4`_zxoW)gUb~bB=_+Si& zO`Dtui3^M{0!0MdpzUx%Eg9?pegw5Z7nSSyQcN?>6v?&1PdJMHNHL%OEqBF^7E?rI zOwI=cvR9wcBRAjkf=!<`NO%XUTY87*x89vLsqFCjPvDwIYr(uGVKPKqs-pn;oY-x* zDlGXLF1X_r!3xVUnz^CUGV`Az?F|CCEK9cEOp`Q^Fu0L!B{x!*V5-Zc(}661*ZA;{ zih(7BwmG*2nE{ZoezTwXVPRcI!|=WK zR_lvT1_H6s%T`-{BNK}8OFDqj(6yo;gCOz!6(2aa0eh;q9*mY`pC*10A7MHLm%L0z ziFwKqqfj5#L-oNH50dVr40*co6b|H@tso~|3Mx;*QiBNP&qTw2*O>#7sHbMp%KmL| zNlZdm3%GU{f5S$6;j*(p*?j713UtMZg$##D8cjl2mz!VCNL9b~)d1M2iJLv7^Z?;KpzBo0-;ZfjY6 z%safJ^wJ$>VFrdE`NZH*T7EnE6%EgE*2Pv=9gv&`XNW33~#~0nhM4|EmCI(l^!Ny zgve*5U}iHX6+JPT&v&`cytS&1&)RP=>YISy7zP+luO9GJ(xDr z#lG1UO)1OZJ9J;1ud<QQP}+SVafS!y`*yP|*w2Rvr2=}4 z)4Z=aD|)tQo1jxBMgqU>KnB-m&^-T|(>a{Uya8TdK0$|d2De#3)_!-HD?7jKQ$(L~ zk?c0{ALmtU26F=I4KB+|M$eyq-hPEo*z6NiiFSSQpI|J{ozxS7Tj;U79n zbEMnr0kD#nwr{b7N^;Ga+Ab z{l2>oA_}Gl{+U2r`gsSkS?`f${&*_Cb>4B=ffxM^h9KC z_Cq<%xJpC1^?SW)b9hMV4j@CZPz`#J4ZI&88T5!E?Pqn2UM@=qh-jrpeZoj7))>%~Y536p#5$>U7$MJ7Ai)!X``+I$m zEqS^gPh`7#h@}_4aSW_`>HoDeYFmY1*LhBBNhSrDEmRlDP)uM}`bAqBeWdT@fis<# ziuc`c!{2V**bdEP=U>>F4%By4q|j2=vzgzN<`ZVK^zTo7d(dJSq2uvS)~J`?+jw-2 zlSNoe%95JXRqSv`D;xY@WL{bO@OB01R5PFu3}MH6F1C=Iu_blNO+V2U1`VM+O|zbY zXN1o)|7PdnD3Ps4=Ovfbf@z8N?ZM}8(fX~*&#Uv$?xQy?9Ms5H_e<<_pJlC!R@aBF zNtbeB`pfb9G#OVT-M4n}lw${F%&lsm@5SjoEng$vw)8Lq@s<@n2dg_3)v@K0>ZvSJ z+|PJL5C74M&t?1LU`;C$2y}aG=d6FHd8jTrsViDBuB^-M2XtW}Z+MVMicCkOxNT^J zCNvSmZw1UJM*8J6Xos6w7CRivC!ff#rFPA+-7bb^WqhcDL=>`%N6yPhIeCA+j#*~x zZ-;J8MDQ^2!}8wEZzBp`)$*t(&;Z%a_s_Lv$lZn&a-i1t7Cadz+1Z4MHk0*wLWY(K zbKp&%LYH^n=weZrPPysfv}C@tdeqG#lBoGF?GFBRS}0_gycgUTJFYlumyFYrEaCY9 zl7`hn$l&n&oyS_KPm?rFb7j;w^Ie2RN4STpO{M3yM7bv4mC z_x=X22m}7e@a730Bt{*tJVtxGTg_2q?uCOgtH2GyxJJ;=pg>%NhRFzK>?<+Uqn7Y) z|4A((bUz2t6EaZzbrbHQUf|IEB6c5jk8yr`VY|7g!1c_*HAKo+^uQ8A3;OJooWZXG|1blRYeU}_H$s{uUl1*CFFba~r891d76Wq5pWYgr z!(T`hb-gD$?H-a7zBs;MM>1>-n)7 zx+3~#(b=DU%F_4MnA?ssax<@??@aO@Y(H*!ORxq9+IWW0E;e|C+}_F37l>;vNOrl* zeBQWjNx7~YGSno4m8mmCJ7lWiD!>6D);lru=l&NWZf>iCRc-DJ~MY))~3NeA|`>D)Q##PoK9N*kCEVxyo^eDNk% zG-V)kzYXgVyL?zfjU2v9Lq|+)pWYwU|LgnGZB>A6DC=;Y*ewZ|JyM%whg6=$PkiQ^ z$$)ts6bpNuA>{v38)EL*V`Y&dn+KC$wm(bC&U%%S-0(i1EaA#{Ta7^*l|!B;OikxYq%t!fQRN=x%n)uUV|2hJNPV`C?QL@+&0)=ifCL4%RH{kB$Pb%{9H%e zN%RKu;okaY`99i9_FRrAb>}c-sc`@@!}F~kp@$b&n@D z_o*a6R{~sjCH=ALlI5u7OUDrf9!Ax;5Ov*K0%k90nKHxk<9TR+^(zr49 z+T2yZ(f{9o6aVtNft>rBT3E}ze z^bqRm+hUKm>DOY!tQG5YRwF8tqCSJ--GggR$ymK_86FS`c!16X%P-ap6;vJ5%5&hz z*ozbD$B;IZ{?&V0#7#cbK_nlIARY)@Jrp8Q1me*pV|H1=dWPC8@& z(o5{nM?i0P)_nh6C>DiJc>RNbFbI>LP3KlYnOC9R@8#<4g^}Kyp!cph#Yd@O5r3#v zJTcHx#J;X8RIJ&TcR71E0A)I~%MnN^ir*PT-k|lP=lhq6<|k1)_zSsyZ5}#iBg$P` zF*-|zdc&Ny>X)iu(=Aga#5In@XHAI5!O;1-XAM`QgthC!e|fwqG@lm8#KNyfSgVUc z`8>!cV#OJ6b;X}b&JI-0MbgG(9~rTbO#pnV+L>2fy(Kddo7LC>`@SgV87?r zD0xy!_}%N^LY^f3W?$+XY`C^1YEak-veY%P?Jx9&a#f#YKC<-hbpK>egc0% zni9c;?k1~p0W5A^}WTHa9|9?sgFG^??A9^WuAip zmTkdoXh6RAtJTAY?HcC|^JsY=AkVUU%3Ond7~_c=Dw-k1@`GP6q#QfJ+md$X>5q+5tihUDe^dZ;1qf^%C6HR*&bC~R`9{JZ4tAnPD-xcpZ0_y-e*=c!ky|0tQ(eA|omnIsSE1^Yyzg0|g!nc{2c^%1%$&Og@FO@CzzOEEnU;sH zW$;W>)UXngulZAe@r!{iL(zQ4cJGnagKPQeKfPb^LB3jrK+6Nu+YZA zZ|hu7w0O*jPqKzw%*6eiE29e<@Q$S{%y<8VqnTth^;lqaR3ON<&c8CORFSjCA{(q9 z&cL6|C_(L2zSMlLZ(Y?rd$INX9nTaM%@Wy4q-c*+9_2jr4ajZbl{NxbB}kW`qD6&$ zWvGcQZ^*cX9XCWs4eWo^1}*)lb}{jS-FkrnfX#qgSARl zUB!y;ohCg2W>qc(`H|o0W;x(VA^3t3=Y)=7w9BbK))e)goV2Tykb+k{(2) zg+7c|=Q}0(+9=nr_{NGRLAx#G&xh5Df>bqazg_&}oK?n!a(sV9&FH3`N{eYyF$qpl zd<9yK^fg|Oy-c<7nZg`;Ib$1c=@CN;dfRnn=t@B`f=6_+?8Z`k= z)eidZKFw~JE|E<~H;3HcuCF`94iD;w#~wO4fG#uP051B)46~2S7-aQ$o5U|6fXK`k z*wrC=9L?~Q|GdK2 zrZ*VRvS2;z@T#OQT4oECr(C2WTZ{MXNov^uf~lpD|3jyKQeG6J!BnPyVj5?*2% zdO#Ab6oq*=YuID28VD#7&X%G+-*J37qo@X&v6*eGTWXkuH>Y+Mr8C|9U+=-!`h?n< z;18kN@@p7Tk}oPVp~{?&fIrcQ#R&2b+M(7U`gN0A;29NXei1DJQ9BQC#*|WxZu#dZ zlhi!S!Xpe3+U1TLQ-LH(3Mqu)b}ly}BUTW}a01?G&!!fU>UxRmwq}R9E^;#eLzh=( zaDB#QL~-(pMK-gfMy$bT)Cm2w{!ax zS@7@EWx1w9FDxo+>!)Gu-f{^b2sc}@q>>fE`zf)cH>y+ZSQ}izZmr6G{PDo^_*SA| z1mvlK%v-tF7Ap~ONj}k5LV`RYA?8Mhy6!S@*SuC;2ETuWSH(I#XUA;>z4RJ!FNP<5 zf|zmBj98H*Rk|_wBN3G|6tb7Je5+EV$JBr1Wb%K><&+a;qmbAID}iF8&Hze|incOz zX~+$(u_M$U>Xk*VTJY=RJ|ez7vHC28wh|VRzxu(u)J9}h4=KR+#~QITcf)rwN+XT8 zx$dmdGxMo(hqLX7msE~U9k7laC5syHNXO+KvCKw#RWcLy{$)yxt_0Vca8_+qINGxgG}gXQSI>g zLaRAR$`@{Dh}_7OT_mYu_p|$Xh#SO7(*m=V9dNR2#GnjEED;5woIF4iOhk>Ea7_hd z4&$gFiY8T$7i@MtC^|~3*|YT8WvK-Hjf!;H<(oNM+tWKl7?dk-iWi(xu0!Q}Y*1UN z3iGzCBo@NeO5=3EyxBNWJ9Og|-gm^R^fE&YeZ2WIF*5CEiLg@|>)S|sK~cz#-JnX4 zBI0|8G2_1{CI?fuIB9Y{C7QBV_4-4hAAtFB-~by+hdw8%;6Z6GUB^US_TY+)nB_d0 zt_(~^BnG^FWnoImYnGqoi(3M`E^vg5J%bPL9Aq)~2MW2twa57~YM+q>&>2Wld(q

    }6l)FF~N57<4 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 zΠR+Bsly1FGT?ut}!Pvqvewv@r#U1MZ6h|LjrhCt5+#E0=e^#teGxCwIgTT*AGH z5YLL;SpjE>NAvA^R&M(yl{PXBpnt6UVuo3FEyWWS?F!X5ueN$Vfj&NXd-M@H6bI3(qe^ z30#G)T@Yn_1~1$NAK#Ts2&l*sii`YqZO%jVp2csoIYc7Bq-}bLL~+ssB2N+AY7+J= zth;7H5~M{R0Igl){r8~qgAo*Ph@@&j#gqaZ)s$QC4QlwwAl#OoKszekbcGR~v)qwR zrV*Qr!|J3UPF+EAlR&vBlfndlbflpJVgPTOe`b~S(`~eUJ3$xd@rnp6=Ln-`_)UUL zFp>jmM-I(d!3D$ze&M0t|5k)ZWNw!t^MhxbMgp7aI5EzG2VK*H5XwaaxvsM?lFx5w z@#^vde9vpS-AGgwc0I_b<#X`6RzBZV(Em^$NjdmZ5-)?y)!xwm<6Mf zb^KH@uz12_$l9@9s>dOlhnApBOe&E$!kbjOV6#t%R7#;=n@og>!jfnYkW1TlTRB?9 zRif9GeN}iyz8)MPWVa4zvJj$U(@`(xf3HC4?svng$V7~9CoVd#dAU0vBW~! z5lDt$iDFxDQ9X?59#8lKzZrhqWL#mlU-y^WFNW#BKvve!?!gyjMj_jbDqZy1uLxRL zO9W|76h(P zyhEOy0~rRHkVo8|deX<(XjH;SYRiAMEZX=MI;#wOybJCBkt3!bbK$04ynLo!df^ji zEarDisENlh?mta2wQ7^+-DZ+HAdH}l1^&t20}n;GuEoiKI;0-dtXJ**=He z-aO(nxL3krSuM8@FbA@(>6dW?<^N;atL{3hY7DR1hmbbw?b~6_fhk6(*QHyS{eC&K zndoCY^<91pE;H!w9ahYsG<_YiCQy6~?k^=ILG%xC##PcY-hB_Ff zzBrzxRiX|1+W8!OXZIe8YW$1Hik>m!ih2hehLS#VcA}lihF>`M07e!0tN(_77EF^r zPE}Pcc5JL7#^eK+2#;DRS^e6%t+T~TBb66FJ_1zQJHxK2%c|PY-aq1mjosgmHtLyV znwC~9T;ewB2&@iTp!TCD2lRbRKG(-`_uWd;4q^qf$2$akEi4}sm(Nsf`!#w%bS%Q6 zv~VV~y0i8}LJJ0fzAAqNS1-%}ROco?D6{ca)?`#W7W%EC!v(*dN1*({X|XN0uacbl znV_w`qAY^2ZQJ)9Pc- z|3t3�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 a|77)<_F=w%f%*2gr~^Da5uyKz;eP;c&RRAA diff --git a/Standalones/ParticlesAndPores/Single_Pore_Scene.aRTist b/Standalones/ParticlesAndPores/Single_Pore_Scene.aRTist deleted file mode 100644 index 29ae4fedb5e7b210216554feb78b5c1bb5bfb28e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1458 zcmWIWW@Zs#VBp|j*jO7E$e3~Y*jHu-26qky1}+8$hTO!=JiX%N)V$QAp}xhR%mnPZ z;}<4Zcermed~k=O#bj=cK}*foWjDA3vsLzQnlmBs$NRfeH!9}x&waV@j6t&J?(=rP z-(;1tO0CiPvF^B>Pp)yrgxQ+{s?K^X-tu~*rp1Xl8;iHLK5A`s>X4g#<(u=aTTI5Q zuU=gC`EICO_w#_JbB??J#y7gO`|(*6rlt>^gVn)Gwb_vuvBN((+r1BSH)gHfqT}`Q-p{=A=6<;i?SBK~RbDE1 zS>(vR;5z&vAzQodYlZF8#V#>@t~O$aD{lB-jgd zGoqf~m?oZfJI6+wTU*<_{oCF%*FP-bJN9GYy$Lp3!*6f;Kj&5EqD9HS?oaxAKX|E1 zzF7aRLuQ($A)>;$(=ICbxQg&EQs})LDB~)zqb#i}bI+#D8;<{} z^K<+Xt6s-h!{z_>PV(lPM1MsJe{_+-Y&rW+>BM#OB9#7w?A-i)wWMln zV&05%O|Kl{=IP%)@z%VHht=-cC#RhWlhZFfv{kpw+uZtR*R@j@cVs5&rLgk6H_6&n zS|`X>AohL6y#3PYB}bJcgw}VpDc$kwIOV#wYmc6!S9wVCx=r>9`O1^oE#xQJ>^kh0 zB;VoIz`-h}D5Dx^H@3b%NRI#9;wk=m z(`|$v3iQ5TadZ8wbl%@Cq8-&sbZmayskvlh-RQQ+_FK13n0eOI>^rL8);F0Y?vk`V? zvxQj~awKuFTr=mpJI$Uk09rUOfC~p;c>o9OKvr;mX;E^jK1>m$1SvbFvC$hS=?BEx z2t^jA2Cj|<#*PN&#^xrLmTo4dX2yoj=EjZ|&IZP2ZZ3KiMa98kAI_dX?SD?=)OlZ> zlRjYvCZ+)={CF=18iZU3zfe%F6>=d+L+{d)r$J#KywCV6@X58f(&|yHJz_6_mL?cQ$gg)$E2B~IX5McQ4D9eHr0H~Is g2LVJA$TBB{CSn34z?+o~q?s8Aj{)gxK None: + self.rc = remote_control + + def get_image(self) -> np.ndarray: + self.rc.send('set imgList [Engine::Go]') + self.rc.send('RemoteControl::SendImage [lindex $imgList 0]') + return self.rc.get_image() + + def translate(self, id: int | str, x: float = 0.0, y: float = 0.0, z: float = 0.0) -> None: + self.rc.send(f'::PartList::Invoke {str(id)} SetPosition {str(x)} {str(y)} {str(z)};') + self.rc.send(f'::PartList::Invoke {str(id)} SetRefPos {str(x)} {str(y)} {str(z)};') + + def rotate(self, id: int | str, alpha: float = 0.0, beta: float = 0.0, gamma: float = 0.0) -> None: + position = self.get_position(id) + self.rc.send(f'::PartList::Invoke {str(id)} SetRefPos {str(position[0])} {str(position[1])} {str(position[2])};') + self.rc.send(f'::PartList::Invoke {str(id)} SetOrientation {str(alpha)} {str(beta)} {str(gamma)};') + + def rotate_from_rotation_matrix(self, id: int | str, rotation_matrix: np.ndarray) -> None: + rotation = Rotation.from_matrix(rotation_matrix) + euler_scipy = rotation.as_euler("ZXY", degrees=True) + euler_scipy = [euler_scipy[1], euler_scipy[2], euler_scipy[0]] + self.rotate(id, *euler_scipy) + + def get_position(self, id: int | str) -> np.ndarray: + result = self.rc.send(f'[::PartList::Get {id} Obj] GetPosition') + return np.float32(result[1:-2].split(" ")) + + def get_euler_angles(self, id: int | str) -> np.ndarray: + result = self.rc.send(f'[::PartList::Get {id} Obj] GetOrientation') + return np.float32(result[1:-2].split(" ")) + + def get_rotation_matrix(self, id: int | str) -> np.ndarray: + euler_angles = self.get_euler_angles(id) + + R_x = Rotation.from_euler("X", euler_angles[0], degrees=True).as_matrix() + R_y = Rotation.from_euler("Y", euler_angles[1], degrees=True).as_matrix() + R_z = Rotation.from_euler("Z", euler_angles[2], degrees=True).as_matrix() + + rotation = R_z + rotation = rotation.dot(R_x) + rotation = rotation.dot(R_y) + + return rotation + + def get_orientation(self, id) -> np.ndarray: + rotation = Rotation.from_matrix(self.get_rotation_matrix(id)) + return rotation.as_quat() diff --git a/artistlib/remote_connection.py b/artistlib/remote_connection.py new file mode 100644 index 0000000..24a2454 --- /dev/null +++ b/artistlib/remote_connection.py @@ -0,0 +1,147 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import numpy as np +import socket +import base64 +import pathlib +from PIL import Image + + +class Junction: + """Remote control of aRTist simulator (this is a test) + """ + def __init__(self, host="localhost", port=3658, bufferSize=1024, timeout=10): + self.host = host + self.port = port + self.bufferSize = bufferSize + self.timeout = timeout + self.error = 0 + self.progress = 0 + self.answer = {} + + self.connect() + + def connect(self): + try: + self.S = socket.socket() # Create socket (for TCP) + self.S.connect((self.host, self.port)) # Connect to aRTist + self.S.settimeout(self.timeout) + self.S.setblocking(True) + self.listen(0) + except ConnectionRefusedError: + raise ConnectionRefusedError('The Connection to aRTist was refused. Is aRTist running and the remote connection enabled?') + except Exception as e: + raise e + return self + + def send(self, command, msgType="RESULT"): + c = command + '\n' + self.S.send(c.encode()) + return self.listen(msgType=msgType) + + def listen(self, command_no=1, msgType="RESULT"): + answer = "" + stop = False + if (command_no == 0): + self.S.settimeout(0.2) + while (not stop):# and ("SUCCESS" not in total) and ("ERROR" not in total): # Solange server antwortet und nicht "SUCCESS" enthält + try: + msg = self.S.recv(self.bufferSize).decode() + except BaseException as e: + err = e.args[0] + if err == "timed out": + #print("Timeout\n") + answer += "RESULT Timeout\n" + #print(answer) + stop = True + continue + else: + if ("SUCCESS" in msg): + answer += msg + stop = True + continue + elif ("ERROR" in msg): + answer += msg + stop = True + #global error + self.error = self.error + 1 + continue + elif ("PROGRESS" in msg): + try: + self.progress = float(msg.strip('PROGRESS ')) + except: + self.progress = 0 + continue + else: + if (command_no == 0): + print(msg) + answer += msg + self.S.settimeout(self.timeout) + self.answer.update({"SUCCESS":self.pick(answer, "SUCCESS"), + "RESULT":self.pick(answer, "RESULT"), + "SDTOUT":self.pick(answer, "STDOUT"), + "BASE64":self.pick(answer, "BASE64"), + "IMAGE":self.pick(answer, "IMAGE"), + "FILE":self.pick(answer, "FILE")}) + if (msgType != "*"): + answer = self.pick(answer, msgType) + return answer + + def pick(self, answer, res='RESULT'): + picked = '' + for a in answer.split('\n'): + if a.find(res) == 0: + picked += a[1 + len(res):].strip('\r') + '\n' + if len(picked) == 0: + return res + ' not found.' + return picked + + def get_answer(self, key): + return self.answer[key] + + def save_image(self, imageName: str): + npTypes = [np.bool_, np.ubyte, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, np.int_, np.uint, np.single, np.double] + imageData = self.answer["BASE64"] + decodedData = base64.b64decode((imageData)) + imageHeader = self.answer["IMAGE"].split() + # dtype = npTypes[int(imageHeader[np.double])] + dtype = np.double + im = np.frombuffer(decodedData, dtype).reshape((int(imageHeader[1]),int(imageHeader[2]))) + Image.fromarray(im).save(imageName) + + def receive_file(self, fileName): + fileData = self.answer["BASE64"] + decodedFile = base64.b64decode((fileData)) + artistFile = open(fileName, "wb") + artistFile.write(decodedFile) + artistFile.close() + + def send_file(self, fileName): + outFile = open(fileName, "br") + fileBytes = outFile.read() + encBytes = base64.b64encode((fileBytes)) + encString = str(encBytes) + encString = encString.lstrip("b'").rstrip("'") + fileExtension = pathlib.Path(fileName).suffix + com = "::RemoteControl::ReceiveFile " + encString + " " + fileExtension + recAnswer = self.send(com, "RESULT") + return recAnswer + + def get_image(self) -> np.ndarray: + imageData = self.answer["BASE64"] + decodedData = base64.b64decode((imageData)) + imageHeader = self.answer["IMAGE"].split() + dtype = np.double + return np.frombuffer(decodedData, dtype).reshape((int(imageHeader[1]),int(imageHeader[2]))) \ No newline at end of file diff --git a/example_artistlib.py b/example_artistlib.py deleted file mode 100644 index e81a6da..0000000 --- a/example_artistlib.py +++ /dev/null @@ -1,29 +0,0 @@ -import artistlib as a - -# connect to aRTist (default: host='localhost', port=3658) -rc = a.Junction() - -# print aRTist's version number -ver = a.Junction.send(rc, '::aRTist::GetVersion full') -print(ver) - -# - load a project -# - run the simulation -# - save the resulting projection from the image viewer -a.Junction.send(rc, 'FileIO::OpenAny $Xray(LibraryDir)/ExampleProjects/Schlumpfmark.aRTist') -a.Junction.send(rc, 'Engine::GoCmd') -ans = "Saved as: " -ans += a.Junction.send(rc, 'Modules::Invoke ImageViewer SaveFile [file join $env(HOME) Pictures/artistlib.tif] true') -print(ans) - -# - load a project -# - run the simulation without viewing the result -# - transfer the final projection -# - saving the projection image >>>> This requires aRTist 2.12.7 or higher! <<<< -# - delete the images to release the memory -a.Junction.send(rc, 'FileIO::OpenAny $Xray(LibraryDir)/ExampleProjects/aRTist.aRTist') -a.Junction.send(rc, 'set imgList [Engine::Go]') -a.Junction.send(rc, 'RemoteControl::SendImage [lindex $imgList 0]') -a.Junction.save_image(rc, "transferred.tif") -a.Junction.send(rc, 'foreach i $imgList {$i Delete}') -print("Saved as: transferred.tif") \ No newline at end of file diff --git a/examples/make_circular_scan.py b/examples/make_circular_scan.py new file mode 100644 index 0000000..706bc43 --- /dev/null +++ b/examples/make_circular_scan.py @@ -0,0 +1,40 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import matplotlib.pyplot as plt +from PythonTools.py2raw import py2raw +from PythonTools.ezrt_header import EzrtHeader +from artistlib import API + +artist_api = API() +print(artist_api.get_position('S')) +print(artist_api.get_euler_angles('S')) +print(artist_api.get_rotation_matrix('D')) + +artist_api.rotate('S', beta=77) + +source_matrix = artist_api.get_rotation_matrix('S') +print(source_matrix) + +artist_api.rotate_from_rotation_matrix('S', source_matrix) + +source_matrix = artist_api.get_rotation_matrix('S') +print(source_matrix) + +image = artist_api.get_image() +artist_api.translate('S', 0, -130, 190) + +plt.imshow(image) +plt.show() + From c37c4f26958e570d2efc117a7ee84c417178713e Mon Sep 17 00:00:00 2001 From: swittl Date: Mon, 16 Oct 2023 16:35:52 +0200 Subject: [PATCH 02/21] added hardware --- artistlib/api.py | 4 +- artistlib/hardware/__init__.py | 16 ++++++ artistlib/hardware/base_hardware.py | 27 +++++++++ artistlib/hardware/common_types.py | 19 +++++++ artistlib/hardware/xray_detector.py | 23 ++++++++ artistlib/hardware/xray_source.py | 87 +++++++++++++++++++++++++++++ examples/01_api_example.py | 53 ++++++++++++++++++ examples/02_circular_trajectory.py | 52 +++++++++++++++++ examples/make_circular_scan.py | 40 ------------- project.toml | 1 + 10 files changed, 280 insertions(+), 42 deletions(-) create mode 100644 artistlib/hardware/__init__.py create mode 100644 artistlib/hardware/base_hardware.py create mode 100644 artistlib/hardware/common_types.py create mode 100644 artistlib/hardware/xray_detector.py create mode 100644 artistlib/hardware/xray_source.py create mode 100644 examples/01_api_example.py create mode 100644 examples/02_circular_trajectory.py delete mode 100644 examples/make_circular_scan.py diff --git a/artistlib/api.py b/artistlib/api.py index fd1d861..30a9c59 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -45,11 +45,11 @@ def rotate_from_rotation_matrix(self, id: int | str, rotation_matrix: np.ndarray def get_position(self, id: int | str) -> np.ndarray: result = self.rc.send(f'[::PartList::Get {id} Obj] GetPosition') - return np.float32(result[1:-2].split(" ")) + return np.float32(result[1:-1].split(" ")) def get_euler_angles(self, id: int | str) -> np.ndarray: result = self.rc.send(f'[::PartList::Get {id} Obj] GetOrientation') - return np.float32(result[1:-2].split(" ")) + return np.float32(result[1:-1].split(" ")) def get_rotation_matrix(self, id: int | str) -> np.ndarray: euler_angles = self.get_euler_angles(id) diff --git a/artistlib/hardware/__init__.py b/artistlib/hardware/__init__.py new file mode 100644 index 0000000..0032278 --- /dev/null +++ b/artistlib/hardware/__init__.py @@ -0,0 +1,16 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .xray_source import XraySource +from .xray_detector import XrayDetector \ No newline at end of file diff --git a/artistlib/hardware/base_hardware.py b/artistlib/hardware/base_hardware.py new file mode 100644 index 0000000..72afbd7 --- /dev/null +++ b/artistlib/hardware/base_hardware.py @@ -0,0 +1,27 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from ..remote_connection import Junction +from ..api import API + + +class BaseHardware(): + def __init__(self, remote_control: Junction | API) -> None: + if isinstance(remote_control, Junction): + self.rc = remote_control + elif isinstance(remote_control, API): + self.rc = remote_control.rc + else: + raise ValueError('Wrong remote_control argument?') \ No newline at end of file diff --git a/artistlib/hardware/common_types.py b/artistlib/hardware/common_types.py new file mode 100644 index 0000000..0d80ddc --- /dev/null +++ b/artistlib/hardware/common_types.py @@ -0,0 +1,19 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from enum import IntEnum + +class SOURCETYPES(IntEnum): + MONOCHROMATIC = 0 + GENERAL = 1 \ No newline at end of file diff --git a/artistlib/hardware/xray_detector.py b/artistlib/hardware/xray_detector.py new file mode 100644 index 0000000..e69273f --- /dev/null +++ b/artistlib/hardware/xray_detector.py @@ -0,0 +1,23 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +from artistlib.api import API +from artistlib.remote_connection import Junction +from .base_hardware import BaseHardware + + +class XrayDetector(BaseHardware): + def __init__(self, remote_control: Junction | API) -> None: + super().__init__(remote_control) \ No newline at end of file diff --git a/artistlib/hardware/xray_source.py b/artistlib/hardware/xray_source.py new file mode 100644 index 0000000..3694e02 --- /dev/null +++ b/artistlib/hardware/xray_source.py @@ -0,0 +1,87 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + + +from artistlib.api import API +from artistlib.remote_connection import Junction +from .base_hardware import BaseHardware + +from .common_types import SOURCETYPES + + +class XraySource(BaseHardware): + def __init__(self, remote_control: Junction | API) -> None: + super().__init__(remote_control) + + @property + def voltage_kv(self) -> float: + return_value = self.rc.send('array get Xsource Voltage') + return_value = return_value.split(' ')[1] + return float(return_value) + + @voltage_kv.setter + def voltage_kv(self, voltage_kv: float) -> None: + self.rc.send(f'set ::Xsource(Voltage) {voltage_kv}') + self.rc.send(f'::XSource::ComputeSpectrum') + + @property + def exposure_ma(self) -> float: + return_value = self.rc.send('array get Xsource Exposure') + return_value = return_value.split(' ')[1] + return float(return_value) + + @exposure_ma.setter + def exposure_ma(self, exposure_ma: float) -> None: + self.rc.send(f'set ::Xsource(Exposure) {exposure_ma}') + + @property + def filter_material(self) -> float: + return_value = self.rc.send('array get Xsource FilterMaterial') + return_value = return_value.split(' ')[1] + return float(return_value) + + @filter_material.setter + def filter_material(self, filter_material: float) -> None: + self.rc.send(f'set ::Xsource(FilterMaterial) {filter_material}') + self.rc.send(f'::XSource::ComputeSpectrum') + + @property + def filter_thickness_mm(self) -> float: + return_value = self.rc.send('array get Xsource FilterThickness') + return_value = return_value.split(' ')[1] + return float(return_value) + + @filter_thickness_mm.setter + def filter_thickness_mm(self, filter_thickness_mm: float) -> None: + self.rc.send(f'set ::Xsource(FilterThickness) {filter_thickness_mm}') + self.rc.send(f'::XSource::ComputeSpectrum') + + @property + def source_type(self) -> int: + return_value = self.rc.send('array get Xsource Tube') + return_value = return_value.split(' ')[1] + + if str(return_value).startswith('Mono'): + return SOURCETYPES.MONOCHROMATIC + elif str(return_value).startswith('General'): + return SOURCETYPES.GENERAL + + @source_type.setter + def source_type(self, source_type: SOURCETYPES) -> None: + if source_type == SOURCETYPES.MONOCHROMATIC: + self.rc.send(f'set ::Xsource(Tube) Mono') + elif source_type == SOURCETYPES.GENERAL: + self.rc.send(f'set ::Xsource(Tube) General') + self.rc.send(f'::XSource::ComputeSpectrum') \ No newline at end of file diff --git a/examples/01_api_example.py b/examples/01_api_example.py new file mode 100644 index 0000000..0815fb2 --- /dev/null +++ b/examples/01_api_example.py @@ -0,0 +1,53 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import matplotlib.pyplot as plt + +from artistlib import API +from artistlib.hardware import XraySource + + +def main(): + # Initialize the api. + artist_api = API() + + # Move and rotate source to initial position / orientation. + artist_api.rotate('S', alpha=0., beta=77, gamma=-12.) + artist_api.translate('S', x=10, y=-129, z=199.4) + + # Get the current position of the source: + source_position = artist_api.get_position('S') + source_orientation = artist_api.get_orientation('S') + + print(f'Source Position: {source_position}') + print(f'Source Orientation: {source_orientation}') + + # Create a source object and set the voltage + source = XraySource(artist_api) + source.voltage_kv = 142. + source.exposure_ma = 10. + + print(f'Source Voltage: {source.voltage_kv} kV') + print(f'Source Exposure: {source.exposure_ma} mA') + print(f'Source Type: {source.source_type}') + + + # Make a projection an visualize it in python + image = artist_api.get_image() + + plt.imshow(image) + plt.show() + +if __name__ == '__main__': + main() diff --git a/examples/02_circular_trajectory.py b/examples/02_circular_trajectory.py new file mode 100644 index 0000000..b02b385 --- /dev/null +++ b/examples/02_circular_trajectory.py @@ -0,0 +1,52 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import numpy as np +from scipy.spatial.transform import Rotation +from matplotlib import pyplot as plt + +from artistlib import API + + +def generate_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) -> tuple[np.ndarray]: + rotation_angles = np.linspace(-np.pi, np.pi, number_of_projections, endpoint=False) + rotation_object = Rotation.from_euler('Y', rotation_angles, degrees=False) + + source_initial_position = np.array([0., 0., fod_mm]) + detector_initial_position = np.array([0., 0., fod_mm - fdd_mm]) + + source_positions = rotation_object.apply(source_initial_position) + detector_positions = rotation_object.apply(detector_initial_position) + + return zip(source_positions, detector_positions, rotation_angles * 180 / np.pi) + +def main(): + trajectory = generate_trajectory(100., 200., 20) + api = API() + + for scan_pose in trajectory: + source, detector, beta_angles = scan_pose + + api.translate('S', *source) + api.translate('D', *detector) + api.rotate('D', beta=beta_angles) + + image = api.get_image() + plt.imshow(image) + plt.show() + +if __name__ == '__main__': + main() + \ No newline at end of file diff --git a/examples/make_circular_scan.py b/examples/make_circular_scan.py deleted file mode 100644 index 706bc43..0000000 --- a/examples/make_circular_scan.py +++ /dev/null @@ -1,40 +0,0 @@ -# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import matplotlib.pyplot as plt -from PythonTools.py2raw import py2raw -from PythonTools.ezrt_header import EzrtHeader -from artistlib import API - -artist_api = API() -print(artist_api.get_position('S')) -print(artist_api.get_euler_angles('S')) -print(artist_api.get_rotation_matrix('D')) - -artist_api.rotate('S', beta=77) - -source_matrix = artist_api.get_rotation_matrix('S') -print(source_matrix) - -artist_api.rotate_from_rotation_matrix('S', source_matrix) - -source_matrix = artist_api.get_rotation_matrix('S') -print(source_matrix) - -image = artist_api.get_image() -artist_api.translate('S', 0, -130, 190) - -plt.imshow(image) -plt.show() - diff --git a/project.toml b/project.toml index f56da58..6cab824 100644 --- a/project.toml +++ b/project.toml @@ -3,5 +3,6 @@ requires = [ "setuptools>=42", "versioneer" "wheel" + "scipy" ] build-backend = "setuptools.build_meta" From 5a493238707116ab8f75a14fdc1b27c7a51fb31e Mon Sep 17 00:00:00 2001 From: swittl Date: Mon, 16 Oct 2023 16:48:58 +0200 Subject: [PATCH 03/21] circular trajectory example --- examples/02_circular_trajectory.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/examples/02_circular_trajectory.py b/examples/02_circular_trajectory.py index b02b385..38952ef 100644 --- a/examples/02_circular_trajectory.py +++ b/examples/02_circular_trajectory.py @@ -21,6 +21,9 @@ def generate_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) -> tuple[np.ndarray]: + if fod_mm > fdd_mm: + raise ValueError('fod > fdd.') + rotation_angles = np.linspace(-np.pi, np.pi, number_of_projections, endpoint=False) rotation_object = Rotation.from_euler('Y', rotation_angles, degrees=False) @@ -33,7 +36,7 @@ def generate_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int return zip(source_positions, detector_positions, rotation_angles * 180 / np.pi) def main(): - trajectory = generate_trajectory(100., 200., 20) + trajectory = generate_trajectory(500., 1000., 20) api = API() for scan_pose in trajectory: @@ -41,6 +44,7 @@ def main(): api.translate('S', *source) api.translate('D', *detector) + api.rotate('S', beta=beta_angles) api.rotate('D', beta=beta_angles) image = api.get_image() From ab65aa1dd5d3790043146eb09bf344498a264a2c Mon Sep 17 00:00:00 2001 From: swittl Date: Tue, 17 Oct 2023 11:09:44 +0200 Subject: [PATCH 04/21] added trajectories --- .gitignore | 3 +- artistlib/api.py | 43 +++++++++++++- artistlib/hardware/xray_detector.py | 24 +++++++- artistlib/trajectory/__init__.py | 15 +++++ artistlib/trajectory/ct_trajectories.py | 79 +++++++++++++++++++++++++ examples/01_api_example.py | 1 - examples/02_circular_trajectory.py | 24 ++------ 7 files changed, 167 insertions(+), 22 deletions(-) create mode 100644 artistlib/trajectory/__init__.py create mode 100644 artistlib/trajectory/ct_trajectories.py diff --git a/.gitignore b/.gitignore index 2108ddb..105479e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ __pycache__ artistlib.egg-info dist /venv/ -*.tif \ No newline at end of file +*.tif +/workspace/ \ No newline at end of file diff --git a/artistlib/api.py b/artistlib/api.py index 30a9c59..adfd6d3 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -16,7 +16,10 @@ from .remote_connection import Junction import numpy as np + from scipy.spatial.transform import Rotation +from pathlib import Path +import json class API(): @@ -27,7 +30,17 @@ def get_image(self) -> np.ndarray: self.rc.send('set imgList [Engine::Go]') self.rc.send('RemoteControl::SendImage [lindex $imgList 0]') return self.rc.get_image() - + + def save_image_uint16(self, save_path: Path): + self.rc.send('set imgList [Engine::Go]') + save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') + save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', + self.rc.send(f'Image::SaveFile [lindex $imgList 0] {save_path_projection} true') + self.rc.send('foreach i $imgList {$i Delete}') + + with open(str(save_path_json), 'w') as f: + json.dump(self.projection_geometry(), f, indent=4) + def translate(self, id: int | str, x: float = 0.0, y: float = 0.0, z: float = 0.0) -> None: self.rc.send(f'::PartList::Invoke {str(id)} SetPosition {str(x)} {str(y)} {str(z)};') self.rc.send(f'::PartList::Invoke {str(id)} SetRefPos {str(x)} {str(y)} {str(z)};') @@ -67,3 +80,31 @@ def get_rotation_matrix(self, id: int | str) -> np.ndarray: def get_orientation(self, id) -> np.ndarray: rotation = Rotation.from_matrix(self.get_rotation_matrix(id)) return rotation.as_quat() + + def projection_geometry(self): + source_position = np.array(self.get_position('S')) + source_orientation = np.array(self.get_rotation_matrix('S')) + detector_position = np.array(self.get_position('D')) + detector_orientation = np.array(self.get_rotation_matrix('D')) + + detector_resolution = self.get_detector_resolution() + detector_pixel_count = self.get_detector_pixel_count() + + data_dict = dict() + data_dict['source_position_mm'] = source_position.tolist() + data_dict['source_orientation_matrix'] = source_orientation.tolist() + data_dict['detector_position_mm'] = detector_position.tolist() + data_dict['detector_orientation_matrix'] = detector_orientation.tolist() + + data_dict['detector_count_px'] = detector_pixel_count.tolist() + data_dict['detector_resolution_mm'] = detector_resolution.tolist() + + return data_dict + + def get_detector_resolution(self) -> np.ndarray: + result = self.rc.send(f'::XDetector::GetResolution') + return np.array(np.float32(result.split(" "))) + + def get_detector_pixel_count(self) -> np.ndarray: + result = self.rc.send(f'::XDetector::GetPixelSize') + return np.array(np.int32(result.split(" "))) diff --git a/artistlib/hardware/xray_detector.py b/artistlib/hardware/xray_detector.py index e69273f..043bb13 100644 --- a/artistlib/hardware/xray_detector.py +++ b/artistlib/hardware/xray_detector.py @@ -17,7 +17,29 @@ from artistlib.remote_connection import Junction from .base_hardware import BaseHardware +import numpy as np + class XrayDetector(BaseHardware): def __init__(self, remote_control: Junction | API) -> None: - super().__init__(remote_control) \ No newline at end of file + super().__init__(remote_control) + + @property + def detector_resolution_mm(self) -> np.ndarray: + return_value = self.rc.send('::XDetector::GetResolution') + return_value = np.array(np.float32(return_value.split(" "))) + return return_value + + @detector_resolution_mm.setter + def detector_resolution_mm(self, detector_resolution_mm: np.ndarray) -> None: + self.rc.send(f'::XDetector::SetResolution {detector_resolution_mm[0], detector_resolution_mm[1]}') + + @property + def detector_count_px(self) -> np.ndarray: + return_value = self.rc.send(':XDetector::GetPixelSize') + return_value = np.array(np.int32(return_value.split(" "))) + return return_value + + @detector_count_px.setter + def detector_count_px(self, detector_count_px: np.ndarray) -> None: + self.rc.send(f'::XDetector::SetPixelSize {detector_count_px[0], detector_count_px[1]}') \ No newline at end of file diff --git a/artistlib/trajectory/__init__.py b/artistlib/trajectory/__init__.py new file mode 100644 index 0000000..cd65e4b --- /dev/null +++ b/artistlib/trajectory/__init__.py @@ -0,0 +1,15 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +from .ct_trajectories import circular_trajectory, look_at_orientation, sphere_trajectory diff --git a/artistlib/trajectory/ct_trajectories.py b/artistlib/trajectory/ct_trajectories.py new file mode 100644 index 0000000..da746d6 --- /dev/null +++ b/artistlib/trajectory/ct_trajectories.py @@ -0,0 +1,79 @@ +# Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +from __future__ import annotations + +import numpy as np +from scipy.spatial.transform import Rotation + + +def circular_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) -> tuple[np.ndarray, np.ndarray, np.ndarray]: + if fod_mm > fdd_mm: + raise ValueError('fod > fdd.') + + rotation_angles = np.linspace(0., np.pi*1.2, number_of_projections, endpoint=False) + rotation_object = Rotation.from_euler('Y', rotation_angles, degrees=False) + + source_initial_position = np.array([0., 0., fod_mm]) + detector_initial_position = np.array([0., 0., fod_mm - fdd_mm]) + + source_positions = rotation_object.apply(source_initial_position) + detector_positions = rotation_object.apply(detector_initial_position) + + return source_positions, detector_positions, rotation_angles * 180. / np.pi + +def look_at_orientation(source, detector, up_vector: np.ndarray = np.array([0., 1., 0.])): + normal = source - detector + normal = normal / np.linalg.norm(normal) + + up_axis = int(np.argmax(up_vector)) + + line = np.cross(normal, up_vector) + col = np.cross(line, normal) + + if np.sign(col[up_axis]) != np.sign(up_vector[up_axis]): + col *= -1. + + line = np.cross(normal, col) + + rotation_matrix = np.eye(3) + rotation_matrix[:, 0] = line + rotation_matrix[:, 1] = col + rotation_matrix[:, 2] = normal + + if np.linalg.det(rotation_matrix) < 0.0: + rotation_matrix[:, np.argmax(up_vector)] *= -1. + + return rotation_matrix + +def sphere_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) -> tuple[np.ndarray, np.ndarray, np.ndarray]: + phi = (1.0 + np.sqrt(5.0)) / 2.0 + start = -(number_of_projections - 1.) + end = number_of_projections - 1. + i = np.linspace(start, end, number_of_projections) + theta = np.divide(2. * i * np.pi, phi) + sphi = i / number_of_projections + cphi = np.sqrt((number_of_projections + i) * (number_of_projections - i)) / number_of_projections + + point_array = np.zeros((number_of_projections, 3)) + + point_array[:, 0] = cphi * np.cos(theta) + point_array[:, 1] = sphi + point_array[:, 2] = cphi * np.sin(theta) + + source_positions = point_array * fod_mm + detector_positions = point_array * (fod_mm - fdd_mm) + orientation = np.array(list(map(look_at_orientation, source_positions, detector_positions))) + + return source_positions, detector_positions, orientation + diff --git a/examples/01_api_example.py b/examples/01_api_example.py index 0815fb2..0b42499 100644 --- a/examples/01_api_example.py +++ b/examples/01_api_example.py @@ -42,7 +42,6 @@ def main(): print(f'Source Exposure: {source.exposure_ma} mA') print(f'Source Type: {source.source_type}') - # Make a projection an visualize it in python image = artist_api.get_image() diff --git a/examples/02_circular_trajectory.py b/examples/02_circular_trajectory.py index 38952ef..2f09b89 100644 --- a/examples/02_circular_trajectory.py +++ b/examples/02_circular_trajectory.py @@ -13,34 +13,21 @@ # limitations under the License. from __future__ import annotations -import numpy as np -from scipy.spatial.transform import Rotation from matplotlib import pyplot as plt from artistlib import API +from artistlib.trajectory import circular_trajectory -def generate_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) -> tuple[np.ndarray]: - if fod_mm > fdd_mm: - raise ValueError('fod > fdd.') +NUMBER_OF_PROJECTIONS = 20 - rotation_angles = np.linspace(-np.pi, np.pi, number_of_projections, endpoint=False) - rotation_object = Rotation.from_euler('Y', rotation_angles, degrees=False) - - source_initial_position = np.array([0., 0., fod_mm]) - detector_initial_position = np.array([0., 0., fod_mm - fdd_mm]) - - source_positions = rotation_object.apply(source_initial_position) - detector_positions = rotation_object.apply(detector_initial_position) - - return zip(source_positions, detector_positions, rotation_angles * 180 / np.pi) def main(): - trajectory = generate_trajectory(500., 1000., 20) + trajectory = circular_trajectory(500., 1000., NUMBER_OF_PROJECTIONS) api = API() - for scan_pose in trajectory: - source, detector, beta_angles = scan_pose + for i in range(NUMBER_OF_PROJECTIONS): + source, detector, beta_angles = trajectory[0][i], trajectory[1][i], trajectory[2][i] api.translate('S', *source) api.translate('D', *detector) @@ -51,6 +38,7 @@ def main(): plt.imshow(image) plt.show() + if __name__ == '__main__': main() \ No newline at end of file From f1fb1fd1740a6da71be04d6d629093ef6dc859d8 Mon Sep 17 00:00:00 2001 From: swittl Date: Tue, 17 Oct 2023 11:20:36 +0200 Subject: [PATCH 05/21] detector dummy --- artistlib/hardware/xray_detector.py | 8 +++++--- examples/01_api_example.py | 10 +++++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/artistlib/hardware/xray_detector.py b/artistlib/hardware/xray_detector.py index 043bb13..168b191 100644 --- a/artistlib/hardware/xray_detector.py +++ b/artistlib/hardware/xray_detector.py @@ -32,14 +32,16 @@ def detector_resolution_mm(self) -> np.ndarray: @detector_resolution_mm.setter def detector_resolution_mm(self, detector_resolution_mm: np.ndarray) -> None: - self.rc.send(f'::XDetector::SetResolution {detector_resolution_mm[0], detector_resolution_mm[1]}') + self.rc.send(f'set ::Xsetup_private(DGdx) {detector_resolution_mm[0]}') + self.rc.send(f'set ::Xsetup_private(DGdy) {detector_resolution_mm[1]}') @property def detector_count_px(self) -> np.ndarray: - return_value = self.rc.send(':XDetector::GetPixelSize') + return_value = self.rc.send('::XDetector::GetPixelSize') return_value = np.array(np.int32(return_value.split(" "))) return return_value @detector_count_px.setter def detector_count_px(self, detector_count_px: np.ndarray) -> None: - self.rc.send(f'::XDetector::SetPixelSize {detector_count_px[0], detector_count_px[1]}') \ No newline at end of file + self.rc.send(f'set ::Xsetup(DetectorPixelX) {detector_count_px[0]}') + self.rc.send(f'set ::Xsetup(DetectorPixelY) {detector_count_px[1]}') \ No newline at end of file diff --git a/examples/01_api_example.py b/examples/01_api_example.py index 0b42499..9facd6f 100644 --- a/examples/01_api_example.py +++ b/examples/01_api_example.py @@ -15,7 +15,7 @@ import matplotlib.pyplot as plt from artistlib import API -from artistlib.hardware import XraySource +from artistlib.hardware import XraySource, XrayDetector def main(): @@ -42,6 +42,14 @@ def main(): print(f'Source Exposure: {source.exposure_ma} mA') print(f'Source Type: {source.source_type}') + # Create a detector object and set the resolution + detector = XrayDetector(artist_api) + detector.detector_resolution_mm = [0.1, 0.15] + detector.detector_count_px = [1000, 1000] + + print(f'Detector Resolution: {detector.detector_resolution_mm} mm') + print(f'Detector Pixel Count: {detector.detector_count_px} px') + # Make a projection an visualize it in python image = artist_api.get_image() From 08a76d1ae9b4732662d0dae50536d6e3b092d74c Mon Sep 17 00:00:00 2001 From: swittl Date: Wed, 18 Oct 2023 07:30:33 +0200 Subject: [PATCH 06/21] load part update --- artistlib/__init__.py | 1 + artistlib/api.py | 137 ++++++++++++++++++++++- artistlib/{hardware => }/common_types.py | 9 +- artistlib/hardware/base_hardware.py | 8 +- artistlib/hardware/xray_detector.py | 13 ++- artistlib/hardware/xray_source.py | 6 +- artistlib/remote_connection.py | 4 +- examples/01_api_example.py | 19 +++- 8 files changed, 181 insertions(+), 16 deletions(-) rename artistlib/{hardware => }/common_types.py (85%) diff --git a/artistlib/__init__.py b/artistlib/__init__.py index 25797a2..2586765 100644 --- a/artistlib/__init__.py +++ b/artistlib/__init__.py @@ -9,6 +9,7 @@ from ._version import get_versions as __get_versions from .remote_connection import Junction from .api import API +from .common_types import SAVEMODES, SOURCETYPES __version__ = __get_versions()['version'] diff --git a/artistlib/api.py b/artistlib/api.py index adfd6d3..50612e9 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -13,7 +13,8 @@ # limitations under the License. from __future__ import annotations -from .remote_connection import Junction +from .remote_connection import Junction, _rc +from .common_types import SAVEMODES import numpy as np @@ -23,34 +24,152 @@ class API(): - def __init__(self, remote_control: Junction = Junction()) -> None: + def __init__(self, remote_control: Junction = None) -> None: + if remote_control is None: + remote_control = _rc self.rc = remote_control + @staticmethod + def path_to_artist(path: Path) -> str: + return str(path.absolute()).replace('\\', '\\\\') + def get_image(self) -> np.ndarray: + """Make a projection of the current scene. + + Returns: + np.ndarray: projection as ndarray. + """ self.rc.send('set imgList [Engine::Go]') self.rc.send('RemoteControl::SendImage [lindex $imgList 0]') return self.rc.get_image() + + def save_image(self, + save_path: Path, + save_mode: SAVEMODES = SAVEMODES.UINT16, + save_projection_geometry: bool = True): + """Save the current scene as projection. The projection geometry can be stored in a .json file. + + Args: + save_path (Path): Save path of the Projection + save_mode (SAVEMODES, optional): File type of saved projection. Defaults to SAVEMODES.UINT16. + save_projection_geometry (bool, optional): Projection geometry of the scene. Stem of save_path is used as path. Defaults to True. + """ + + if save_projection_geometry: + save_path_json = save_path.parent / (save_path.stem + '.json') + with open(str(save_path_json), 'w') as f: + json.dump(self.projection_geometry(), f, indent=4) + + if save_mode == SAVEMODES.UINT8: + self._save_image_uint8(save_path) + elif save_mode == SAVEMODES.UINT16: + self._save_image_uint16(save_path) + elif save_mode == SAVEMODES.FLOAT_TIFF: + self._save_image_float_tiff(save_path) + elif save_mode == SAVEMODES.FLOAT_RAW: + self._save_image_float_raw(save_path) + elif save_mode == SAVEMODES.PNG: + self._save_image_png(save_path) + + def _save_image_uint16(self, save_path: Path): + """Saves the current scene as porjection (.tif) and geometry (.json). + + Args: + save_path (Path): Save path of the projection. + """ + self.rc.send('set imgList [Engine::Go]') + save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') + self.rc.send(f'Image::Save16bit [lindex $imgList 0] {save_path_projection} True') + self.rc.send('foreach i $imgList {$i Delete}') + + def _save_image_uint8(self, save_path: Path): + """Saves the current scene as porjection (.tif) and geometry (.json). + + Args: + save_path (Path): Save path of the projection. + """ + self.rc.send('set imgList [Engine::Go]') + save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') + save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', + self.rc.send(f'Image::Save8bit [lindex $imgList 0] {save_path_projection} True') + self.rc.send('foreach i $imgList {$i Delete}') + + with open(str(save_path_json), 'w') as f: + json.dump(self.projection_geometry(), f, indent=4) + + def _save_image_float_tiff(self, save_path: Path): + """Saves the current scene as porjection (.tiff) and geometry (.json). + + Args: + save_path (Path): Save path of the projection. + """ + self.rc.send('set imgList [Engine::Go]') + save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') + save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', + self.rc.send(f'Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True') + self.rc.send('foreach i $imgList {$i Delete}') - def save_image_uint16(self, save_path: Path): + with open(str(save_path_json), 'w') as f: + json.dump(self.projection_geometry(), f, indent=4) + + def _save_image_float_raw(self, save_path: Path): + """Saves the current scene as porjection (.raw) and geometry (.json). + + Args: + save_path (Path): Save path of the projection. + """ self.rc.send('set imgList [Engine::Go]') save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', - self.rc.send(f'Image::SaveFile [lindex $imgList 0] {save_path_projection} true') + self.rc.send(f'Image::SaveFloatRawFile [lindex $imgList 0] {save_path_projection} True') self.rc.send('foreach i $imgList {$i Delete}') with open(str(save_path_json), 'w') as f: json.dump(self.projection_geometry(), f, indent=4) + + def _save_image_png(self, save_path: Path): + """Saves the current scene as porjection (.png) and geometry (.json). + + Args: + save_path (Path): Save path of the projection. + """ + self.rc.send('set imgList [Engine::Go]') + save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') + self.rc.send(f'Image::SavePNG [lindex $imgList 0] {save_path_projection} True') + self.rc.send('foreach i $imgList {$i Delete}') def translate(self, id: int | str, x: float = 0.0, y: float = 0.0, z: float = 0.0) -> None: + """Moves an object to an absolute position. All values in [mm]. + + Args: + id (int | str): ID of the Object. + x (float, optional): Absolute X position. Defaults to 0.0. + y (float, optional): Absolute Y position. Defaults to 0.0. + z (float, optional): Absolute Z position. Defaults to 0.0. + """ self.rc.send(f'::PartList::Invoke {str(id)} SetPosition {str(x)} {str(y)} {str(z)};') self.rc.send(f'::PartList::Invoke {str(id)} SetRefPos {str(x)} {str(y)} {str(z)};') def rotate(self, id: int | str, alpha: float = 0.0, beta: float = 0.0, gamma: float = 0.0) -> None: + """Rotates an object to an absolute position. All values in [°]. + + Args: + id (int | str): _description_ + alpha (float, optional): Absolute alpha rotation. Defaults to 0.0. + beta (float, optional): Absolute beta rotation. Defaults to 0.0. + gamma (float, optional): Absolute gamma rotation. Defaults to 0.0. + """ position = self.get_position(id) self.rc.send(f'::PartList::Invoke {str(id)} SetRefPos {str(position[0])} {str(position[1])} {str(position[2])};') self.rc.send(f'::PartList::Invoke {str(id)} SetOrientation {str(alpha)} {str(beta)} {str(gamma)};') def rotate_from_rotation_matrix(self, id: int | str, rotation_matrix: np.ndarray) -> None: + """_summary_ + + Args: + id (int | str): ID of the Object. + rotation_matrix (np.ndarray): _description_ + """ rotation = Rotation.from_matrix(rotation_matrix) euler_scipy = rotation.as_euler("ZXY", degrees=True) euler_scipy = [euler_scipy[1], euler_scipy[2], euler_scipy[0]] @@ -108,3 +227,13 @@ def get_detector_resolution(self) -> np.ndarray: def get_detector_pixel_count(self) -> np.ndarray: result = self.rc.send(f'::XDetector::GetPixelSize') return np.array(np.int32(result.split(" "))) + + def set_material(self, id: int | str, material: str): + self.rc.send(f':::PartList::SetMaterial {material} {id}') + + def load_part(self, load_path: Path, material: str = 'Al', name: str = 'Object') -> int: + return_value = self.rc.send(f'set obj [::PartList::LoadPart "{self.path_to_artist(load_path)}" "{material}" "{name}"]') + return int(return_value) + + def delete_part(self, id: int | str): + self.rc.send(f'::PartList::Delete "{id}"') diff --git a/artistlib/hardware/common_types.py b/artistlib/common_types.py similarity index 85% rename from artistlib/hardware/common_types.py rename to artistlib/common_types.py index 0d80ddc..b5b0b92 100644 --- a/artistlib/hardware/common_types.py +++ b/artistlib/common_types.py @@ -16,4 +16,11 @@ class SOURCETYPES(IntEnum): MONOCHROMATIC = 0 - GENERAL = 1 \ No newline at end of file + GENERAL = 1 + +class SAVEMODES(IntEnum): + UINT8 = 0 + UINT16 = 1 + FLOAT_TIFF = 2 + FLOAT_RAW = 3 + PNG = 4 \ No newline at end of file diff --git a/artistlib/hardware/base_hardware.py b/artistlib/hardware/base_hardware.py index 72afbd7..10a13cf 100644 --- a/artistlib/hardware/base_hardware.py +++ b/artistlib/hardware/base_hardware.py @@ -13,15 +13,17 @@ # limitations under the License. from __future__ import annotations -from ..remote_connection import Junction +from ..remote_connection import Junction, _rc from ..api import API class BaseHardware(): - def __init__(self, remote_control: Junction | API) -> None: + def __init__(self, remote_control: Junction | API = None) -> None: if isinstance(remote_control, Junction): self.rc = remote_control elif isinstance(remote_control, API): self.rc = remote_control.rc + elif remote_control is None: + self.rc = _rc else: - raise ValueError('Wrong remote_control argument?') \ No newline at end of file + raise ValueError('Wrong remote_control argument?') diff --git a/artistlib/hardware/xray_detector.py b/artistlib/hardware/xray_detector.py index 168b191..d5fbfeb 100644 --- a/artistlib/hardware/xray_detector.py +++ b/artistlib/hardware/xray_detector.py @@ -21,7 +21,7 @@ class XrayDetector(BaseHardware): - def __init__(self, remote_control: Junction | API) -> None: + def __init__(self, remote_control: Junction | API = None) -> None: super().__init__(remote_control) @property @@ -44,4 +44,13 @@ def detector_count_px(self) -> np.ndarray: @detector_count_px.setter def detector_count_px(self, detector_count_px: np.ndarray) -> None: self.rc.send(f'set ::Xsetup(DetectorPixelX) {detector_count_px[0]}') - self.rc.send(f'set ::Xsetup(DetectorPixelY) {detector_count_px[1]}') \ No newline at end of file + self.rc.send(f'set ::Xsetup(DetectorPixelY) {detector_count_px[1]}') + + @property + def flatfield_correction(self) -> bool: + return_value = self.rc.send('array get Xdetector FFCorrRun') + return_value = return_value.split(' ')[1] + return bool(return_value) + + + diff --git a/artistlib/hardware/xray_source.py b/artistlib/hardware/xray_source.py index 3694e02..5d4707f 100644 --- a/artistlib/hardware/xray_source.py +++ b/artistlib/hardware/xray_source.py @@ -18,11 +18,11 @@ from artistlib.remote_connection import Junction from .base_hardware import BaseHardware -from .common_types import SOURCETYPES +from ..common_types import SOURCETYPES class XraySource(BaseHardware): - def __init__(self, remote_control: Junction | API) -> None: + def __init__(self, remote_control: Junction | API = None) -> None: super().__init__(remote_control) @property @@ -84,4 +84,4 @@ def source_type(self, source_type: SOURCETYPES) -> None: self.rc.send(f'set ::Xsource(Tube) Mono') elif source_type == SOURCETYPES.GENERAL: self.rc.send(f'set ::Xsource(Tube) General') - self.rc.send(f'::XSource::ComputeSpectrum') \ No newline at end of file + self.rc.send(f'::XSource::ComputeSpectrum') diff --git a/artistlib/remote_connection.py b/artistlib/remote_connection.py index 24a2454..ad5492d 100644 --- a/artistlib/remote_connection.py +++ b/artistlib/remote_connection.py @@ -144,4 +144,6 @@ def get_image(self) -> np.ndarray: decodedData = base64.b64decode((imageData)) imageHeader = self.answer["IMAGE"].split() dtype = np.double - return np.frombuffer(decodedData, dtype).reshape((int(imageHeader[1]),int(imageHeader[2]))) \ No newline at end of file + return np.frombuffer(decodedData, dtype).reshape((int(imageHeader[1]),int(imageHeader[2]))) + +_rc = Junction() \ No newline at end of file diff --git a/examples/01_api_example.py b/examples/01_api_example.py index 9facd6f..cb94ac0 100644 --- a/examples/01_api_example.py +++ b/examples/01_api_example.py @@ -13,6 +13,7 @@ # limitations under the License. import matplotlib.pyplot as plt +from pathlib import Path from artistlib import API from artistlib.hardware import XraySource, XrayDetector @@ -34,7 +35,7 @@ def main(): print(f'Source Orientation: {source_orientation}') # Create a source object and set the voltage - source = XraySource(artist_api) + source = XraySource() source.voltage_kv = 142. source.exposure_ma = 10. @@ -43,7 +44,7 @@ def main(): print(f'Source Type: {source.source_type}') # Create a detector object and set the resolution - detector = XrayDetector(artist_api) + detector = XrayDetector() detector.detector_resolution_mm = [0.1, 0.15] detector.detector_count_px = [1000, 1000] @@ -53,8 +54,22 @@ def main(): # Make a projection an visualize it in python image = artist_api.get_image() + # Load .stl part + new_id = artist_api.load_part( + Path(r'C:\Program Files\BAM\aRTist 2.12\Data\Library\ExampleParts\Fun\Dog.stl'), + 'Fe', + 'test_object') + + print(f'Inserted ID: {new_id}') + + # change material + artist_api.set_material(new_id, 'Al') + plt.imshow(image) plt.show() + # Delete part + artist_api.delete_part(new_id) + if __name__ == '__main__': main() From 0aaf9107aa4bd7ca9f3cd7ef099f0f46d5e03362 Mon Sep 17 00:00:00 2001 From: swittl Date: Fri, 20 Oct 2023 09:22:27 +0200 Subject: [PATCH 07/21] visibility update --- artistlib/api.py | 9 ++++++++- examples/01_api_example.py | 3 +++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/artistlib/api.py b/artistlib/api.py index 50612e9..1d9ff5f 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -229,7 +229,10 @@ def get_detector_pixel_count(self) -> np.ndarray: return np.array(np.int32(result.split(" "))) def set_material(self, id: int | str, material: str): - self.rc.send(f':::PartList::SetMaterial {material} {id}') + self.rc.send(f'::PartList::SetMaterial {material} {id}') + + def get_material(self, id: int | str): + return_value = self.rc.send(f'::PartList::Get {id} Material') def load_part(self, load_path: Path, material: str = 'Al', name: str = 'Object') -> int: return_value = self.rc.send(f'set obj [::PartList::LoadPart "{self.path_to_artist(load_path)}" "{material}" "{name}"]') @@ -237,3 +240,7 @@ def load_part(self, load_path: Path, material: str = 'Al', name: str = 'Object') def delete_part(self, id: int | str): self.rc.send(f'::PartList::Delete "{id}"') + + def set_visibility(self, id: int | str, visible: bool = True): + visible = 'on' if visible else 'off' + self.rc.send(f'[::PartList::Get {id} Obj] SetVisibility "{visible}"') diff --git a/examples/01_api_example.py b/examples/01_api_example.py index cb94ac0..da7d5aa 100644 --- a/examples/01_api_example.py +++ b/examples/01_api_example.py @@ -68,6 +68,9 @@ def main(): plt.imshow(image) plt.show() + # Set visibility off + artist_api.set_visibility(new_id, False) + # Delete part artist_api.delete_part(new_id) From a97fe125b686c2f6e621cb12b4d68fc277198efd Mon Sep 17 00:00:00 2001 From: swittl Date: Fri, 27 Oct 2023 09:47:29 +0200 Subject: [PATCH 08/21] added docu --- artistlib/api.py | 81 +++++++++++++++++++++++++++-- artistlib/hardware/xray_detector.py | 20 +++++++ artistlib/hardware/xray_source.py | 34 +++++++++++- examples/01_api_example.py | 2 +- project.toml | 8 +-- setup.py | 4 +- 6 files changed, 138 insertions(+), 11 deletions(-) diff --git a/artistlib/api.py b/artistlib/api.py index 1d9ff5f..0d35d28 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -164,11 +164,11 @@ def rotate(self, id: int | str, alpha: float = 0.0, beta: float = 0.0, gamma: fl self.rc.send(f'::PartList::Invoke {str(id)} SetOrientation {str(alpha)} {str(beta)} {str(gamma)};') def rotate_from_rotation_matrix(self, id: int | str, rotation_matrix: np.ndarray) -> None: - """_summary_ + """Rotates an object to an absolute position. Args: id (int | str): ID of the Object. - rotation_matrix (np.ndarray): _description_ + rotation_matrix (np.ndarray): Rotationmatix in world coordinate system. """ rotation = Rotation.from_matrix(rotation_matrix) euler_scipy = rotation.as_euler("ZXY", degrees=True) @@ -176,10 +176,27 @@ def rotate_from_rotation_matrix(self, id: int | str, rotation_matrix: np.ndarray self.rotate(id, *euler_scipy) def get_position(self, id: int | str) -> np.ndarray: + """Returns the current position of the object in [mm]. + + Args: + id (int | str): ID of the Object. + + Returns: + np.ndarray: position (x,y,z) in [mm]. + """ result = self.rc.send(f'[::PartList::Get {id} Obj] GetPosition') return np.float32(result[1:-1].split(" ")) def get_euler_angles(self, id: int | str) -> np.ndarray: + """Returns the current orientation of the object as euler angles in the ZXY convention. + + Args: + id (int | str): ID of the Object. + + + Returns: + np.ndarray: Euler angle in ZXY convention. + """ result = self.rc.send(f'[::PartList::Get {id} Obj] GetOrientation') return np.float32(result[1:-1].split(" ")) @@ -197,10 +214,25 @@ def get_rotation_matrix(self, id: int | str) -> np.ndarray: return rotation def get_orientation(self, id) -> np.ndarray: + """Return the current orientation of the object as quarternion. + + Args: + id (int | str): ID of the Object. + + Returns: + np.ndarray: Quarternion of the object in the wolrd coordinate system. + """ rotation = Rotation.from_matrix(self.get_rotation_matrix(id)) return rotation.as_quat() - def projection_geometry(self): + def projection_geometry(self) -> dict: + """Returns the current projection geometry of the scene. All positions are in [mm]. + + Returns: + dict: Dictionary of the projection geometry. Keys are: 'source_position_mm', + 'source_orientation_matrix', 'detector_position_mm', 'detector_orientation_matrix', + 'detector_count_px' and 'detector_resolution_mm' + """ source_position = np.array(self.get_position('S')) source_orientation = np.array(self.get_rotation_matrix('S')) detector_position = np.array(self.get_position('D')) @@ -221,26 +253,69 @@ def projection_geometry(self): return data_dict def get_detector_resolution(self) -> np.ndarray: + """Returns the current pixel pitch of the detector as array + + Returns: + np.ndarray: Pixel pitch of the detector (u, v). + """ result = self.rc.send(f'::XDetector::GetResolution') return np.array(np.float32(result.split(" "))) def get_detector_pixel_count(self) -> np.ndarray: + """Returns the current pixel count of the detector. + + Returns: + np.ndarray: Pixel count (u, v). + """ result = self.rc.send(f'::XDetector::GetPixelSize') return np.array(np.int32(result.split(" "))) def set_material(self, id: int | str, material: str): + """Changes the material of the object. + + Args: + id (int | str): ID of the Object. + material (str): Matiral as string. !!!Must be in the material database of artist!!! + """ self.rc.send(f'::PartList::SetMaterial {material} {id}') def get_material(self, id: int | str): + """Returns the material of the object. + + Args: + id (int | str): ID of the Object. + """ return_value = self.rc.send(f'::PartList::Get {id} Material') + return return_value def load_part(self, load_path: Path, material: str = 'Al', name: str = 'Object') -> int: + """Loads a mesh file into the artist scene. Returns the object id for further mainpulations. + + Args: + load_path (Path): Path object pointing to the mesh file. + material (str, optional): Material of the mesh file. Defaults to 'Al'. + name (str, optional): Displayed name in the aRTist GUI. Defaults to 'Object'. + + Returns: + int: Object ID for further Manipulations. + """ return_value = self.rc.send(f'set obj [::PartList::LoadPart "{self.path_to_artist(load_path)}" "{material}" "{name}"]') return int(return_value) def delete_part(self, id: int | str): + """Delets the object from the scene. + + Args: + id (int | str): ID of the Object. + """ self.rc.send(f'::PartList::Delete "{id}"') def set_visibility(self, id: int | str, visible: bool = True): + """Sets the Object in/visiible. + + Args: + id (int | str): ID of the Object. + visible (bool, optional): Visible: True. Defaults to True. + """ visible = 'on' if visible else 'off' self.rc.send(f'[::PartList::Get {id} Obj] SetVisibility "{visible}"') diff --git a/artistlib/hardware/xray_detector.py b/artistlib/hardware/xray_detector.py index d5fbfeb..1a5cef8 100644 --- a/artistlib/hardware/xray_detector.py +++ b/artistlib/hardware/xray_detector.py @@ -22,10 +22,20 @@ class XrayDetector(BaseHardware): def __init__(self, remote_control: Junction | API = None) -> None: + """XRay detector object. Needs a remote control connection. + + Args: + remote_control (Junction | API, optional): Remote control connection for the communication with artist. Defaults to None. + """ super().__init__(remote_control) @property def detector_resolution_mm(self) -> np.ndarray: + """Current detector resolution / pixel pitch in [mm]. + + Returns: + np.ndarray: Detector resolution (u, v) in [mm]. + """ return_value = self.rc.send('::XDetector::GetResolution') return_value = np.array(np.float32(return_value.split(" "))) return return_value @@ -37,6 +47,11 @@ def detector_resolution_mm(self, detector_resolution_mm: np.ndarray) -> None: @property def detector_count_px(self) -> np.ndarray: + """Current detector pixel count. + + Returns: + np.ndarray: Detector pixel count (u, v) in [n]. + """ return_value = self.rc.send('::XDetector::GetPixelSize') return_value = np.array(np.int32(return_value.split(" "))) return return_value @@ -48,6 +63,11 @@ def detector_count_px(self, detector_count_px: np.ndarray) -> None: @property def flatfield_correction(self) -> bool: + """Faltfiled corrected? + + Returns: + bool: Return wheter the projection is flatfield corrected or not. + """ return_value = self.rc.send('array get Xdetector FFCorrRun') return_value = return_value.split(' ')[1] return bool(return_value) diff --git a/artistlib/hardware/xray_source.py b/artistlib/hardware/xray_source.py index 5d4707f..07975b6 100644 --- a/artistlib/hardware/xray_source.py +++ b/artistlib/hardware/xray_source.py @@ -23,10 +23,20 @@ class XraySource(BaseHardware): def __init__(self, remote_control: Junction | API = None) -> None: + """Xray source objet. Needs a remote control connection. + + Args: + remote_control (Junction | API, optional): remote connection to communicate with aRTist. Defaults to None. + """ super().__init__(remote_control) @property def voltage_kv(self) -> float: + """Current voltage setting of the XRay source. + + Returns: + float: Voltage value in [kV]. + """ return_value = self.rc.send('array get Xsource Voltage') return_value = return_value.split(' ')[1] return float(return_value) @@ -38,6 +48,11 @@ def voltage_kv(self, voltage_kv: float) -> None: @property def exposure_ma(self) -> float: + """Current set exposure of the XRay source + + Returns: + float: Exposure in [µA]. + """ return_value = self.rc.send('array get Xsource Exposure') return_value = return_value.split(' ')[1] return float(return_value) @@ -47,10 +62,15 @@ def exposure_ma(self, exposure_ma: float) -> None: self.rc.send(f'set ::Xsource(Exposure) {exposure_ma}') @property - def filter_material(self) -> float: + def filter_material(self) -> str: + """Filter Material of the XRay source. + + Returns: + str: Filter material of the XRay source. + """ return_value = self.rc.send('array get Xsource FilterMaterial') return_value = return_value.split(' ')[1] - return float(return_value) + return str(return_value) @filter_material.setter def filter_material(self, filter_material: float) -> None: @@ -59,6 +79,11 @@ def filter_material(self, filter_material: float) -> None: @property def filter_thickness_mm(self) -> float: + """Thickness of the filter in [mm]. + + Returns: + float: Filter thickness in [mm]. + """ return_value = self.rc.send('array get Xsource FilterThickness') return_value = return_value.split(' ')[1] return float(return_value) @@ -70,6 +95,11 @@ def filter_thickness_mm(self, filter_thickness_mm: float) -> None: @property def source_type(self) -> int: + """Source type of the XRay source. Types are Monocromatic or General. See SOURCETYPES. + + Returns: + int: Source type as integer. Use SOURCETYPES. + """ return_value = self.rc.send('array get Xsource Tube') return_value = return_value.split(' ')[1] diff --git a/examples/01_api_example.py b/examples/01_api_example.py index da7d5aa..4d51172 100644 --- a/examples/01_api_example.py +++ b/examples/01_api_example.py @@ -56,7 +56,7 @@ def main(): # Load .stl part new_id = artist_api.load_part( - Path(r'C:\Program Files\BAM\aRTist 2.12\Data\Library\ExampleParts\Fun\Dog.stl'), + Path(r'C:\Program Files\BAM\aRTist 2.12\Data\Library\ExampleParts\Fun\Dog.stl'), # Plesas check where the aRTist software is installed. 'Fe', 'test_object') diff --git a/project.toml b/project.toml index 6cab824..d26117c 100644 --- a/project.toml +++ b/project.toml @@ -1,8 +1,10 @@ [build-system] requires = [ "setuptools>=42", - "versioneer" - "wheel" - "scipy" + "versioneer", + "wheel", + "scipy", + "numpy", + "matplotlib ] build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index 2aa7607..bb8c6ba 100644 --- a/setup.py +++ b/setup.py @@ -9,12 +9,12 @@ cmdclass=versioneer.get_cmdclass(), description='aRTist Python library', url='https://github.com/BAMresearch/aRTist-PythonLib', - author='Carsten Bellon', + author='Carsten Bellon, Simon Wittl', author_email='Carsten.Bellon@bam.de', long_description=long_description, long_description_content_type="text/markdown", license='Apache 2.0', - packages=['artistlib'], + packages=['artistlib', 'artistlib.hardware', 'artistlib.trajectory'], classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: Apache Software License", From 6570262edc2cfd9362de0327cef0c456335999aa Mon Sep 17 00:00:00 2001 From: swittl Date: Wed, 20 Mar 2024 07:27:36 +0100 Subject: [PATCH 09/21] added spectrum --- .gitignore | 7 +++- artistlib/api.py | 31 +++++++++++----- artistlib/trajectory/ct_trajectories.py | 6 ++-- examples/03_get_spectrum.py | 47 +++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 13 deletions(-) create mode 100644 examples/03_get_spectrum.py diff --git a/.gitignore b/.gitignore index 105479e..451b672 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,9 @@ artistlib.egg-info dist /venv/ *.tif -/workspace/ \ No newline at end of file +/workspace/ +*.raw +*.stl +*.json +*.aRTist +*.ply \ No newline at end of file diff --git a/artistlib/api.py b/artistlib/api.py index 0d35d28..b24f0c1 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -54,12 +54,12 @@ def save_image(self, save_mode (SAVEMODES, optional): File type of saved projection. Defaults to SAVEMODES.UINT16. save_projection_geometry (bool, optional): Projection geometry of the scene. Stem of save_path is used as path. Defaults to True. """ - + save_path = save_path.resolve() if save_projection_geometry: save_path_json = save_path.parent / (save_path.stem + '.json') with open(str(save_path_json), 'w') as f: json.dump(self.projection_geometry(), f, indent=4) - + if save_mode == SAVEMODES.UINT8: self._save_image_uint8(save_path) elif save_mode == SAVEMODES.UINT16: @@ -150,6 +150,17 @@ def translate(self, id: int | str, x: float = 0.0, y: float = 0.0, z: float = 0. self.rc.send(f'::PartList::Invoke {str(id)} SetPosition {str(x)} {str(y)} {str(z)};') self.rc.send(f'::PartList::Invoke {str(id)} SetRefPos {str(x)} {str(y)} {str(z)};') + def scale(self, id: int | str, x: float = 1.0) -> None: + """Moves an object to an absolute position. All values in [mm]. + + Args: + id (int | str): ID of the Object. + x (float, optional): Absolute X position. Defaults to 0.0. + y (float, optional): Absolute Y position. Defaults to 0.0. + z (float, optional): Absolute Z position. Defaults to 0.0. + """ + self.rc.send(f'::PartList::Invoke {str(id)} SetScale {str(x)} {str(x)} {str(x)};') + def rotate(self, id: int | str, alpha: float = 0.0, beta: float = 0.0, gamma: float = 0.0) -> None: """Rotates an object to an absolute position. All values in [°]. @@ -229,8 +240,9 @@ def projection_geometry(self) -> dict: """Returns the current projection geometry of the scene. All positions are in [mm]. Returns: - dict: Dictionary of the projection geometry. Keys are: 'source_position_mm', - 'source_orientation_matrix', 'detector_position_mm', 'detector_orientation_matrix', + dict: Dictionary of the projection geometry. Keys are: 'focal_spot_position_mm', + 'focal_spot_orientation_matrix', 'detector_center_position_mm', + 'detector_center_orientation_matrix', 'detector_center_orientation_quat', 'detector_count_px' and 'detector_resolution_mm' """ source_position = np.array(self.get_position('S')) @@ -242,13 +254,14 @@ def projection_geometry(self) -> dict: detector_pixel_count = self.get_detector_pixel_count() data_dict = dict() - data_dict['source_position_mm'] = source_position.tolist() - data_dict['source_orientation_matrix'] = source_orientation.tolist() - data_dict['detector_position_mm'] = detector_position.tolist() - data_dict['detector_orientation_matrix'] = detector_orientation.tolist() + data_dict['focal_spot_position_mm'] = source_position.tolist() + data_dict['focal_spot_orientation_matrix'] = source_orientation.tolist() + data_dict['detector_center_position_mm'] = detector_position.tolist() + data_dict['detector_center_orientation_matrix'] = detector_orientation.tolist() + data_dict['detector_center_orientation_quat'] = Rotation.from_matrix(detector_orientation).as_quat().tolist() data_dict['detector_count_px'] = detector_pixel_count.tolist() - data_dict['detector_resolution_mm'] = detector_resolution.tolist() + data_dict['pixel_pitch_mm'] = detector_resolution.tolist() return data_dict diff --git a/artistlib/trajectory/ct_trajectories.py b/artistlib/trajectory/ct_trajectories.py index da746d6..56c421e 100644 --- a/artistlib/trajectory/ct_trajectories.py +++ b/artistlib/trajectory/ct_trajectories.py @@ -17,11 +17,11 @@ from scipy.spatial.transform import Rotation -def circular_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) -> tuple[np.ndarray, np.ndarray, np.ndarray]: +def circular_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int, opening_angle: float = 0.2) -> tuple[np.ndarray, np.ndarray, np.ndarray]: if fod_mm > fdd_mm: raise ValueError('fod > fdd.') - rotation_angles = np.linspace(0., np.pi*1.2, number_of_projections, endpoint=False) + rotation_angles = np.linspace(0., np.pi * (1. + opening_angle), number_of_projections, endpoint=False) rotation_object = Rotation.from_euler('Y', rotation_angles, degrees=False) source_initial_position = np.array([0., 0., fod_mm]) @@ -30,7 +30,7 @@ def circular_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int source_positions = rotation_object.apply(source_initial_position) detector_positions = rotation_object.apply(detector_initial_position) - return source_positions, detector_positions, rotation_angles * 180. / np.pi + return source_positions, detector_positions, rotation_object.as_matrix() def look_at_orientation(source, detector, up_vector: np.ndarray = np.array([0., 1., 0.])): normal = source - detector diff --git a/examples/03_get_spectrum.py b/examples/03_get_spectrum.py new file mode 100644 index 0000000..2f33512 --- /dev/null +++ b/examples/03_get_spectrum.py @@ -0,0 +1,47 @@ +from artistlib import API +import numpy as np +from matplotlib import pyplot as plt +from xraydb import mu_elam +import re + +# Install xraydb: pip install xraydb + +def scrap_spectrum(artist_spectrum: str): + spectrum_dict = artist_spectrum.split('# [degrees]} ')[1].split('{# Avg:')[0] + spectrum_dict = spectrum_dict.replace('{', '') + spectrum_dict = spectrum_dict.replace('}', '') + spectrum_dict = spectrum_dict.replace('\t', ' ') + spectrum_dict = spectrum_dict.split(' ')[:-1] + spectrum = np.array(spectrum_dict, np.float32) + return spectrum.reshape((-1, 2)) + + +def get_current_artist_spcectrum(api: API) -> np.ndarray: + return scrap_spectrum(api.rc.send('[Engine::GetSpectrum]')) + + +def main(): + api = API() + current_spectrum = get_current_artist_spcectrum(api) + energy_keV = current_spectrum[:, 0] + photons_n = current_spectrum[:, 1] + + plt.plot(energy_keV, photons_n) + plt.show() + + energy = np.arange(500, 120000, 10) # energy in eV + + for elem in ('C', 'Cu', 'Au'): + mu = mu_elam(elem, energy) + plt.plot(energy, mu) + + plt.title('X-ray mass attenuation') + plt.xlabel('Energy (eV)') + plt.ylabel(r'$\mu/\rho \rm\, (cm^2/gr)$') + plt.legend() + plt.yscale('log') + plt.xscale('log') + plt.show() + +if __name__ == '__main__': + main() \ No newline at end of file From cdf97238a2fb53481b49df1bda135789641f7c0e Mon Sep 17 00:00:00 2001 From: Anton Weiss Date: Wed, 20 Mar 2024 07:40:28 +0100 Subject: [PATCH 10/21] added error message --- .gitignore | 3 ++- build.sh | 6 ------ build_html.sh | 8 -------- build_pdf.sh | 8 -------- 4 files changed, 2 insertions(+), 23 deletions(-) delete mode 100644 build.sh delete mode 100644 build_html.sh delete mode 100644 build_pdf.sh diff --git a/.gitignore b/.gitignore index 451b672..ec951ea 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,5 @@ dist *.stl *.json *.aRTist -*.ply \ No newline at end of file +*.ply +/build/ \ No newline at end of file diff --git a/build.sh b/build.sh deleted file mode 100644 index dcd830f..0000000 --- a/build.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash -rm -R dist -rm -R artistlib.egg-info -python -m build - -# twine upload dist/* \ No newline at end of file diff --git a/build_html.sh b/build_html.sh deleted file mode 100644 index 18e650d..0000000 --- a/build_html.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -# Builds the HTML documentation using pdoc3 -# and moves it to the "docs" folder (instead of docs/artistlib). -pdoc --force --html --template-dir "docs/templates" -o "docs/" artistlib -cp -R docs/artistlib/* docs/ -rm -R docs/artistlib -###pdoc --logo "artistlib.png" --template-dir "docs/templates" -o "docs/" artistlib -###rm -R docs/artistlib \ No newline at end of file diff --git a/build_pdf.sh b/build_pdf.sh deleted file mode 100644 index 34c26c2..0000000 --- a/build_pdf.sh +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/bash -# Builds the documentation as a PDF file, -# using pdoc3 to create a complete Markdown file, -# which is then passed to pandoc to create a LaTeX -# file and a PDF using XeLaTeX. -pdoc --force --pdf artistlib > docs/artistlib.md -pandoc --metadata=title:"aRTsit PythonLib Documentation" --from=markdown+abbreviations+tex_math_single_backslash --pdf-engine=xelatex --variable=mainfont:"DejaVu Sans" --toc --toc-depth=1 --output=docs/artistlib.pdf docs/artistlib.md -rm docs/artistlib.md \ No newline at end of file From 4c8f1bc7726a8566341b52b313fca6b9a3fe34f0 Mon Sep 17 00:00:00 2001 From: Anton Weiss Date: Thu, 21 Mar 2024 09:18:02 +0100 Subject: [PATCH 11/21] added clear --- artistlib/api.py | 6 ++++++ examples/01_api_example.py | 1 + examples/03_get_spectrum.py | 27 +++++++++++++++++---------- examples/04_save_image.py | 16 ++++++++++++++++ 4 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 examples/04_save_image.py diff --git a/artistlib/api.py b/artistlib/api.py index b24f0c1..a0ac03f 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -332,3 +332,9 @@ def set_visibility(self, id: int | str, visible: bool = True): """ visible = 'on' if visible else 'off' self.rc.send(f'[::PartList::Get {id} Obj] SetVisibility "{visible}"') + + def clear_scene(self): + """Clears all objects from the scene. + """ + self.rc.send('::PartList::Clear') + diff --git a/examples/01_api_example.py b/examples/01_api_example.py index 4d51172..9ea47b9 100644 --- a/examples/01_api_example.py +++ b/examples/01_api_example.py @@ -60,6 +60,7 @@ def main(): 'Fe', 'test_object') + artist_api.delete_part('test_object') print(f'Inserted ID: {new_id}') # change material diff --git a/examples/03_get_spectrum.py b/examples/03_get_spectrum.py index 2f33512..a1c722d 100644 --- a/examples/03_get_spectrum.py +++ b/examples/03_get_spectrum.py @@ -7,13 +7,17 @@ # Install xraydb: pip install xraydb def scrap_spectrum(artist_spectrum: str): - spectrum_dict = artist_spectrum.split('# [degrees]} ')[1].split('{# Avg:')[0] - spectrum_dict = spectrum_dict.replace('{', '') - spectrum_dict = spectrum_dict.replace('}', '') - spectrum_dict = spectrum_dict.replace('\t', ' ') - spectrum_dict = spectrum_dict.split(' ')[:-1] - spectrum = np.array(spectrum_dict, np.float32) - return spectrum.reshape((-1, 2)) + try: + spectrum_dict = artist_spectrum.split('# [degrees]} ')[1].split('{# Avg:')[0] + spectrum_dict = spectrum_dict.replace('{', '') + spectrum_dict = spectrum_dict.replace('}', '') + spectrum_dict = spectrum_dict.replace('\t', ' ') + spectrum_dict = spectrum_dict.split(' ')[:-1] + spectrum = np.array(spectrum_dict, np.float32) + return spectrum.reshape((-1, 2)) + except IndexError: + raise ValueError('Ploychromatic Source must be set in aRTist!') + def get_current_artist_spcectrum(api: API) -> np.ndarray: @@ -27,16 +31,19 @@ def main(): photons_n = current_spectrum[:, 1] plt.plot(energy_keV, photons_n) + plt.title('aRTist Source Spectrum') + plt.ylabel('Photons (n)') + plt.xlabel('Energy (keV)') plt.show() energy = np.arange(500, 120000, 10) # energy in eV for elem in ('C', 'Cu', 'Au'): mu = mu_elam(elem, energy) - plt.plot(energy, mu) + plt.plot(energy / 1000., mu, label=elem) - plt.title('X-ray mass attenuation') - plt.xlabel('Energy (eV)') + plt.title('X-ray Mass Attenuation') + plt.xlabel('Energy (keV)') plt.ylabel(r'$\mu/\rho \rm\, (cm^2/gr)$') plt.legend() plt.yscale('log') diff --git a/examples/04_save_image.py b/examples/04_save_image.py new file mode 100644 index 0000000..d83f740 --- /dev/null +++ b/examples/04_save_image.py @@ -0,0 +1,16 @@ +from artistlib import SAVEMODES, API +from pathlib import Path + +def main(): + # Initialize the api. + artist_api = API() + + # Save Folder + save_folder = Path('./workspace') + save_folder.mkdir(exist_ok=True) + + # Save image / Save images and load them is fastern than to send the images via the rc connection. + artist_api.save_image(save_folder / 'projection.tif', SAVEMODES.UINT16, save_projection_geometry=True) + +if __name__ == '__main__': + main() \ No newline at end of file From a795b9eb4b02e1c6694192cd03a7b6f9a1320611 Mon Sep 17 00:00:00 2001 From: swittl Date: Tue, 26 Mar 2024 08:46:18 +0100 Subject: [PATCH 12/21] added load scene / fixes sphere trajectory --- artistlib/api.py | 5 +++++ artistlib/trajectory/ct_trajectories.py | 7 ++++--- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/artistlib/api.py b/artistlib/api.py index a0ac03f..14e4f6a 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -338,3 +338,8 @@ def clear_scene(self): """ self.rc.send('::PartList::Clear') + def load_project(self, project_file: Path): + if project_file.suffix != '.aRTist': + raise ValueError('Wrong File / Path. The *project_file* path must be a .aRTist File!') + self.rc.send(f'::XRayProject::LoadProject "{self.path_to_artist(project_file)}"') + diff --git a/artistlib/trajectory/ct_trajectories.py b/artistlib/trajectory/ct_trajectories.py index 56c421e..6e5ec2d 100644 --- a/artistlib/trajectory/ct_trajectories.py +++ b/artistlib/trajectory/ct_trajectories.py @@ -32,7 +32,7 @@ def circular_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int return source_positions, detector_positions, rotation_object.as_matrix() -def look_at_orientation(source, detector, up_vector: np.ndarray = np.array([0., 1., 0.])): +def look_at_orientation(source, detector, up_vector: np.ndarray = np.array([0., 0., 1.])): normal = source - detector normal = normal / np.linalg.norm(normal) @@ -68,8 +68,9 @@ def sphere_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) point_array = np.zeros((number_of_projections, 3)) point_array[:, 0] = cphi * np.cos(theta) - point_array[:, 1] = sphi - point_array[:, 2] = cphi * np.sin(theta) + + point_array[:, 1] = cphi * np.sin(theta) + point_array[:, 2] = sphi source_positions = point_array * fod_mm detector_positions = point_array * (fod_mm - fdd_mm) From 4f0bc90ed222753d695ef7dadccea8e026566f12 Mon Sep 17 00:00:00 2001 From: swittl Date: Wed, 19 Jun 2024 11:09:15 +0200 Subject: [PATCH 13/21] added load function --- artistlib/api.py | 9 + artistlib/objects/__init__.py | 0 artistlib/remote_connection.py | 2 +- artistlib/trajectory/__init__.py | 2 +- artistlib/trajectory/ct_trajectories.py | 23 +- artistlib/utility/__init__.py | 1 + artistlib/utility/load_projection.py | 19 + setup.cfg | 12 - setup.py | 22 +- versioneer.py | 2194 ----------------------- 10 files changed, 62 insertions(+), 2222 deletions(-) create mode 100644 artistlib/objects/__init__.py create mode 100644 artistlib/utility/__init__.py create mode 100644 artistlib/utility/load_projection.py delete mode 100644 setup.cfg delete mode 100644 versioneer.py diff --git a/artistlib/api.py b/artistlib/api.py index 14e4f6a..09c7fc8 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -185,6 +185,15 @@ def rotate_from_rotation_matrix(self, id: int | str, rotation_matrix: np.ndarray euler_scipy = rotation.as_euler("ZXY", degrees=True) euler_scipy = [euler_scipy[1], euler_scipy[2], euler_scipy[0]] self.rotate(id, *euler_scipy) + + def rotate_from_quat(self, id: int | str, qaurternion: np.ndarray) -> None: + """Rotates an object to an absolute position. + + Args: + id (int | str): ID of the Object. + qaurternion (np.ndarray): Quarternion in world coordinate system. + """ + self.rotate_from_rotation_matrix(id, Rotation.from_quat(qaurternion).as_matrix()) def get_position(self, id: int | str) -> np.ndarray: """Returns the current position of the object in [mm]. diff --git a/artistlib/objects/__init__.py b/artistlib/objects/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/artistlib/remote_connection.py b/artistlib/remote_connection.py index ad5492d..1811348 100644 --- a/artistlib/remote_connection.py +++ b/artistlib/remote_connection.py @@ -41,7 +41,7 @@ def connect(self): self.S.setblocking(True) self.listen(0) except ConnectionRefusedError: - raise ConnectionRefusedError('The Connection to aRTist was refused. Is aRTist running and the remote connection enabled?') + print('The Connection to aRTist was refused. Is aRTist running and the remote connection enabled?') except Exception as e: raise e return self diff --git a/artistlib/trajectory/__init__.py b/artistlib/trajectory/__init__.py index cd65e4b..5f83328 100644 --- a/artistlib/trajectory/__init__.py +++ b/artistlib/trajectory/__init__.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -from .ct_trajectories import circular_trajectory, look_at_orientation, sphere_trajectory +from .ct_trajectories import circular_trajectory, look_at_orientation, sphere_trajectory, arbitary_circular_trajectory diff --git a/artistlib/trajectory/ct_trajectories.py b/artistlib/trajectory/ct_trajectories.py index 6e5ec2d..26a8a8a 100644 --- a/artistlib/trajectory/ct_trajectories.py +++ b/artistlib/trajectory/ct_trajectories.py @@ -68,7 +68,6 @@ def sphere_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) point_array = np.zeros((number_of_projections, 3)) point_array[:, 0] = cphi * np.cos(theta) - point_array[:, 1] = cphi * np.sin(theta) point_array[:, 2] = sphi @@ -78,3 +77,25 @@ def sphere_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) return source_positions, detector_positions, orientation + +def arbitary_circular_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int, transformation: np.ndarray = np.eye(4), opening_angle: float = 0.2): + source_positions, detector_positions, orientation = circular_trajectory(fod_mm, fdd_mm, number_of_projections, opening_angle) + + source_transformation_matrix = np.zeros((number_of_projections, 4, 4)) + source_transformation_matrix[:, 3, 3] = 1. + detector_transformation_matrix = source_transformation_matrix.copy() + + source_transformation_matrix[:, :3, 3] = source_positions + detector_transformation_matrix[:, :3, 3] = detector_positions + + source_transformation_matrix[:, :3, :3] = orientation + detector_transformation_matrix[:, :3, :3] = orientation + + transformation = np.expand_dims(transformation, 0) + source_transformation_matrix = transformation @ source_transformation_matrix + detector_transformation_matrix = transformation @ detector_transformation_matrix + + return source_transformation_matrix[:, :3, 3].reshape((number_of_projections, 3)), detector_transformation_matrix[:, :3, 3].reshape((number_of_projections, 3)), detector_transformation_matrix[:, :3, :3].reshape((number_of_projections, 3, 3)) + + + diff --git a/artistlib/utility/__init__.py b/artistlib/utility/__init__.py new file mode 100644 index 0000000..6bca333 --- /dev/null +++ b/artistlib/utility/__init__.py @@ -0,0 +1 @@ +from .load_projection import load_projection, load_header \ No newline at end of file diff --git a/artistlib/utility/load_projection.py b/artistlib/utility/load_projection.py new file mode 100644 index 0000000..21e8153 --- /dev/null +++ b/artistlib/utility/load_projection.py @@ -0,0 +1,19 @@ +from PIL import Image +import numpy as np +from pathlib import Path +import json + + +def load_projection(projection_path: Path, load_projection_geometry: bool = True) -> tuple[np.ndarray, dict]: + projection_array = np.array(Image.open(projection_path)) + + if not load_projection_geometry: + return projection_array, None + else: + return projection_array, load_header(projection_path) + +def load_header(projection_path) -> dict: + with open(str(projection_path.parent / f'{projection_path.stem}.json'), 'r') as f: + projection_geometry = json.load(f) + + return projection_geometry diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index f81c5e6..0000000 --- a/setup.cfg +++ /dev/null @@ -1,12 +0,0 @@ - -# See the docstring in versioneer.py for instructions. Note that you must -# re-run 'versioneer.py setup' after changing this section, and commit the -# resulting files. - -[versioneer] -VCS = git -style = pep440 -versionfile_source = artistlib/_version.py -versionfile_build = artistlib/_version.py -tag_prefix = v -parentdir_prefix = diff --git a/setup.py b/setup.py index bb8c6ba..27ce5c4 100644 --- a/setup.py +++ b/setup.py @@ -1,20 +1,16 @@ from setuptools import setup -import versioneer - -with open("README.md", "r", encoding="utf-8") as fh: - long_description = fh.read() setup(name='artistlib', - version=versioneer.get_version(), - cmdclass=versioneer.get_cmdclass(), - description='aRTist Python library', - url='https://github.com/BAMresearch/aRTist-PythonLib', - author='Carsten Bellon, Simon Wittl', - author_email='Carsten.Bellon@bam.de', - long_description=long_description, - long_description_content_type="text/markdown", + version='0.1', + description='THD: aRTist Python library', + author='Simon Wittl', + author_email='simon.wittl@th-deg.de', license='Apache 2.0', - packages=['artistlib', 'artistlib.hardware', 'artistlib.trajectory'], + packages=['artistlib', + 'artistlib.hardware', + 'artistlib.trajectory', + 'artistlib.utility', + 'artistlib.objects'], classifiers=[ "Programming Language :: Python :: 3", "License :: OSI Approved :: Apache Software License", diff --git a/versioneer.py b/versioneer.py deleted file mode 100644 index 223db1d..0000000 --- a/versioneer.py +++ /dev/null @@ -1,2194 +0,0 @@ - -# Version: 0.26 - -"""The Versioneer - like a rocketeer, but for versions. - -The Versioneer -============== - -* like a rocketeer, but for versions! -* https://github.com/python-versioneer/python-versioneer -* Brian Warner -* License: Public Domain (Unlicense) -* Compatible with: Python 3.7, 3.8, 3.9, 3.10 and pypy3 -* [![Latest Version][pypi-image]][pypi-url] -* [![Build Status][travis-image]][travis-url] - -This is a tool for managing a recorded version number in setuptools-based -python projects. The goal is to remove the tedious and error-prone "update -the embedded version string" step from your release process. Making a new -release should be as easy as recording a new tag in your version-control -system, and maybe making new tarballs. - - -## Quick Install - -Versioneer provides two installation modes. The "classic" vendored mode installs -a copy of versioneer into your repository. The experimental build-time dependency mode -is intended to allow you to skip this step and simplify the process of upgrading. - -### Vendored mode - -* `pip install versioneer` to somewhere in your $PATH -* add a `[tool.versioneer]` section to your `pyproject.toml or a - `[versioneer]` section to your `setup.cfg` (see [Install](INSTALL.md)) -* run `versioneer install --vendor` in your source tree, commit the results -* verify version information with `python setup.py version` - -### Build-time dependency mode - -* `pip install versioneer` to somewhere in your $PATH -* add a `[tool.versioneer]` section to your `pyproject.toml or a - `[versioneer]` section to your `setup.cfg` (see [Install](INSTALL.md)) -* add `versioneer` to the `requires` key of the `build-system` table in - `pyproject.toml`: - ```toml - [build-system] - requires = ["setuptools", "versioneer"] - build-backend = "setuptools.build_meta" - ``` -* run `versioneer install --no-vendor` in your source tree, commit the results -* verify version information with `python setup.py version` - -## Version Identifiers - -Source trees come from a variety of places: - -* a version-control system checkout (mostly used by developers) -* a nightly tarball, produced by build automation -* a snapshot tarball, produced by a web-based VCS browser, like github's - "tarball from tag" feature -* a release tarball, produced by "setup.py sdist", distributed through PyPI - -Within each source tree, the version identifier (either a string or a number, -this tool is format-agnostic) can come from a variety of places: - -* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows - about recent "tags" and an absolute revision-id -* the name of the directory into which the tarball was unpacked -* an expanded VCS keyword ($Id$, etc) -* a `_version.py` created by some earlier build step - -For released software, the version identifier is closely related to a VCS -tag. Some projects use tag names that include more than just the version -string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool -needs to strip the tag prefix to extract the version identifier. For -unreleased software (between tags), the version identifier should provide -enough information to help developers recreate the same tree, while also -giving them an idea of roughly how old the tree is (after version 1.2, before -version 1.3). Many VCS systems can report a description that captures this, -for example `git describe --tags --dirty --always` reports things like -"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the -0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has -uncommitted changes). - -The version identifier is used for multiple purposes: - -* to allow the module to self-identify its version: `myproject.__version__` -* to choose a name and prefix for a 'setup.py sdist' tarball - -## Theory of Operation - -Versioneer works by adding a special `_version.py` file into your source -tree, where your `__init__.py` can import it. This `_version.py` knows how to -dynamically ask the VCS tool for version information at import time. - -`_version.py` also contains `$Revision$` markers, and the installation -process marks `_version.py` to have this marker rewritten with a tag name -during the `git archive` command. As a result, generated tarballs will -contain enough information to get the proper version. - -To allow `setup.py` to compute a version too, a `versioneer.py` is added to -the top level of your source tree, next to `setup.py` and the `setup.cfg` -that configures it. This overrides several distutils/setuptools commands to -compute the version when invoked, and changes `setup.py build` and `setup.py -sdist` to replace `_version.py` with a small static file that contains just -the generated version data. - -## Installation - -See [INSTALL.md](./INSTALL.md) for detailed installation instructions. - -## Version-String Flavors - -Code which uses Versioneer can learn about its version string at runtime by -importing `_version` from your main `__init__.py` file and running the -`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can -import the top-level `versioneer.py` and run `get_versions()`. - -Both functions return a dictionary with different flavors of version -information: - -* `['version']`: A condensed version string, rendered using the selected - style. This is the most commonly used value for the project's version - string. The default "pep440" style yields strings like `0.11`, - `0.11+2.g1076c97`, or `0.11+2.g1076c97.dirty`. See the "Styles" section - below for alternative styles. - -* `['full-revisionid']`: detailed revision identifier. For Git, this is the - full SHA1 commit id, e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac". - -* `['date']`: Date and time of the latest `HEAD` commit. For Git, it is the - commit date in ISO 8601 format. This will be None if the date is not - available. - -* `['dirty']`: a boolean, True if the tree has uncommitted changes. Note that - this is only accurate if run in a VCS checkout, otherwise it is likely to - be False or None - -* `['error']`: if the version string could not be computed, this will be set - to a string describing the problem, otherwise it will be None. It may be - useful to throw an exception in setup.py if this is set, to avoid e.g. - creating tarballs with a version string of "unknown". - -Some variants are more useful than others. Including `full-revisionid` in a -bug report should allow developers to reconstruct the exact code being tested -(or indicate the presence of local changes that should be shared with the -developers). `version` is suitable for display in an "about" box or a CLI -`--version` output: it can be easily compared against release notes and lists -of bugs fixed in various releases. - -The installer adds the following text to your `__init__.py` to place a basic -version in `YOURPROJECT.__version__`: - - from ._version import get_versions - __version__ = get_versions()['version'] - del get_versions - -## Styles - -The setup.cfg `style=` configuration controls how the VCS information is -rendered into a version string. - -The default style, "pep440", produces a PEP440-compliant string, equal to the -un-prefixed tag name for actual releases, and containing an additional "local -version" section with more detail for in-between builds. For Git, this is -TAG[+DISTANCE.gHEX[.dirty]] , using information from `git describe --tags ---dirty --always`. For example "0.11+2.g1076c97.dirty" indicates that the -tree is like the "1076c97" commit but has uncommitted changes (".dirty"), and -that this commit is two revisions ("+2") beyond the "0.11" tag. For released -software (exactly equal to a known tag), the identifier will only contain the -stripped tag, e.g. "0.11". - -Other styles are available. See [details.md](details.md) in the Versioneer -source tree for descriptions. - -## Debugging - -Versioneer tries to avoid fatal errors: if something goes wrong, it will tend -to return a version of "0+unknown". To investigate the problem, run `setup.py -version`, which will run the version-lookup code in a verbose mode, and will -display the full contents of `get_versions()` (including the `error` string, -which may help identify what went wrong). - -## Known Limitations - -Some situations are known to cause problems for Versioneer. This details the -most significant ones. More can be found on Github -[issues page](https://github.com/python-versioneer/python-versioneer/issues). - -### Subprojects - -Versioneer has limited support for source trees in which `setup.py` is not in -the root directory (e.g. `setup.py` and `.git/` are *not* siblings). The are -two common reasons why `setup.py` might not be in the root: - -* Source trees which contain multiple subprojects, such as - [Buildbot](https://github.com/buildbot/buildbot), which contains both - "master" and "slave" subprojects, each with their own `setup.py`, - `setup.cfg`, and `tox.ini`. Projects like these produce multiple PyPI - distributions (and upload multiple independently-installable tarballs). -* Source trees whose main purpose is to contain a C library, but which also - provide bindings to Python (and perhaps other languages) in subdirectories. - -Versioneer will look for `.git` in parent directories, and most operations -should get the right version string. However `pip` and `setuptools` have bugs -and implementation details which frequently cause `pip install .` from a -subproject directory to fail to find a correct version string (so it usually -defaults to `0+unknown`). - -`pip install --editable .` should work correctly. `setup.py install` might -work too. - -Pip-8.1.1 is known to have this problem, but hopefully it will get fixed in -some later version. - -[Bug #38](https://github.com/python-versioneer/python-versioneer/issues/38) is tracking -this issue. The discussion in -[PR #61](https://github.com/python-versioneer/python-versioneer/pull/61) describes the -issue from the Versioneer side in more detail. -[pip PR#3176](https://github.com/pypa/pip/pull/3176) and -[pip PR#3615](https://github.com/pypa/pip/pull/3615) contain work to improve -pip to let Versioneer work correctly. - -Versioneer-0.16 and earlier only looked for a `.git` directory next to the -`setup.cfg`, so subprojects were completely unsupported with those releases. - -### Editable installs with setuptools <= 18.5 - -`setup.py develop` and `pip install --editable .` allow you to install a -project into a virtualenv once, then continue editing the source code (and -test) without re-installing after every change. - -"Entry-point scripts" (`setup(entry_points={"console_scripts": ..})`) are a -convenient way to specify executable scripts that should be installed along -with the python package. - -These both work as expected when using modern setuptools. When using -setuptools-18.5 or earlier, however, certain operations will cause -`pkg_resources.DistributionNotFound` errors when running the entrypoint -script, which must be resolved by re-installing the package. This happens -when the install happens with one version, then the egg_info data is -regenerated while a different version is checked out. Many setup.py commands -cause egg_info to be rebuilt (including `sdist`, `wheel`, and installing into -a different virtualenv), so this can be surprising. - -[Bug #83](https://github.com/python-versioneer/python-versioneer/issues/83) describes -this one, but upgrading to a newer version of setuptools should probably -resolve it. - - -## Updating Versioneer - -To upgrade your project to a new release of Versioneer, do the following: - -* install the new Versioneer (`pip install -U versioneer` or equivalent) -* edit `setup.cfg` and `pyproject.toml`, if necessary, - to include any new configuration settings indicated by the release notes. - See [UPGRADING](./UPGRADING.md) for details. -* re-run `versioneer install --[no-]vendor` in your source tree, to replace - `SRC/_version.py` -* commit any changed files - -## Future Directions - -This tool is designed to make it easily extended to other version-control -systems: all VCS-specific components are in separate directories like -src/git/ . The top-level `versioneer.py` script is assembled from these -components by running make-versioneer.py . In the future, make-versioneer.py -will take a VCS name as an argument, and will construct a version of -`versioneer.py` that is specific to the given VCS. It might also take the -configuration arguments that are currently provided manually during -installation by editing setup.py . Alternatively, it might go the other -direction and include code from all supported VCS systems, reducing the -number of intermediate scripts. - -## Similar projects - -* [setuptools_scm](https://github.com/pypa/setuptools_scm/) - a non-vendored build-time - dependency -* [minver](https://github.com/jbweston/miniver) - a lightweight reimplementation of - versioneer -* [versioningit](https://github.com/jwodder/versioningit) - a PEP 518-based setuptools - plugin - -## License - -To make Versioneer easier to embed, all its code is dedicated to the public -domain. The `_version.py` that it creates is also in the public domain. -Specifically, both are released under the Creative Commons "Public Domain -Dedication" license (CC0-1.0), as described in -https://creativecommons.org/publicdomain/zero/1.0/ . - -[pypi-image]: https://img.shields.io/pypi/v/versioneer.svg -[pypi-url]: https://pypi.python.org/pypi/versioneer/ -[travis-image]: -https://img.shields.io/travis/com/python-versioneer/python-versioneer.svg -[travis-url]: https://travis-ci.com/github/python-versioneer/python-versioneer - -""" -# pylint:disable=invalid-name,import-outside-toplevel,missing-function-docstring -# pylint:disable=missing-class-docstring,too-many-branches,too-many-statements -# pylint:disable=raise-missing-from,too-many-lines,too-many-locals,import-error -# pylint:disable=too-few-public-methods,redefined-outer-name,consider-using-with -# pylint:disable=attribute-defined-outside-init,too-many-arguments - -import configparser -import errno -import json -import os -import re -import subprocess -import sys -from pathlib import Path -from typing import Callable, Dict -import functools -try: - import tomli - have_tomli = True -except ImportError: - have_tomli = False - - -class VersioneerConfig: - """Container for Versioneer configuration parameters.""" - - -def get_root(): - """Get the project root directory. - - We require that all commands are run from the project root, i.e. the - directory that contains setup.py, setup.cfg, and versioneer.py . - """ - root = os.path.realpath(os.path.abspath(os.getcwd())) - setup_py = os.path.join(root, "setup.py") - versioneer_py = os.path.join(root, "versioneer.py") - if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): - # allow 'python path/to/setup.py COMMAND' - root = os.path.dirname(os.path.realpath(os.path.abspath(sys.argv[0]))) - setup_py = os.path.join(root, "setup.py") - versioneer_py = os.path.join(root, "versioneer.py") - if not (os.path.exists(setup_py) or os.path.exists(versioneer_py)): - err = ("Versioneer was unable to run the project root directory. " - "Versioneer requires setup.py to be executed from " - "its immediate directory (like 'python setup.py COMMAND'), " - "or in a way that lets it use sys.argv[0] to find the root " - "(like 'python path/to/setup.py COMMAND').") - raise VersioneerBadRootError(err) - try: - # Certain runtime workflows (setup.py install/develop in a setuptools - # tree) execute all dependencies in a single python process, so - # "versioneer" may be imported multiple times, and python's shared - # module-import table will cache the first one. So we can't use - # os.path.dirname(__file__), as that will find whichever - # versioneer.py was first imported, even in later projects. - my_path = os.path.realpath(os.path.abspath(__file__)) - me_dir = os.path.normcase(os.path.splitext(my_path)[0]) - vsr_dir = os.path.normcase(os.path.splitext(versioneer_py)[0]) - if me_dir != vsr_dir and "VERSIONEER_PEP518" not in globals(): - print("Warning: build in %s is using versioneer.py from %s" - % (os.path.dirname(my_path), versioneer_py)) - except NameError: - pass - return root - - -def get_config_from_root(root): - """Read the project setup.cfg file to determine Versioneer config.""" - # This might raise OSError (if setup.cfg is missing), or - # configparser.NoSectionError (if it lacks a [versioneer] section), or - # configparser.NoOptionError (if it lacks "VCS="). See the docstring at - # the top of versioneer.py for instructions on writing your setup.cfg . - root = Path(root) - pyproject_toml = root / "pyproject.toml" - setup_cfg = root / "setup.cfg" - section = None - if pyproject_toml.exists() and have_tomli: - try: - with open(pyproject_toml, 'rb') as fobj: - pp = tomli.load(fobj) - section = pp['tool']['versioneer'] - except (tomli.TOMLDecodeError, KeyError): - pass - if not section: - parser = configparser.ConfigParser() - with open(setup_cfg) as cfg_file: - parser.read_file(cfg_file) - parser.get("versioneer", "VCS") # raise error if missing - - section = parser["versioneer"] - - cfg = VersioneerConfig() - cfg.VCS = section['VCS'] - cfg.style = section.get("style", "") - cfg.versionfile_source = section.get("versionfile_source") - cfg.versionfile_build = section.get("versionfile_build") - cfg.tag_prefix = section.get("tag_prefix") - if cfg.tag_prefix in ("''", '""', None): - cfg.tag_prefix = "" - cfg.parentdir_prefix = section.get("parentdir_prefix") - cfg.verbose = section.get("verbose") - return cfg - - -class NotThisMethod(Exception): - """Exception raised if a method is not valid for the current scenario.""" - - -# these dictionaries contain VCS-specific tools -LONG_VERSION_PY: Dict[str, str] = {} -HANDLERS: Dict[str, Dict[str, Callable]] = {} - - -def register_vcs_handler(vcs, method): # decorator - """Create decorator to mark a method as the handler of a VCS.""" - def decorate(f): - """Store f in HANDLERS[vcs][method].""" - HANDLERS.setdefault(vcs, {})[method] = f - return f - return decorate - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): - """Call the given command(s).""" - assert isinstance(commands, list) - process = None - - popen_kwargs = {} - if sys.platform == "win32": - # This hides the console window if pythonw.exe is used - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - popen_kwargs["startupinfo"] = startupinfo - - for command in commands: - try: - dispcmd = str([command] + args) - # remember shell=False, so use git.cmd on windows, not just git - process = subprocess.Popen([command] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None), **popen_kwargs) - break - except OSError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %s" % dispcmd) - print(e) - return None, None - else: - if verbose: - print("unable to find command, tried %s" % (commands,)) - return None, None - stdout = process.communicate()[0].strip().decode() - if process.returncode != 0: - if verbose: - print("unable to run %s (error)" % dispcmd) - print("stdout was %s" % stdout) - return None, process.returncode - return stdout, process.returncode - - -LONG_VERSION_PY['git'] = r''' -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by githubs download-from-tag -# feature). Distribution tarballs (built by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. -# Generated by versioneer-0.26 -# https://github.com/python-versioneer/python-versioneer - -"""Git implementation of _version.py.""" - -import errno -import os -import re -import subprocess -import sys -from typing import Callable, Dict -import functools - - -def get_keywords(): - """Get the keywords needed to look up the version information.""" - # these strings will be replaced by git during git-archive. - # setup.py/versioneer.py will grep for the variable names, so they must - # each be defined on a line of their own. _version.py will just call - # get_keywords(). - git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s" - git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s" - git_date = "%(DOLLAR)sFormat:%%ci%(DOLLAR)s" - keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} - return keywords - - -class VersioneerConfig: - """Container for Versioneer configuration parameters.""" - - -def get_config(): - """Create, populate and return the VersioneerConfig() object.""" - # these strings are filled in when 'setup.py versioneer' creates - # _version.py - cfg = VersioneerConfig() - cfg.VCS = "git" - cfg.style = "%(STYLE)s" - cfg.tag_prefix = "%(TAG_PREFIX)s" - cfg.parentdir_prefix = "%(PARENTDIR_PREFIX)s" - cfg.versionfile_source = "%(VERSIONFILE_SOURCE)s" - cfg.verbose = False - return cfg - - -class NotThisMethod(Exception): - """Exception raised if a method is not valid for the current scenario.""" - - -LONG_VERSION_PY: Dict[str, str] = {} -HANDLERS: Dict[str, Dict[str, Callable]] = {} - - -def register_vcs_handler(vcs, method): # decorator - """Create decorator to mark a method as the handler of a VCS.""" - def decorate(f): - """Store f in HANDLERS[vcs][method].""" - if vcs not in HANDLERS: - HANDLERS[vcs] = {} - HANDLERS[vcs][method] = f - return f - return decorate - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): - """Call the given command(s).""" - assert isinstance(commands, list) - process = None - - popen_kwargs = {} - if sys.platform == "win32": - # This hides the console window if pythonw.exe is used - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - popen_kwargs["startupinfo"] = startupinfo - - for command in commands: - try: - dispcmd = str([command] + args) - # remember shell=False, so use git.cmd on windows, not just git - process = subprocess.Popen([command] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None), **popen_kwargs) - break - except OSError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %%s" %% dispcmd) - print(e) - return None, None - else: - if verbose: - print("unable to find command, tried %%s" %% (commands,)) - return None, None - stdout = process.communicate()[0].strip().decode() - if process.returncode != 0: - if verbose: - print("unable to run %%s (error)" %% dispcmd) - print("stdout was %%s" %% stdout) - return None, process.returncode - return stdout, process.returncode - - -def versions_from_parentdir(parentdir_prefix, root, verbose): - """Try to determine the version from the parent directory name. - - Source tarballs conventionally unpack into a directory that includes both - the project name and a version string. We will also support searching up - two directory levels for an appropriately named parent directory - """ - rootdirs = [] - - for _ in range(3): - dirname = os.path.basename(root) - if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} - rootdirs.append(root) - root = os.path.dirname(root) # up a level - - if verbose: - print("Tried directories %%s but none started with prefix %%s" %% - (str(rootdirs), parentdir_prefix)) - raise NotThisMethod("rootdir doesn't start with parentdir_prefix") - - -@register_vcs_handler("git", "get_keywords") -def git_get_keywords(versionfile_abs): - """Extract version information from the given file.""" - # the code embedded in _version.py can just fetch the value of these - # keywords. When used from setup.py, we don't want to import _version.py, - # so we do it with a regexp instead. This function is not used from - # _version.py. - keywords = {} - try: - with open(versionfile_abs, "r") as fobj: - for line in fobj: - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - except OSError: - pass - return keywords - - -@register_vcs_handler("git", "keywords") -def git_versions_from_keywords(keywords, tag_prefix, verbose): - """Get version information from git keywords.""" - if "refnames" not in keywords: - raise NotThisMethod("Short version file found") - date = keywords.get("date") - if date is not None: - # Use only the last line. Previous lines may contain GPG signature - # information. - date = date.splitlines()[-1] - - # git-2.2.0 added "%%cI", which expands to an ISO-8601 -compliant - # datestamp. However we prefer "%%ci" (which expands to an "ISO-8601 - # -like" string, which we must then edit to make compliant), because - # it's been around since git-1.5.3, and it's too difficult to - # discover which version we're using, or to work around using an - # older one. - date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - refnames = keywords["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("keywords are unexpanded, not using") - raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = {r.strip() for r in refnames.strip("()").split(",")} - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = {r[len(TAG):] for r in refs if r.startswith(TAG)} - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %%d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = {r for r in refs if re.search(r'\d', r)} - if verbose: - print("discarding '%%s', no digits" %% ",".join(refs - tags)) - if verbose: - print("likely tags: %%s" %% ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - # Filter out refs that exactly match prefix or that don't start - # with a number once the prefix is stripped (mostly a concern - # when prefix is '') - if not re.match(r'\d', r): - continue - if verbose: - print("picking %%s" %% r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} - # no suitable tags, so version is "0+unknown", but full hex is still there - if verbose: - print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} - - -@register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command): - """Get version from 'git describe' in the root of the source tree. - - This only gets called if the git-archive 'subst' keywords were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - - # GIT_DIR can interfere with correct operation of Versioneer. - # It may be intended to be passed to the Versioneer-versioned project, - # but that should not change where we get our version from. - env = os.environ.copy() - env.pop("GIT_DIR", None) - runner = functools.partial(runner, env=env) - - _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=not verbose) - if rc != 0: - if verbose: - print("Directory %%s not under git control" %% root) - raise NotThisMethod("'git rev-parse --git-dir' returned error") - - # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] - # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = runner(GITS, [ - "describe", "--tags", "--dirty", "--always", "--long", - "--match", f"{tag_prefix}[[:digit:]]*" - ], cwd=root) - # --long was added in git-1.5.5 - if describe_out is None: - raise NotThisMethod("'git describe' failed") - describe_out = describe_out.strip() - full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root) - if full_out is None: - raise NotThisMethod("'git rev-parse' failed") - full_out = full_out.strip() - - pieces = {} - pieces["long"] = full_out - pieces["short"] = full_out[:7] # maybe improved later - pieces["error"] = None - - branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"], - cwd=root) - # --abbrev-ref was added in git-1.6.3 - if rc != 0 or branch_name is None: - raise NotThisMethod("'git rev-parse --abbrev-ref' returned error") - branch_name = branch_name.strip() - - if branch_name == "HEAD": - # If we aren't exactly on a branch, pick a branch which represents - # the current commit. If all else fails, we are on a branchless - # commit. - branches, rc = runner(GITS, ["branch", "--contains"], cwd=root) - # --contains was added in git-1.5.4 - if rc != 0 or branches is None: - raise NotThisMethod("'git branch --contains' returned error") - branches = branches.split("\n") - - # Remove the first line if we're running detached - if "(" in branches[0]: - branches.pop(0) - - # Strip off the leading "* " from the list of branches. - branches = [branch[2:] for branch in branches] - if "master" in branches: - branch_name = "master" - elif not branches: - branch_name = None - else: - # Pick the first branch that is returned. Good or bad. - branch_name = branches[0] - - pieces["branch"] = branch_name - - # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] - # TAG might have hyphens. - git_describe = describe_out - - # look for -dirty suffix - dirty = git_describe.endswith("-dirty") - pieces["dirty"] = dirty - if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] - - # now we have TAG-NUM-gHEX or HEX - - if "-" in git_describe: - # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) - if not mo: - # unparsable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%%s'" - %% describe_out) - return pieces - - # tag - full_tag = mo.group(1) - if not full_tag.startswith(tag_prefix): - if verbose: - fmt = "tag '%%s' doesn't start with prefix '%%s'" - print(fmt %% (full_tag, tag_prefix)) - pieces["error"] = ("tag '%%s' doesn't start with prefix '%%s'" - %% (full_tag, tag_prefix)) - return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] - - # distance: number of commits since tag - pieces["distance"] = int(mo.group(2)) - - # commit: short hex revision ID - pieces["short"] = mo.group(3) - - else: - # HEX: no tags - pieces["closest-tag"] = None - out, rc = runner(GITS, ["rev-list", "HEAD", "--left-right"], cwd=root) - pieces["distance"] = len(out.split()) # total number of commits - - # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = runner(GITS, ["show", "-s", "--format=%%ci", "HEAD"], cwd=root)[0].strip() - # Use only the last line. Previous lines may contain GPG signature - # information. - date = date.splitlines()[-1] - pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - - return pieces - - -def plus_or_dot(pieces): - """Return a + if we don't already have one, else return a .""" - if "+" in pieces.get("closest-tag", ""): - return "." - return "+" - - -def render_pep440(pieces): - """Build up version string, with post-release "local version identifier". - - Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you - get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty - - Exceptions: - 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += plus_or_dot(pieces) - rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0+untagged.%%d.g%%s" %% (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_branch(pieces): - """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] . - - The ".dev0" means not master branch. Note that .dev0 sorts backwards - (a feature branch will appear "older" than the master branch). - - Exceptions: - 1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "%%d.g%%s" %% (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0" - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += "+untagged.%%d.g%%s" %% (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def pep440_split_post(ver): - """Split pep440 version string at the post-release segment. - - Returns the release segments before the post-release and the - post-release version number (or -1 if no post-release segment is present). - """ - vc = str.split(ver, ".post") - return vc[0], int(vc[1] or 0) if len(vc) == 2 else None - - -def render_pep440_pre(pieces): - """TAG[.postN.devDISTANCE] -- No -dirty. - - Exceptions: - 1: no tags. 0.post0.devDISTANCE - """ - if pieces["closest-tag"]: - if pieces["distance"]: - # update the post release segment - tag_version, post_version = pep440_split_post(pieces["closest-tag"]) - rendered = tag_version - if post_version is not None: - rendered += ".post%%d.dev%%d" %% (post_version + 1, pieces["distance"]) - else: - rendered += ".post0.dev%%d" %% (pieces["distance"]) - else: - # no commits, use the tag as the version - rendered = pieces["closest-tag"] - else: - # exception #1 - rendered = "0.post0.dev%%d" %% pieces["distance"] - return rendered - - -def render_pep440_post(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX] . - - The ".dev0" means dirty. Note that .dev0 sorts backwards - (a dirty tree will appear "older" than the corresponding clean one), - but you shouldn't be releasing software with -dirty anyways. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%%s" %% pieces["short"] - else: - # exception #1 - rendered = "0.post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += "+g%%s" %% pieces["short"] - return rendered - - -def render_pep440_post_branch(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] . - - The ".dev0" means not master branch. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%%d" %% pieces["distance"] - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%%s" %% pieces["short"] - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0.post%%d" %% pieces["distance"] - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += "+g%%s" %% pieces["short"] - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_old(pieces): - """TAG[.postDISTANCE[.dev0]] . - - The ".dev0" means dirty. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - else: - # exception #1 - rendered = "0.post%%d" %% pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - return rendered - - -def render_git_describe(pieces): - """TAG[-DISTANCE-gHEX][-dirty]. - - Like 'git describe --tags --dirty --always'. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render_git_describe_long(pieces): - """TAG-DISTANCE-gHEX[-dirty]. - - Like 'git describe --tags --dirty --always -long'. - The distance/hash is unconditional. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - rendered += "-%%d-g%%s" %% (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render(pieces, style): - """Render the given version pieces into the requested style.""" - if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} - - if not style or style == "default": - style = "pep440" # the default - - if style == "pep440": - rendered = render_pep440(pieces) - elif style == "pep440-branch": - rendered = render_pep440_branch(pieces) - elif style == "pep440-pre": - rendered = render_pep440_pre(pieces) - elif style == "pep440-post": - rendered = render_pep440_post(pieces) - elif style == "pep440-post-branch": - rendered = render_pep440_post_branch(pieces) - elif style == "pep440-old": - rendered = render_pep440_old(pieces) - elif style == "git-describe": - rendered = render_git_describe(pieces) - elif style == "git-describe-long": - rendered = render_git_describe_long(pieces) - else: - raise ValueError("unknown style '%%s'" %% style) - - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} - - -def get_versions(): - """Get version information or return default if unable to do so.""" - # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have - # __file__, we can work backwards from there to the root. Some - # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which - # case we can only use expanded keywords. - - cfg = get_config() - verbose = cfg.verbose - - try: - return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, - verbose) - except NotThisMethod: - pass - - try: - root = os.path.realpath(__file__) - # versionfile_source is the relative path from the top of the source - # tree (where the .git directory might live) to this file. Invert - # this to find the root from __file__. - for _ in cfg.versionfile_source.split('/'): - root = os.path.dirname(root) - except NameError: - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to find root of source tree", - "date": None} - - try: - pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) - return render(pieces, cfg.style) - except NotThisMethod: - pass - - try: - if cfg.parentdir_prefix: - return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) - except NotThisMethod: - pass - - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to compute version", "date": None} -''' - - -@register_vcs_handler("git", "get_keywords") -def git_get_keywords(versionfile_abs): - """Extract version information from the given file.""" - # the code embedded in _version.py can just fetch the value of these - # keywords. When used from setup.py, we don't want to import _version.py, - # so we do it with a regexp instead. This function is not used from - # _version.py. - keywords = {} - try: - with open(versionfile_abs, "r") as fobj: - for line in fobj: - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - except OSError: - pass - return keywords - - -@register_vcs_handler("git", "keywords") -def git_versions_from_keywords(keywords, tag_prefix, verbose): - """Get version information from git keywords.""" - if "refnames" not in keywords: - raise NotThisMethod("Short version file found") - date = keywords.get("date") - if date is not None: - # Use only the last line. Previous lines may contain GPG signature - # information. - date = date.splitlines()[-1] - - # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant - # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 - # -like" string, which we must then edit to make compliant), because - # it's been around since git-1.5.3, and it's too difficult to - # discover which version we're using, or to work around using an - # older one. - date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - refnames = keywords["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("keywords are unexpanded, not using") - raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = {r.strip() for r in refnames.strip("()").split(",")} - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = {r[len(TAG):] for r in refs if r.startswith(TAG)} - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = {r for r in refs if re.search(r'\d', r)} - if verbose: - print("discarding '%s', no digits" % ",".join(refs - tags)) - if verbose: - print("likely tags: %s" % ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - # Filter out refs that exactly match prefix or that don't start - # with a number once the prefix is stripped (mostly a concern - # when prefix is '') - if not re.match(r'\d', r): - continue - if verbose: - print("picking %s" % r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} - # no suitable tags, so version is "0+unknown", but full hex is still there - if verbose: - print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} - - -@register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command): - """Get version from 'git describe' in the root of the source tree. - - This only gets called if the git-archive 'subst' keywords were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - - # GIT_DIR can interfere with correct operation of Versioneer. - # It may be intended to be passed to the Versioneer-versioned project, - # but that should not change where we get our version from. - env = os.environ.copy() - env.pop("GIT_DIR", None) - runner = functools.partial(runner, env=env) - - _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=not verbose) - if rc != 0: - if verbose: - print("Directory %s not under git control" % root) - raise NotThisMethod("'git rev-parse --git-dir' returned error") - - # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] - # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = runner(GITS, [ - "describe", "--tags", "--dirty", "--always", "--long", - "--match", f"{tag_prefix}[[:digit:]]*" - ], cwd=root) - # --long was added in git-1.5.5 - if describe_out is None: - raise NotThisMethod("'git describe' failed") - describe_out = describe_out.strip() - full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root) - if full_out is None: - raise NotThisMethod("'git rev-parse' failed") - full_out = full_out.strip() - - pieces = {} - pieces["long"] = full_out - pieces["short"] = full_out[:7] # maybe improved later - pieces["error"] = None - - branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"], - cwd=root) - # --abbrev-ref was added in git-1.6.3 - if rc != 0 or branch_name is None: - raise NotThisMethod("'git rev-parse --abbrev-ref' returned error") - branch_name = branch_name.strip() - - if branch_name == "HEAD": - # If we aren't exactly on a branch, pick a branch which represents - # the current commit. If all else fails, we are on a branchless - # commit. - branches, rc = runner(GITS, ["branch", "--contains"], cwd=root) - # --contains was added in git-1.5.4 - if rc != 0 or branches is None: - raise NotThisMethod("'git branch --contains' returned error") - branches = branches.split("\n") - - # Remove the first line if we're running detached - if "(" in branches[0]: - branches.pop(0) - - # Strip off the leading "* " from the list of branches. - branches = [branch[2:] for branch in branches] - if "master" in branches: - branch_name = "master" - elif not branches: - branch_name = None - else: - # Pick the first branch that is returned. Good or bad. - branch_name = branches[0] - - pieces["branch"] = branch_name - - # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] - # TAG might have hyphens. - git_describe = describe_out - - # look for -dirty suffix - dirty = git_describe.endswith("-dirty") - pieces["dirty"] = dirty - if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] - - # now we have TAG-NUM-gHEX or HEX - - if "-" in git_describe: - # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) - if not mo: - # unparsable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%s'" - % describe_out) - return pieces - - # tag - full_tag = mo.group(1) - if not full_tag.startswith(tag_prefix): - if verbose: - fmt = "tag '%s' doesn't start with prefix '%s'" - print(fmt % (full_tag, tag_prefix)) - pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" - % (full_tag, tag_prefix)) - return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] - - # distance: number of commits since tag - pieces["distance"] = int(mo.group(2)) - - # commit: short hex revision ID - pieces["short"] = mo.group(3) - - else: - # HEX: no tags - pieces["closest-tag"] = None - out, rc = runner(GITS, ["rev-list", "HEAD", "--left-right"], cwd=root) - pieces["distance"] = len(out.split()) # total number of commits - - # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = runner(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() - # Use only the last line. Previous lines may contain GPG signature - # information. - date = date.splitlines()[-1] - pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - - return pieces - - -def do_vcs_install(versionfile_source, ipy): - """Git-specific installation logic for Versioneer. - - For Git, this means creating/changing .gitattributes to mark _version.py - for export-subst keyword substitution. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - files = [versionfile_source] - if ipy: - files.append(ipy) - if "VERSIONEER_PEP518" not in globals(): - try: - my_path = __file__ - if my_path.endswith(".pyc") or my_path.endswith(".pyo"): - my_path = os.path.splitext(my_path)[0] + ".py" - versioneer_file = os.path.relpath(my_path) - except NameError: - versioneer_file = "versioneer.py" - files.append(versioneer_file) - present = False - try: - with open(".gitattributes", "r") as fobj: - for line in fobj: - if line.strip().startswith(versionfile_source): - if "export-subst" in line.strip().split()[1:]: - present = True - break - except OSError: - pass - if not present: - with open(".gitattributes", "a+") as fobj: - fobj.write(f"{versionfile_source} export-subst\n") - files.append(".gitattributes") - run_command(GITS, ["add", "--"] + files) - - -def versions_from_parentdir(parentdir_prefix, root, verbose): - """Try to determine the version from the parent directory name. - - Source tarballs conventionally unpack into a directory that includes both - the project name and a version string. We will also support searching up - two directory levels for an appropriately named parent directory - """ - rootdirs = [] - - for _ in range(3): - dirname = os.path.basename(root) - if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} - rootdirs.append(root) - root = os.path.dirname(root) # up a level - - if verbose: - print("Tried directories %s but none started with prefix %s" % - (str(rootdirs), parentdir_prefix)) - raise NotThisMethod("rootdir doesn't start with parentdir_prefix") - - -SHORT_VERSION_PY = """ -# This file was generated by 'versioneer.py' (0.26) from -# revision-control system data, or from the parent directory name of an -# unpacked source archive. Distribution tarballs contain a pre-generated copy -# of this file. - -import json - -version_json = ''' -%s -''' # END VERSION_JSON - - -def get_versions(): - return json.loads(version_json) -""" - - -def versions_from_file(filename): - """Try to determine the version from _version.py if present.""" - try: - with open(filename) as f: - contents = f.read() - except OSError: - raise NotThisMethod("unable to read _version.py") - mo = re.search(r"version_json = '''\n(.*)''' # END VERSION_JSON", - contents, re.M | re.S) - if not mo: - mo = re.search(r"version_json = '''\r\n(.*)''' # END VERSION_JSON", - contents, re.M | re.S) - if not mo: - raise NotThisMethod("no version_json in _version.py") - return json.loads(mo.group(1)) - - -def write_to_version_file(filename, versions): - """Write the given version number to the given _version.py file.""" - os.unlink(filename) - contents = json.dumps(versions, sort_keys=True, - indent=1, separators=(",", ": ")) - with open(filename, "w") as f: - f.write(SHORT_VERSION_PY % contents) - - print("set %s to '%s'" % (filename, versions["version"])) - - -def plus_or_dot(pieces): - """Return a + if we don't already have one, else return a .""" - if "+" in pieces.get("closest-tag", ""): - return "." - return "+" - - -def render_pep440(pieces): - """Build up version string, with post-release "local version identifier". - - Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you - get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty - - Exceptions: - 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += plus_or_dot(pieces) - rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_branch(pieces): - """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] . - - The ".dev0" means not master branch. Note that .dev0 sorts backwards - (a feature branch will appear "older" than the master branch). - - Exceptions: - 1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0" - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += "+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def pep440_split_post(ver): - """Split pep440 version string at the post-release segment. - - Returns the release segments before the post-release and the - post-release version number (or -1 if no post-release segment is present). - """ - vc = str.split(ver, ".post") - return vc[0], int(vc[1] or 0) if len(vc) == 2 else None - - -def render_pep440_pre(pieces): - """TAG[.postN.devDISTANCE] -- No -dirty. - - Exceptions: - 1: no tags. 0.post0.devDISTANCE - """ - if pieces["closest-tag"]: - if pieces["distance"]: - # update the post release segment - tag_version, post_version = pep440_split_post(pieces["closest-tag"]) - rendered = tag_version - if post_version is not None: - rendered += ".post%d.dev%d" % (post_version + 1, pieces["distance"]) - else: - rendered += ".post0.dev%d" % (pieces["distance"]) - else: - # no commits, use the tag as the version - rendered = pieces["closest-tag"] - else: - # exception #1 - rendered = "0.post0.dev%d" % pieces["distance"] - return rendered - - -def render_pep440_post(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX] . - - The ".dev0" means dirty. Note that .dev0 sorts backwards - (a dirty tree will appear "older" than the corresponding clean one), - but you shouldn't be releasing software with -dirty anyways. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%s" % pieces["short"] - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += "+g%s" % pieces["short"] - return rendered - - -def render_pep440_post_branch(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] . - - The ".dev0" means not master branch. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%s" % pieces["short"] - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += "+g%s" % pieces["short"] - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_old(pieces): - """TAG[.postDISTANCE[.dev0]] . - - The ".dev0" means dirty. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - return rendered - - -def render_git_describe(pieces): - """TAG[-DISTANCE-gHEX][-dirty]. - - Like 'git describe --tags --dirty --always'. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render_git_describe_long(pieces): - """TAG-DISTANCE-gHEX[-dirty]. - - Like 'git describe --tags --dirty --always -long'. - The distance/hash is unconditional. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render(pieces, style): - """Render the given version pieces into the requested style.""" - if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} - - if not style or style == "default": - style = "pep440" # the default - - if style == "pep440": - rendered = render_pep440(pieces) - elif style == "pep440-branch": - rendered = render_pep440_branch(pieces) - elif style == "pep440-pre": - rendered = render_pep440_pre(pieces) - elif style == "pep440-post": - rendered = render_pep440_post(pieces) - elif style == "pep440-post-branch": - rendered = render_pep440_post_branch(pieces) - elif style == "pep440-old": - rendered = render_pep440_old(pieces) - elif style == "git-describe": - rendered = render_git_describe(pieces) - elif style == "git-describe-long": - rendered = render_git_describe_long(pieces) - else: - raise ValueError("unknown style '%s'" % style) - - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} - - -class VersioneerBadRootError(Exception): - """The project root directory is unknown or missing key files.""" - - -def get_versions(verbose=False): - """Get the project version from whatever source is available. - - Returns dict with two keys: 'version' and 'full'. - """ - if "versioneer" in sys.modules: - # see the discussion in cmdclass.py:get_cmdclass() - del sys.modules["versioneer"] - - root = get_root() - cfg = get_config_from_root(root) - - assert cfg.VCS is not None, "please set [versioneer]VCS= in setup.cfg" - handlers = HANDLERS.get(cfg.VCS) - assert handlers, "unrecognized VCS '%s'" % cfg.VCS - verbose = verbose or cfg.verbose - assert cfg.versionfile_source is not None, \ - "please set versioneer.versionfile_source" - assert cfg.tag_prefix is not None, "please set versioneer.tag_prefix" - - versionfile_abs = os.path.join(root, cfg.versionfile_source) - - # extract version from first of: _version.py, VCS command (e.g. 'git - # describe'), parentdir. This is meant to work for developers using a - # source checkout, for users of a tarball created by 'setup.py sdist', - # and for users of a tarball/zipball created by 'git archive' or github's - # download-from-tag feature or the equivalent in other VCSes. - - get_keywords_f = handlers.get("get_keywords") - from_keywords_f = handlers.get("keywords") - if get_keywords_f and from_keywords_f: - try: - keywords = get_keywords_f(versionfile_abs) - ver = from_keywords_f(keywords, cfg.tag_prefix, verbose) - if verbose: - print("got version from expanded keyword %s" % ver) - return ver - except NotThisMethod: - pass - - try: - ver = versions_from_file(versionfile_abs) - if verbose: - print("got version from file %s %s" % (versionfile_abs, ver)) - return ver - except NotThisMethod: - pass - - from_vcs_f = handlers.get("pieces_from_vcs") - if from_vcs_f: - try: - pieces = from_vcs_f(cfg.tag_prefix, root, verbose) - ver = render(pieces, cfg.style) - if verbose: - print("got version from VCS %s" % ver) - return ver - except NotThisMethod: - pass - - try: - if cfg.parentdir_prefix: - ver = versions_from_parentdir(cfg.parentdir_prefix, root, verbose) - if verbose: - print("got version from parentdir %s" % ver) - return ver - except NotThisMethod: - pass - - if verbose: - print("unable to compute version") - - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, "error": "unable to compute version", - "date": None} - - -def get_version(): - """Get the short version string for this project.""" - return get_versions()["version"] - - -def get_cmdclass(cmdclass=None): - """Get the custom setuptools subclasses used by Versioneer. - - If the package uses a different cmdclass (e.g. one from numpy), it - should be provide as an argument. - """ - if "versioneer" in sys.modules: - del sys.modules["versioneer"] - # this fixes the "python setup.py develop" case (also 'install' and - # 'easy_install .'), in which subdependencies of the main project are - # built (using setup.py bdist_egg) in the same python process. Assume - # a main project A and a dependency B, which use different versions - # of Versioneer. A's setup.py imports A's Versioneer, leaving it in - # sys.modules by the time B's setup.py is executed, causing B to run - # with the wrong versioneer. Setuptools wraps the sub-dep builds in a - # sandbox that restores sys.modules to it's pre-build state, so the - # parent is protected against the child's "import versioneer". By - # removing ourselves from sys.modules here, before the child build - # happens, we protect the child from the parent's versioneer too. - # Also see https://github.com/python-versioneer/python-versioneer/issues/52 - - cmds = {} if cmdclass is None else cmdclass.copy() - - # we add "version" to setuptools - from setuptools import Command - - class cmd_version(Command): - description = "report generated version string" - user_options = [] - boolean_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - vers = get_versions(verbose=True) - print("Version: %s" % vers["version"]) - print(" full-revisionid: %s" % vers.get("full-revisionid")) - print(" dirty: %s" % vers.get("dirty")) - print(" date: %s" % vers.get("date")) - if vers["error"]: - print(" error: %s" % vers["error"]) - cmds["version"] = cmd_version - - # we override "build_py" in setuptools - # - # most invocation pathways end up running build_py: - # distutils/build -> build_py - # distutils/install -> distutils/build ->.. - # setuptools/bdist_wheel -> distutils/install ->.. - # setuptools/bdist_egg -> distutils/install_lib -> build_py - # setuptools/install -> bdist_egg ->.. - # setuptools/develop -> ? - # pip install: - # copies source tree to a tempdir before running egg_info/etc - # if .git isn't copied too, 'git describe' will fail - # then does setup.py bdist_wheel, or sometimes setup.py install - # setup.py egg_info -> ? - - # pip install -e . and setuptool/editable_wheel will invoke build_py - # but the build_py command is not expected to copy any files. - - # we override different "build_py" commands for both environments - if 'build_py' in cmds: - _build_py = cmds['build_py'] - else: - from setuptools.command.build_py import build_py as _build_py - - class cmd_build_py(_build_py): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - _build_py.run(self) - if getattr(self, "editable_mode", False): - # During editable installs `.py` and data files are - # not copied to build_lib - return - # now locate _version.py in the new build/ directory and replace - # it with an updated value - if cfg.versionfile_build: - target_versionfile = os.path.join(self.build_lib, - cfg.versionfile_build) - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - cmds["build_py"] = cmd_build_py - - if 'build_ext' in cmds: - _build_ext = cmds['build_ext'] - else: - from setuptools.command.build_ext import build_ext as _build_ext - - class cmd_build_ext(_build_ext): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - _build_ext.run(self) - if self.inplace: - # build_ext --inplace will only build extensions in - # build/lib<..> dir with no _version.py to write to. - # As in place builds will already have a _version.py - # in the module dir, we do not need to write one. - return - # now locate _version.py in the new build/ directory and replace - # it with an updated value - target_versionfile = os.path.join(self.build_lib, - cfg.versionfile_build) - if not os.path.exists(target_versionfile): - print(f"Warning: {target_versionfile} does not exist, skipping " - "version update. This can happen if you are running build_ext " - "without first running build_py.") - return - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - cmds["build_ext"] = cmd_build_ext - - if "cx_Freeze" in sys.modules: # cx_freeze enabled? - from cx_Freeze.dist import build_exe as _build_exe - # nczeczulin reports that py2exe won't like the pep440-style string - # as FILEVERSION, but it can be used for PRODUCTVERSION, e.g. - # setup(console=[{ - # "version": versioneer.get_version().split("+", 1)[0], # FILEVERSION - # "product_version": versioneer.get_version(), - # ... - - class cmd_build_exe(_build_exe): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - target_versionfile = cfg.versionfile_source - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - - _build_exe.run(self) - os.unlink(target_versionfile) - with open(cfg.versionfile_source, "w") as f: - LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % - {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - cmds["build_exe"] = cmd_build_exe - del cmds["build_py"] - - if 'py2exe' in sys.modules: # py2exe enabled? - try: - from py2exe.setuptools_buildexe import py2exe as _py2exe - except ImportError: - from py2exe.distutils_buildexe import py2exe as _py2exe - - class cmd_py2exe(_py2exe): - def run(self): - root = get_root() - cfg = get_config_from_root(root) - versions = get_versions() - target_versionfile = cfg.versionfile_source - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, versions) - - _py2exe.run(self) - os.unlink(target_versionfile) - with open(cfg.versionfile_source, "w") as f: - LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % - {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - cmds["py2exe"] = cmd_py2exe - - # sdist farms its file list building out to egg_info - if 'egg_info' in cmds: - _sdist = cmds['egg_info'] - else: - from setuptools.command.egg_info import egg_info as _egg_info - - class cmd_egg_info(_egg_info): - def find_sources(self): - # egg_info.find_sources builds the manifest list and writes it - # in one shot - super().find_sources() - - # Modify the filelist and normalize it - root = get_root() - cfg = get_config_from_root(root) - self.filelist.append('versioneer.py') - if cfg.versionfile_source: - # There are rare cases where versionfile_source might not be - # included by default, so we must be explicit - self.filelist.append(cfg.versionfile_source) - self.filelist.sort() - self.filelist.remove_duplicates() - - # The write method is hidden in the manifest_maker instance that - # generated the filelist and was thrown away - # We will instead replicate their final normalization (to unicode, - # and POSIX-style paths) - from setuptools import unicode_utils - normalized = [unicode_utils.filesys_decode(f).replace(os.sep, '/') - for f in self.filelist.files] - - manifest_filename = os.path.join(self.egg_info, 'SOURCES.txt') - with open(manifest_filename, 'w') as fobj: - fobj.write('\n'.join(normalized)) - - cmds['egg_info'] = cmd_egg_info - - # we override different "sdist" commands for both environments - if 'sdist' in cmds: - _sdist = cmds['sdist'] - else: - from setuptools.command.sdist import sdist as _sdist - - class cmd_sdist(_sdist): - def run(self): - versions = get_versions() - self._versioneer_generated_versions = versions - # unless we update this, the command will keep using the old - # version - self.distribution.metadata.version = versions["version"] - return _sdist.run(self) - - def make_release_tree(self, base_dir, files): - root = get_root() - cfg = get_config_from_root(root) - _sdist.make_release_tree(self, base_dir, files) - # now locate _version.py in the new base_dir directory - # (remembering that it may be a hardlink) and replace it with an - # updated value - target_versionfile = os.path.join(base_dir, cfg.versionfile_source) - print("UPDATING %s" % target_versionfile) - write_to_version_file(target_versionfile, - self._versioneer_generated_versions) - cmds["sdist"] = cmd_sdist - - return cmds - - -CONFIG_ERROR = """ -setup.cfg is missing the necessary Versioneer configuration. You need -a section like: - - [versioneer] - VCS = git - style = pep440 - versionfile_source = src/myproject/_version.py - versionfile_build = myproject/_version.py - tag_prefix = - parentdir_prefix = myproject- - -You will also need to edit your setup.py to use the results: - - import versioneer - setup(version=versioneer.get_version(), - cmdclass=versioneer.get_cmdclass(), ...) - -Please read the docstring in ./versioneer.py for configuration instructions, -edit setup.cfg, and re-run the installer or 'python versioneer.py setup'. -""" - -SAMPLE_CONFIG = """ -# See the docstring in versioneer.py for instructions. Note that you must -# re-run 'versioneer.py setup' after changing this section, and commit the -# resulting files. - -[versioneer] -#VCS = git -#style = pep440 -#versionfile_source = -#versionfile_build = -#tag_prefix = -#parentdir_prefix = - -""" - -OLD_SNIPPET = """ -from ._version import get_versions -__version__ = get_versions()['version'] -del get_versions -""" - -INIT_PY_SNIPPET = """ -from . import {0} -__version__ = {0}.get_versions()['version'] -""" - - -def do_setup(): - """Do main VCS-independent setup function for installing Versioneer.""" - root = get_root() - try: - cfg = get_config_from_root(root) - except (OSError, configparser.NoSectionError, - configparser.NoOptionError) as e: - if isinstance(e, (OSError, configparser.NoSectionError)): - print("Adding sample versioneer config to setup.cfg", - file=sys.stderr) - with open(os.path.join(root, "setup.cfg"), "a") as f: - f.write(SAMPLE_CONFIG) - print(CONFIG_ERROR, file=sys.stderr) - return 1 - - print(" creating %s" % cfg.versionfile_source) - with open(cfg.versionfile_source, "w") as f: - LONG = LONG_VERSION_PY[cfg.VCS] - f.write(LONG % {"DOLLAR": "$", - "STYLE": cfg.style, - "TAG_PREFIX": cfg.tag_prefix, - "PARENTDIR_PREFIX": cfg.parentdir_prefix, - "VERSIONFILE_SOURCE": cfg.versionfile_source, - }) - - ipy = os.path.join(os.path.dirname(cfg.versionfile_source), - "__init__.py") - if os.path.exists(ipy): - try: - with open(ipy, "r") as f: - old = f.read() - except OSError: - old = "" - module = os.path.splitext(os.path.basename(cfg.versionfile_source))[0] - snippet = INIT_PY_SNIPPET.format(module) - if OLD_SNIPPET in old: - print(" replacing boilerplate in %s" % ipy) - with open(ipy, "w") as f: - f.write(old.replace(OLD_SNIPPET, snippet)) - elif snippet not in old: - print(" appending to %s" % ipy) - with open(ipy, "a") as f: - f.write(snippet) - else: - print(" %s unmodified" % ipy) - else: - print(" %s doesn't exist, ok" % ipy) - ipy = None - - # Make VCS-specific changes. For git, this means creating/changing - # .gitattributes to mark _version.py for export-subst keyword - # substitution. - do_vcs_install(cfg.versionfile_source, ipy) - return 0 - - -def scan_setup_py(): - """Validate the contents of setup.py against Versioneer's expectations.""" - found = set() - setters = False - errors = 0 - with open("setup.py", "r") as f: - for line in f.readlines(): - if "import versioneer" in line: - found.add("import") - if "versioneer.get_cmdclass()" in line: - found.add("cmdclass") - if "versioneer.get_version()" in line: - found.add("get_version") - if "versioneer.VCS" in line: - setters = True - if "versioneer.versionfile_source" in line: - setters = True - if len(found) != 3: - print("") - print("Your setup.py appears to be missing some important items") - print("(but I might be wrong). Please make sure it has something") - print("roughly like the following:") - print("") - print(" import versioneer") - print(" setup( version=versioneer.get_version(),") - print(" cmdclass=versioneer.get_cmdclass(), ...)") - print("") - errors += 1 - if setters: - print("You should remove lines like 'versioneer.VCS = ' and") - print("'versioneer.versionfile_source = ' . This configuration") - print("now lives in setup.cfg, and should be removed from setup.py") - print("") - errors += 1 - return errors - - -def setup_command(): - """Set up Versioneer and exit with appropriate error code.""" - errors = do_setup() - errors += scan_setup_py() - sys.exit(1 if errors else 0) - - -if __name__ == "__main__": - cmd = sys.argv[1] - if cmd == "setup": - setup_command() From dd6473410c3edcbb5032b2110d0386092480d609 Mon Sep 17 00:00:00 2001 From: swittl Date: Wed, 19 Jun 2024 11:17:31 +0200 Subject: [PATCH 14/21] changed example to see the mesh in projection --- examples/01_api_example.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/examples/01_api_example.py b/examples/01_api_example.py index 9ea47b9..5ae477c 100644 --- a/examples/01_api_example.py +++ b/examples/01_api_example.py @@ -51,15 +51,15 @@ def main(): print(f'Detector Resolution: {detector.detector_resolution_mm} mm') print(f'Detector Pixel Count: {detector.detector_count_px} px') - # Make a projection an visualize it in python - image = artist_api.get_image() - # Load .stl part new_id = artist_api.load_part( Path(r'C:\Program Files\BAM\aRTist 2.12\Data\Library\ExampleParts\Fun\Dog.stl'), # Plesas check where the aRTist software is installed. 'Fe', 'test_object') + # Make a projection an visualize it in python + image = artist_api.get_image() + artist_api.delete_part('test_object') print(f'Inserted ID: {new_id}') From 451826a8670c24b609ad2ce2101fd70217c29d28 Mon Sep 17 00:00:00 2001 From: swittl Date: Wed, 30 Oct 2024 08:55:01 +0100 Subject: [PATCH 15/21] changed image saver --- artistlib/api.py | 50 +++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/artistlib/api.py b/artistlib/api.py index 09c7fc8..5019bb2 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -65,7 +65,7 @@ def save_image(self, elif save_mode == SAVEMODES.UINT16: self._save_image_uint16(save_path) elif save_mode == SAVEMODES.FLOAT_TIFF: - self._save_image_float_tiff(save_path) + self._save_image_float_tiff(save_path, save_projection_geometry) elif save_mode == SAVEMODES.FLOAT_RAW: self._save_image_float_raw(save_path) elif save_mode == SAVEMODES.PNG: @@ -77,10 +77,9 @@ def _save_image_uint16(self, save_path: Path): Args: save_path (Path): Save path of the projection. """ - self.rc.send('set imgList [Engine::Go]') + # self.rc.send('set imgList [Engine::Go]') save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') - self.rc.send(f'Image::Save16bit [lindex $imgList 0] {save_path_projection} True') - self.rc.send('foreach i $imgList {$i Delete}') + self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') def _save_image_uint8(self, save_path: Path): """Saves the current scene as porjection (.tif) and geometry (.json). @@ -88,29 +87,28 @@ def _save_image_uint8(self, save_path: Path): Args: save_path (Path): Save path of the projection. """ - self.rc.send('set imgList [Engine::Go]') + # self.rc.send('set imgList [Engine::Go]') save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', - self.rc.send(f'Image::Save8bit [lindex $imgList 0] {save_path_projection} True') - self.rc.send('foreach i $imgList {$i Delete}') + self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') with open(str(save_path_json), 'w') as f: json.dump(self.projection_geometry(), f, indent=4) - def _save_image_float_tiff(self, save_path: Path): + def _save_image_float_tiff(self, save_path: Path, save_projection_geometry: bool = False): """Saves the current scene as porjection (.tiff) and geometry (.json). Args: save_path (Path): Save path of the projection. """ - self.rc.send('set imgList [Engine::Go]') + # self.rc.send('set imgList [Engine::Go]') save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', - self.rc.send(f'Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True') - self.rc.send('foreach i $imgList {$i Delete}') - - with open(str(save_path_json), 'w') as f: - json.dump(self.projection_geometry(), f, indent=4) + self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') + # self.rc.send('foreach i $imgList {$i Delete}') + if save_projection_geometry: + with open(str(save_path_json), 'w') as f: + json.dump(self.projection_geometry(), f, indent=4) def _save_image_float_raw(self, save_path: Path): """Saves the current scene as porjection (.raw) and geometry (.json). @@ -118,11 +116,10 @@ def _save_image_float_raw(self, save_path: Path): Args: save_path (Path): Save path of the projection. """ - self.rc.send('set imgList [Engine::Go]') + # self.rc.send('set imgList [Engine::Go]') save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', - self.rc.send(f'Image::SaveFloatRawFile [lindex $imgList 0] {save_path_projection} True') - self.rc.send('foreach i $imgList {$i Delete}') + self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') with open(str(save_path_json), 'w') as f: json.dump(self.projection_geometry(), f, indent=4) @@ -133,10 +130,9 @@ def _save_image_png(self, save_path: Path): Args: save_path (Path): Save path of the projection. """ - self.rc.send('set imgList [Engine::Go]') + # self.rc.send('set imgList [Engine::Go]') save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') - self.rc.send(f'Image::SavePNG [lindex $imgList 0] {save_path_projection} True') - self.rc.send('foreach i $imgList {$i Delete}') + self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') def translate(self, id: int | str, x: float = 0.0, y: float = 0.0, z: float = 0.0) -> None: """Moves an object to an absolute position. All values in [mm]. @@ -223,14 +219,20 @@ def get_euler_angles(self, id: int | str) -> np.ndarray: def get_rotation_matrix(self, id: int | str) -> np.ndarray: euler_angles = self.get_euler_angles(id) - R_x = Rotation.from_euler("X", euler_angles[0], degrees=True).as_matrix() - R_y = Rotation.from_euler("Y", euler_angles[1], degrees=True).as_matrix() - R_z = Rotation.from_euler("Z", euler_angles[2], degrees=True).as_matrix() + R_x = Rotation.from_euler("x", euler_angles[0], degrees=True).as_matrix() + R_y = Rotation.from_euler("y", euler_angles[1], degrees=True).as_matrix() + R_z = Rotation.from_euler("z", euler_angles[2], degrees=True).as_matrix() + + # rotation = Rotation.from_euler('zxy', -euler_angles, degrees=True).as_matrix() rotation = R_z - rotation = rotation.dot(R_x) + rotation: np.ndarray = rotation.dot(R_x) rotation = rotation.dot(R_y) + # rotation = R_y + # rotation = rotation.dot(R_x) + # rotation = rotation.dot(R_z) + return rotation def get_orientation(self, id) -> np.ndarray: From 1add6eff3e7f26dc35979ea165301e5f267243af Mon Sep 17 00:00:00 2001 From: swittl Date: Mon, 4 Nov 2024 07:41:47 +0100 Subject: [PATCH 16/21] changed header --- artistlib/api.py | 9 +++++---- artistlib/utility/load_projection.py | 9 +++++++-- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/artistlib/api.py b/artistlib/api.py index 5019bb2..c333fc3 100644 --- a/artistlib/api.py +++ b/artistlib/api.py @@ -266,13 +266,14 @@ def projection_geometry(self) -> dict: data_dict = dict() data_dict['focal_spot_position_mm'] = source_position.tolist() - data_dict['focal_spot_orientation_matrix'] = source_orientation.tolist() + data_dict['focal_spot_orientation_quat'] = Rotation.from_matrix(source_orientation).as_quat().tolist() data_dict['detector_center_position_mm'] = detector_position.tolist() - data_dict['detector_center_orientation_matrix'] = detector_orientation.tolist() data_dict['detector_center_orientation_quat'] = Rotation.from_matrix(detector_orientation).as_quat().tolist() - data_dict['detector_count_px'] = detector_pixel_count.tolist() - data_dict['pixel_pitch_mm'] = detector_resolution.tolist() + data_dict['image_width_px'] = detector_pixel_count.tolist()[0] + data_dict['pixel_pitch_width_mm'] = detector_resolution.tolist()[0] + data_dict['image_height_px'] = detector_pixel_count.tolist()[1] + data_dict['pixel_pitch_height_mm'] = detector_resolution.tolist()[1] return data_dict diff --git a/artistlib/utility/load_projection.py b/artistlib/utility/load_projection.py index 21e8153..5c0a097 100644 --- a/artistlib/utility/load_projection.py +++ b/artistlib/utility/load_projection.py @@ -2,11 +2,16 @@ import numpy as np from pathlib import Path import json +import time def load_projection(projection_path: Path, load_projection_geometry: bool = True) -> tuple[np.ndarray, dict]: - projection_array = np.array(Image.open(projection_path)) - + try: + projection_array = np.array(Image.open(projection_path)) + except: + time.sleep(1) + projection_array = np.array(Image.open(projection_path)) + if not load_projection_geometry: return projection_array, None else: From 6747ca13daa392a8f5e67fe49c2c72f5e1ad24d8 Mon Sep 17 00:00:00 2001 From: swittl Date: Tue, 19 Nov 2024 21:00:02 +0100 Subject: [PATCH 17/21] restructure to uv --- .gitignore | 4 +- .python-version | 1 + artistlib/_version.py | 658 ----------------- artistlib/console.py | 7 - artistlib/documentation.md | 65 -- artistlib/remote_access.py | 56 -- docs/artistlib.png | Bin 9038 -> 0 bytes docs/favicon.ico | Bin 46332 -> 0 bytes docs/index.html | 579 --------------- docs/templates/head.mako | 25 - docs/templates/logo.mako | 5 - docs/test.html | 5 - examples/01_api_example.py | 7 +- examples/02_circular_trajectory.py | 4 +- examples/04_save_image.py | 5 +- project.toml | 10 - pyproject.toml | 28 + setup.py | 22 - .../artist_pythonlib}/__init__.py | 7 +- {artistlib => src/artist_pythonlib}/api.py | 82 ++- .../artist_pythonlib}/common_types.py | 7 +- src/artist_pythonlib/geometries/__init__.py | 2 + .../geometries/standard_format.py | 35 + src/artist_pythonlib/geometries/thd_format.py | 57 ++ .../artist_pythonlib}/hardware/__init__.py | 0 .../hardware/base_hardware.py | 0 .../hardware/xray_detector.py | 4 +- .../artist_pythonlib}/hardware/xray_source.py | 4 +- .../artist_pythonlib/py.typed | 0 .../artist_pythonlib}/remote_connection.py | 0 .../artist_pythonlib}/trajectory/__init__.py | 0 .../trajectory/ct_trajectories.py | 0 .../artist_pythonlib}/utility/__init__.py | 0 .../utility/load_projection.py | 0 uv.lock | 663 ++++++++++++++++++ 35 files changed, 847 insertions(+), 1495 deletions(-) create mode 100644 .python-version delete mode 100644 artistlib/_version.py delete mode 100644 artistlib/console.py delete mode 100644 artistlib/documentation.md delete mode 100644 artistlib/remote_access.py delete mode 100644 docs/artistlib.png delete mode 100644 docs/favicon.ico delete mode 100644 docs/index.html delete mode 100644 docs/templates/head.mako delete mode 100644 docs/templates/logo.mako delete mode 100644 docs/test.html delete mode 100644 project.toml create mode 100644 pyproject.toml delete mode 100644 setup.py rename {artistlib => src/artist_pythonlib}/__init__.py (54%) rename {artistlib => src/artist_pythonlib}/api.py (83%) rename {artistlib => src/artist_pythonlib}/common_types.py (89%) create mode 100644 src/artist_pythonlib/geometries/__init__.py create mode 100644 src/artist_pythonlib/geometries/standard_format.py create mode 100644 src/artist_pythonlib/geometries/thd_format.py rename {artistlib => src/artist_pythonlib}/hardware/__init__.py (100%) rename {artistlib => src/artist_pythonlib}/hardware/base_hardware.py (100%) rename {artistlib => src/artist_pythonlib}/hardware/xray_detector.py (96%) rename {artistlib => src/artist_pythonlib}/hardware/xray_source.py (97%) rename artistlib/objects/__init__.py => src/artist_pythonlib/py.typed (100%) rename {artistlib => src/artist_pythonlib}/remote_connection.py (100%) rename {artistlib => src/artist_pythonlib}/trajectory/__init__.py (100%) rename {artistlib => src/artist_pythonlib}/trajectory/ct_trajectories.py (100%) rename {artistlib => src/artist_pythonlib}/utility/__init__.py (100%) rename {artistlib => src/artist_pythonlib}/utility/load_projection.py (100%) create mode 100644 uv.lock diff --git a/.gitignore b/.gitignore index ec951ea..00d2c60 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ __pycache__ artistlib.egg-info dist /venv/ +/.venv/ *.tif /workspace/ *.raw @@ -9,4 +10,5 @@ dist *.json *.aRTist *.ply -/build/ \ No newline at end of file +/build/ +/examples/ \ No newline at end of file diff --git a/.python-version b/.python-version new file mode 100644 index 0000000..c8cfe39 --- /dev/null +++ b/.python-version @@ -0,0 +1 @@ +3.10 diff --git a/artistlib/_version.py b/artistlib/_version.py deleted file mode 100644 index 6e093b4..0000000 --- a/artistlib/_version.py +++ /dev/null @@ -1,658 +0,0 @@ - -# This file helps to compute a version number in source trees obtained from -# git-archive tarball (such as those provided by githubs download-from-tag -# feature). Distribution tarballs (built by setup.py sdist) and build -# directories (produced by setup.py build) will contain a much shorter file -# that just contains the computed version number. - -# This file is released into the public domain. -# Generated by versioneer-0.26 -# https://github.com/python-versioneer/python-versioneer - -"""Git implementation of _version.py.""" - -import errno -import os -import re -import subprocess -import sys -from typing import Callable, Dict -import functools - - -def get_keywords(): - """Get the keywords needed to look up the version information.""" - # these strings will be replaced by git during git-archive. - # setup.py/versioneer.py will grep for the variable names, so they must - # each be defined on a line of their own. _version.py will just call - # get_keywords(). - git_refnames = "$Format:%d$" - git_full = "$Format:%H$" - git_date = "$Format:%ci$" - keywords = {"refnames": git_refnames, "full": git_full, "date": git_date} - return keywords - - -class VersioneerConfig: - """Container for Versioneer configuration parameters.""" - - -def get_config(): - """Create, populate and return the VersioneerConfig() object.""" - # these strings are filled in when 'setup.py versioneer' creates - # _version.py - cfg = VersioneerConfig() - cfg.VCS = "git" - cfg.style = "pep440" - cfg.tag_prefix = "v" - cfg.parentdir_prefix = "" - cfg.versionfile_source = "artistlib/_version.py" - cfg.verbose = False - return cfg - - -class NotThisMethod(Exception): - """Exception raised if a method is not valid for the current scenario.""" - - -LONG_VERSION_PY: Dict[str, str] = {} -HANDLERS: Dict[str, Dict[str, Callable]] = {} - - -def register_vcs_handler(vcs, method): # decorator - """Create decorator to mark a method as the handler of a VCS.""" - def decorate(f): - """Store f in HANDLERS[vcs][method].""" - if vcs not in HANDLERS: - HANDLERS[vcs] = {} - HANDLERS[vcs][method] = f - return f - return decorate - - -def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False, - env=None): - """Call the given command(s).""" - assert isinstance(commands, list) - process = None - - popen_kwargs = {} - if sys.platform == "win32": - # This hides the console window if pythonw.exe is used - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - popen_kwargs["startupinfo"] = startupinfo - - for command in commands: - try: - dispcmd = str([command] + args) - # remember shell=False, so use git.cmd on windows, not just git - process = subprocess.Popen([command] + args, cwd=cwd, env=env, - stdout=subprocess.PIPE, - stderr=(subprocess.PIPE if hide_stderr - else None), **popen_kwargs) - break - except OSError: - e = sys.exc_info()[1] - if e.errno == errno.ENOENT: - continue - if verbose: - print("unable to run %s" % dispcmd) - print(e) - return None, None - else: - if verbose: - print("unable to find command, tried %s" % (commands,)) - return None, None - stdout = process.communicate()[0].strip().decode() - if process.returncode != 0: - if verbose: - print("unable to run %s (error)" % dispcmd) - print("stdout was %s" % stdout) - return None, process.returncode - return stdout, process.returncode - - -def versions_from_parentdir(parentdir_prefix, root, verbose): - """Try to determine the version from the parent directory name. - - Source tarballs conventionally unpack into a directory that includes both - the project name and a version string. We will also support searching up - two directory levels for an appropriately named parent directory - """ - rootdirs = [] - - for _ in range(3): - dirname = os.path.basename(root) - if dirname.startswith(parentdir_prefix): - return {"version": dirname[len(parentdir_prefix):], - "full-revisionid": None, - "dirty": False, "error": None, "date": None} - rootdirs.append(root) - root = os.path.dirname(root) # up a level - - if verbose: - print("Tried directories %s but none started with prefix %s" % - (str(rootdirs), parentdir_prefix)) - raise NotThisMethod("rootdir doesn't start with parentdir_prefix") - - -@register_vcs_handler("git", "get_keywords") -def git_get_keywords(versionfile_abs): - """Extract version information from the given file.""" - # the code embedded in _version.py can just fetch the value of these - # keywords. When used from setup.py, we don't want to import _version.py, - # so we do it with a regexp instead. This function is not used from - # _version.py. - keywords = {} - try: - with open(versionfile_abs, "r") as fobj: - for line in fobj: - if line.strip().startswith("git_refnames ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["refnames"] = mo.group(1) - if line.strip().startswith("git_full ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["full"] = mo.group(1) - if line.strip().startswith("git_date ="): - mo = re.search(r'=\s*"(.*)"', line) - if mo: - keywords["date"] = mo.group(1) - except OSError: - pass - return keywords - - -@register_vcs_handler("git", "keywords") -def git_versions_from_keywords(keywords, tag_prefix, verbose): - """Get version information from git keywords.""" - if "refnames" not in keywords: - raise NotThisMethod("Short version file found") - date = keywords.get("date") - if date is not None: - # Use only the last line. Previous lines may contain GPG signature - # information. - date = date.splitlines()[-1] - - # git-2.2.0 added "%cI", which expands to an ISO-8601 -compliant - # datestamp. However we prefer "%ci" (which expands to an "ISO-8601 - # -like" string, which we must then edit to make compliant), because - # it's been around since git-1.5.3, and it's too difficult to - # discover which version we're using, or to work around using an - # older one. - date = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - refnames = keywords["refnames"].strip() - if refnames.startswith("$Format"): - if verbose: - print("keywords are unexpanded, not using") - raise NotThisMethod("unexpanded keywords, not a git-archive tarball") - refs = {r.strip() for r in refnames.strip("()").split(",")} - # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of - # just "foo-1.0". If we see a "tag: " prefix, prefer those. - TAG = "tag: " - tags = {r[len(TAG):] for r in refs if r.startswith(TAG)} - if not tags: - # Either we're using git < 1.8.3, or there really are no tags. We use - # a heuristic: assume all version tags have a digit. The old git %d - # expansion behaves like git log --decorate=short and strips out the - # refs/heads/ and refs/tags/ prefixes that would let us distinguish - # between branches and tags. By ignoring refnames without digits, we - # filter out many common branch names like "release" and - # "stabilization", as well as "HEAD" and "master". - tags = {r for r in refs if re.search(r'\d', r)} - if verbose: - print("discarding '%s', no digits" % ",".join(refs - tags)) - if verbose: - print("likely tags: %s" % ",".join(sorted(tags))) - for ref in sorted(tags): - # sorting will prefer e.g. "2.0" over "2.0rc1" - if ref.startswith(tag_prefix): - r = ref[len(tag_prefix):] - # Filter out refs that exactly match prefix or that don't start - # with a number once the prefix is stripped (mostly a concern - # when prefix is '') - if not re.match(r'\d', r): - continue - if verbose: - print("picking %s" % r) - return {"version": r, - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": None, - "date": date} - # no suitable tags, so version is "0+unknown", but full hex is still there - if verbose: - print("no suitable tags, using unknown + full revision id") - return {"version": "0+unknown", - "full-revisionid": keywords["full"].strip(), - "dirty": False, "error": "no suitable tags", "date": None} - - -@register_vcs_handler("git", "pieces_from_vcs") -def git_pieces_from_vcs(tag_prefix, root, verbose, runner=run_command): - """Get version from 'git describe' in the root of the source tree. - - This only gets called if the git-archive 'subst' keywords were *not* - expanded, and _version.py hasn't already been rewritten with a short - version string, meaning we're inside a checked out source tree. - """ - GITS = ["git"] - if sys.platform == "win32": - GITS = ["git.cmd", "git.exe"] - - # GIT_DIR can interfere with correct operation of Versioneer. - # It may be intended to be passed to the Versioneer-versioned project, - # but that should not change where we get our version from. - env = os.environ.copy() - env.pop("GIT_DIR", None) - runner = functools.partial(runner, env=env) - - _, rc = runner(GITS, ["rev-parse", "--git-dir"], cwd=root, - hide_stderr=not verbose) - if rc != 0: - if verbose: - print("Directory %s not under git control" % root) - raise NotThisMethod("'git rev-parse --git-dir' returned error") - - # if there is a tag matching tag_prefix, this yields TAG-NUM-gHEX[-dirty] - # if there isn't one, this yields HEX[-dirty] (no NUM) - describe_out, rc = runner(GITS, [ - "describe", "--tags", "--dirty", "--always", "--long", - "--match", f"{tag_prefix}[[:digit:]]*" - ], cwd=root) - # --long was added in git-1.5.5 - if describe_out is None: - raise NotThisMethod("'git describe' failed") - describe_out = describe_out.strip() - full_out, rc = runner(GITS, ["rev-parse", "HEAD"], cwd=root) - if full_out is None: - raise NotThisMethod("'git rev-parse' failed") - full_out = full_out.strip() - - pieces = {} - pieces["long"] = full_out - pieces["short"] = full_out[:7] # maybe improved later - pieces["error"] = None - - branch_name, rc = runner(GITS, ["rev-parse", "--abbrev-ref", "HEAD"], - cwd=root) - # --abbrev-ref was added in git-1.6.3 - if rc != 0 or branch_name is None: - raise NotThisMethod("'git rev-parse --abbrev-ref' returned error") - branch_name = branch_name.strip() - - if branch_name == "HEAD": - # If we aren't exactly on a branch, pick a branch which represents - # the current commit. If all else fails, we are on a branchless - # commit. - branches, rc = runner(GITS, ["branch", "--contains"], cwd=root) - # --contains was added in git-1.5.4 - if rc != 0 or branches is None: - raise NotThisMethod("'git branch --contains' returned error") - branches = branches.split("\n") - - # Remove the first line if we're running detached - if "(" in branches[0]: - branches.pop(0) - - # Strip off the leading "* " from the list of branches. - branches = [branch[2:] for branch in branches] - if "master" in branches: - branch_name = "master" - elif not branches: - branch_name = None - else: - # Pick the first branch that is returned. Good or bad. - branch_name = branches[0] - - pieces["branch"] = branch_name - - # parse describe_out. It will be like TAG-NUM-gHEX[-dirty] or HEX[-dirty] - # TAG might have hyphens. - git_describe = describe_out - - # look for -dirty suffix - dirty = git_describe.endswith("-dirty") - pieces["dirty"] = dirty - if dirty: - git_describe = git_describe[:git_describe.rindex("-dirty")] - - # now we have TAG-NUM-gHEX or HEX - - if "-" in git_describe: - # TAG-NUM-gHEX - mo = re.search(r'^(.+)-(\d+)-g([0-9a-f]+)$', git_describe) - if not mo: - # unparsable. Maybe git-describe is misbehaving? - pieces["error"] = ("unable to parse git-describe output: '%s'" - % describe_out) - return pieces - - # tag - full_tag = mo.group(1) - if not full_tag.startswith(tag_prefix): - if verbose: - fmt = "tag '%s' doesn't start with prefix '%s'" - print(fmt % (full_tag, tag_prefix)) - pieces["error"] = ("tag '%s' doesn't start with prefix '%s'" - % (full_tag, tag_prefix)) - return pieces - pieces["closest-tag"] = full_tag[len(tag_prefix):] - - # distance: number of commits since tag - pieces["distance"] = int(mo.group(2)) - - # commit: short hex revision ID - pieces["short"] = mo.group(3) - - else: - # HEX: no tags - pieces["closest-tag"] = None - out, rc = runner(GITS, ["rev-list", "HEAD", "--left-right"], cwd=root) - pieces["distance"] = len(out.split()) # total number of commits - - # commit date: see ISO-8601 comment in git_versions_from_keywords() - date = runner(GITS, ["show", "-s", "--format=%ci", "HEAD"], cwd=root)[0].strip() - # Use only the last line. Previous lines may contain GPG signature - # information. - date = date.splitlines()[-1] - pieces["date"] = date.strip().replace(" ", "T", 1).replace(" ", "", 1) - - return pieces - - -def plus_or_dot(pieces): - """Return a + if we don't already have one, else return a .""" - if "+" in pieces.get("closest-tag", ""): - return "." - return "+" - - -def render_pep440(pieces): - """Build up version string, with post-release "local version identifier". - - Our goal: TAG[+DISTANCE.gHEX[.dirty]] . Note that if you - get a tagged build and then dirty it, you'll get TAG+0.gHEX.dirty - - Exceptions: - 1: no tags. git_describe was just HEX. 0+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += plus_or_dot(pieces) - rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_branch(pieces): - """TAG[[.dev0]+DISTANCE.gHEX[.dirty]] . - - The ".dev0" means not master branch. Note that .dev0 sorts backwards - (a feature branch will appear "older" than the master branch). - - Exceptions: - 1: no tags. 0[.dev0]+untagged.DISTANCE.gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "%d.g%s" % (pieces["distance"], pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0" - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += "+untagged.%d.g%s" % (pieces["distance"], - pieces["short"]) - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def pep440_split_post(ver): - """Split pep440 version string at the post-release segment. - - Returns the release segments before the post-release and the - post-release version number (or -1 if no post-release segment is present). - """ - vc = str.split(ver, ".post") - return vc[0], int(vc[1] or 0) if len(vc) == 2 else None - - -def render_pep440_pre(pieces): - """TAG[.postN.devDISTANCE] -- No -dirty. - - Exceptions: - 1: no tags. 0.post0.devDISTANCE - """ - if pieces["closest-tag"]: - if pieces["distance"]: - # update the post release segment - tag_version, post_version = pep440_split_post(pieces["closest-tag"]) - rendered = tag_version - if post_version is not None: - rendered += ".post%d.dev%d" % (post_version + 1, pieces["distance"]) - else: - rendered += ".post0.dev%d" % (pieces["distance"]) - else: - # no commits, use the tag as the version - rendered = pieces["closest-tag"] - else: - # exception #1 - rendered = "0.post0.dev%d" % pieces["distance"] - return rendered - - -def render_pep440_post(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX] . - - The ".dev0" means dirty. Note that .dev0 sorts backwards - (a dirty tree will appear "older" than the corresponding clean one), - but you shouldn't be releasing software with -dirty anyways. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%s" % pieces["short"] - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - rendered += "+g%s" % pieces["short"] - return rendered - - -def render_pep440_post_branch(pieces): - """TAG[.postDISTANCE[.dev0]+gHEX[.dirty]] . - - The ".dev0" means not master branch. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0]+gHEX[.dirty] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += plus_or_dot(pieces) - rendered += "g%s" % pieces["short"] - if pieces["dirty"]: - rendered += ".dirty" - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["branch"] != "master": - rendered += ".dev0" - rendered += "+g%s" % pieces["short"] - if pieces["dirty"]: - rendered += ".dirty" - return rendered - - -def render_pep440_old(pieces): - """TAG[.postDISTANCE[.dev0]] . - - The ".dev0" means dirty. - - Exceptions: - 1: no tags. 0.postDISTANCE[.dev0] - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"] or pieces["dirty"]: - rendered += ".post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - else: - # exception #1 - rendered = "0.post%d" % pieces["distance"] - if pieces["dirty"]: - rendered += ".dev0" - return rendered - - -def render_git_describe(pieces): - """TAG[-DISTANCE-gHEX][-dirty]. - - Like 'git describe --tags --dirty --always'. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - if pieces["distance"]: - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render_git_describe_long(pieces): - """TAG-DISTANCE-gHEX[-dirty]. - - Like 'git describe --tags --dirty --always -long'. - The distance/hash is unconditional. - - Exceptions: - 1: no tags. HEX[-dirty] (note: no 'g' prefix) - """ - if pieces["closest-tag"]: - rendered = pieces["closest-tag"] - rendered += "-%d-g%s" % (pieces["distance"], pieces["short"]) - else: - # exception #1 - rendered = pieces["short"] - if pieces["dirty"]: - rendered += "-dirty" - return rendered - - -def render(pieces, style): - """Render the given version pieces into the requested style.""" - if pieces["error"]: - return {"version": "unknown", - "full-revisionid": pieces.get("long"), - "dirty": None, - "error": pieces["error"], - "date": None} - - if not style or style == "default": - style = "pep440" # the default - - if style == "pep440": - rendered = render_pep440(pieces) - elif style == "pep440-branch": - rendered = render_pep440_branch(pieces) - elif style == "pep440-pre": - rendered = render_pep440_pre(pieces) - elif style == "pep440-post": - rendered = render_pep440_post(pieces) - elif style == "pep440-post-branch": - rendered = render_pep440_post_branch(pieces) - elif style == "pep440-old": - rendered = render_pep440_old(pieces) - elif style == "git-describe": - rendered = render_git_describe(pieces) - elif style == "git-describe-long": - rendered = render_git_describe_long(pieces) - else: - raise ValueError("unknown style '%s'" % style) - - return {"version": rendered, "full-revisionid": pieces["long"], - "dirty": pieces["dirty"], "error": None, - "date": pieces.get("date")} - - -def get_versions(): - """Get version information or return default if unable to do so.""" - # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have - # __file__, we can work backwards from there to the root. Some - # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which - # case we can only use expanded keywords. - - cfg = get_config() - verbose = cfg.verbose - - try: - return git_versions_from_keywords(get_keywords(), cfg.tag_prefix, - verbose) - except NotThisMethod: - pass - - try: - root = os.path.realpath(__file__) - # versionfile_source is the relative path from the top of the source - # tree (where the .git directory might live) to this file. Invert - # this to find the root from __file__. - for _ in cfg.versionfile_source.split('/'): - root = os.path.dirname(root) - except NameError: - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to find root of source tree", - "date": None} - - try: - pieces = git_pieces_from_vcs(cfg.tag_prefix, root, verbose) - return render(pieces, cfg.style) - except NotThisMethod: - pass - - try: - if cfg.parentdir_prefix: - return versions_from_parentdir(cfg.parentdir_prefix, root, verbose) - except NotThisMethod: - pass - - return {"version": "0+unknown", "full-revisionid": None, - "dirty": None, - "error": "unable to compute version", "date": None} diff --git a/artistlib/console.py b/artistlib/console.py deleted file mode 100644 index 22a9aa0..0000000 --- a/artistlib/console.py +++ /dev/null @@ -1,7 +0,0 @@ -import subprocess -import os - -path = os.path.dirname(os.path.abspath(__file__)) -correctedPath = path.replace("\\", "/") - -cmd = subprocess.run(["python", correctedPath + "/remote_access.py"]) \ No newline at end of file diff --git a/artistlib/documentation.md b/artistlib/documentation.md deleted file mode 100644 index f1749aa..0000000 --- a/artistlib/documentation.md +++ /dev/null @@ -1,65 +0,0 @@ -**Hint:** This project is in its early stages and may change significantly over time. - -Getting started -=============== - -Requirements ------------- -A **Python 3** environment (Python 3.8 or higher) is required. The following Python packages are required as well. They usually come with a Python environment, or can be installed there easily: - -* none so far. - - -Installation ------------- - -If you want to **install** the package in your Python environment, you can use [pip]. For example, you can run the following command to make the toolbox available: - - pip install artistlib - -[pip]: https://pip.pypa.io - -To use the package **without installation**, you need to download the package manually. You have the following three options: - -* Download the package [from PyPi]. You will get a zipped file called `artistlib-X.X.X.tar.gz` (where X.X.X is the current version number). Open or unpack this file to get to its contents. -* Download the repository [from GitHub]: press the *clone* button to download a ZIP file. Unpack it or open it to see its contents. -* You can also clone the repository from GitHub via the terminal: - - `git clone https://github.com/BAMresearch/aRTist-PythonLib.git` - -From any of these three options, you will get the complete package source code. It contains a folder called `artistlib`. If you want to use the library from your Python scripts without installing it, you need to copy the folder `artistlib` to the location of your Python scripts to make the package available. - - -[from GitHub]: https://github.com/BAMresearch/aRTist-PythonLib -[from PyPi]: https://pypi.org/project/artistlib/ - -Usage ------ - -Please make sure that aRTist is running and waiting for remote connection (menu: Tools>Enable remote access). - -The following example code shows the basic usage: - -```python -.. include:: ../example_artistlib.py -``` - -About -===== - -The aRTist library was developed for utilize the Python scripting of the radiographic simulator [aRTist]. - -The software is released under the **Apache 2.0 license,** its source code is available [on GitHub]. - -[aRTist]: https://artist.bam.de -[on GitHub]: https://github.com/BAMresearch/aRTist-PythonLib - -Contributors ------------- -The following people contributed to code and documentation of the package: - -* Alexander Funke -* David Schumacher -* Carsten Bellon -* David Plotzki -* David Denkler \ No newline at end of file diff --git a/artistlib/remote_access.py b/artistlib/remote_access.py deleted file mode 100644 index 06c8876..0000000 --- a/artistlib/remote_access.py +++ /dev/null @@ -1,56 +0,0 @@ -import sys -import os -path = os.path.dirname(os.path.abspath(__file__)) -path = os.path.dirname(path) -sys.path.insert(0, path) - -import artistlib as a -from prompt_toolkit import PromptSession -session = PromptSession() - -list = ["SUCCESS", "RESULT", "STDOUT"] -commands = [] - -rc = a.Junction() - -c = 0 - -while True: - try: - com = session.prompt("Command: ") - - if "::RemoteControl::ReceiveFile" in com: - fileName2 = input("Send following file: ") - recAnswer = a.Junction.send_file(rc, fileName2) - print(recAnswer) - - else: - ans = a.Junction.send(rc, com, "*") - - if "FILE" in ans: - fileName = input("Save file as: ") - a.Junction.receive_file(rc, fileName) - print("File saved as ", fileName) - - for i in list: - typ = a.Junction.pick(rc, ans, i) - if "IMAGE" in ans and not "{}" in typ: - name = input("Save Image as: ") - a.Junction.save_image(rc, name) - print("Image saved as ", name) - - if not "{}" in typ: - if not "not found" in typ: - print(typ) - else: - c += 1 - else: - c += 1 - - if c >= 3 and not "BASE64" in ans: - print(ans) - - c = 0 - - except KeyboardInterrupt: - raise SystemExit diff --git a/docs/artistlib.png b/docs/artistlib.png deleted file mode 100644 index 18bf79cc5e695cff5e4f509a9367e59b192ca11f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 9038 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%0AKpe!k;bk=tB4%YFWY6VZsBP4+a`bd-*?!J$vcm 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 K(ZTU2I{ynr*+GE- diff --git a/docs/index.html b/docs/index.html deleted file mode 100644 index fc818e1..0000000 --- a/docs/index.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - - - -artistlib API documentation - - - - - - - - - - - - - -

    -
    -
    -

    Package artistlib

    -
    -
    -

    The aRTist Python library is intended to remote control and automate the radiographic simulator aRTist.

    -

    Hint: This project is in its early stages and may change significantly over time.

    -

    Getting started

    -

    Requirements

    -

    A Python 3 environment (Python 3.8 or higher) is required. The following Python packages are required as well. They usually come with a Python environment, or can be installed there easily:

    -
      -
    • none so far.
    • -
    -

    Installation

    -

    If you want to install the package in your Python environment, you can use pip. For example, you can run the following command to make the toolbox available:

    -
    pip install artistlib
    -
    -

    To use the package without installation, you need to download the package manually. You have the following three options:

    -
      -
    • Download the package from PyPi. You will get a zipped file called artistlib-X.X.X.tar.gz (where X.X.X is the current version number). Open or unpack this file to get to its contents.
    • -
    • Download the repository from GitHub: press the clone button to download a ZIP file. Unpack it or open it to see its contents.
    • -
    • -

      You can also clone the repository from GitHub via the terminal:

      -

      git clone https://github.com/BAMresearch/aRTist-PythonLib.git

      -
    • -
    -

    From any of these three options, you will get the complete package source code. It contains a folder called artistlib. If you want to use the library from your Python scripts without installing it, you need to copy the folder artistlib to the location of your Python scripts to make the package available.

    -

    Usage

    -

    Please make sure that aRTist is running and waiting for remote connection (menu: Tools>Enable remote access).

    -

    The following example code shows the basic usage:

    -
    import artistlib as a
    -
    -# connect to aRTist (default: host='localhost', port=3658) 
    -rc = a.Junction()
    -
    -# print aRTist's version number
    -ver = a.Junction.send(rc, '::aRTist::GetVersion full')
    -print(ver)
    -
    -# - load a project
    -# - run the simulation
    -# - save the resulting projection from the image viewer
    -a.Junction.send(rc, 'FileIO::OpenAny $Xray(LibraryDir)/ExampleProjects/Schlumpfmark.aRTist')
    -a.Junction.send(rc, 'Engine::GoCmd')
    -ans = "Saved as: "
    -ans += a.Junction.send(rc, 'Modules::Invoke ImageViewer SaveFile [file join $env(HOME) Pictures/artistlib.tif] true')
    -print(ans)
    -
    -# - load a project
    -# - run the simulation without viewing the result
    -# - transfer the final projection 
    -# - saving the projection image  >>>> This requires aRTist 2.12.7 or higher! <<<<
    -# - delete the images to release the memory
    -a.Junction.send(rc, 'FileIO::OpenAny $Xray(LibraryDir)/ExampleProjects/aRTist.aRTist')
    -a.Junction.send(rc, 'set imgList [Engine::Go]')
    -a.Junction.send(rc, 'RemoteControl::SendImage [lindex $imgList 0]')
    -a.Junction.save_image(rc, "transferred.tif")
    -a.Junction.send(rc, 'foreach i $imgList {$i Delete}')
    -print("Saved as: transferred.tif")
    -
    -

    About

    -

    The aRTist library was developed for utilize the Python scripting of the radiographic simulator aRTist.

    -

    The software is released under the Apache 2.0 license, its source code is available on GitHub.

    -

    Contributors

    -

    The following people contributed to code and documentation of the package:

    -
      -
    • Alexander Funke
    • -
    • David Schumacher
    • -
    • Carsten Bellon
    • -
    • David Plotzki
    • -
    • David Denkler
    • -
    -
    - -Expand source code - -
    # -*- coding: UTF-8 -*-
    -"""The aRTist Python library is intended to remote control and automate the radiographic simulator aRTist.
    -
    -.. include:: ./documentation.md
    -"""
    -
    -__pdoc__ = {'console': False, 'remote_access': False}
    -
    -from ._version import get_versions
    -__version__ = get_versions()['version']
    -del get_versions
    -
    -import numpy as np
    -from numpy import append
    -import socket
    -import base64
    -import pathlib
    -from PIL import Image
    -class Junction:
    -    """Remote control of aRTist simulator (this is a test)
    -    """
    -    def __init__(self, host="localhost", port=3658, bufferSize=1024, timeout=5):
    -        self.host = host
    -        self.port = port
    -        self.bufferSize = bufferSize
    -        self.timeout = timeout
    -        self.error = 0
    -        self.progress = 0
    -        self.answer = {}
    -
    -        self.connect()
    -
    -    def connect(self):
    -        self.S = socket.socket()                        # Create socket (for TCP)
    -        self.S.connect((self.host, self.port))          # Connect to aRTist
    -        self.S.settimeout(self.timeout)
    -        self.listen(0)
    -        return self
    -
    -    def send(self, command, msgType="RESULT"):
    -        c = command + '\n'
    -        self.S.send(c.encode())
    -        return self.listen(msgType=msgType)
    -
    -    def listen(self, command_no=1, msgType="RESULT"):
    -        answer = ""
    -        stop = False
    -        if (command_no == 0):
    -            self.S.settimeout(0.2)
    -        while (not stop):# and ("SUCCESS" not in total) and ("ERROR" not in total):     # Solange server antwortet und nicht "SUCCESS" enthält
    -            try:
    -                msg = self.S.recv(self.bufferSize).decode()
    -            except BaseException as e:
    -                err = e.args[0]
    -                if err == "timed out":
    -                    #print("Timeout\n")
    -                    answer += "RESULT Timeout\n"
    -                    #print(answer)
    -                    stop = True
    -                    continue
    -            else:
    -                if ("SUCCESS" in msg):
    -                    answer += msg
    -                    stop = True
    -                    continue
    -                elif ("ERROR" in msg):
    -                    answer += msg
    -                    stop = True
    -                    #global error
    -                    self.error = self.error + 1 
    -                    continue
    -                elif ("PROGRESS" in msg):
    -                    try:
    -                        self.progress = float(msg.strip('PROGRESS '))
    -                    except:
    -                        self.progress = 0
    -                    continue
    -                else:
    -                    if (command_no == 0):
    -                        print(msg)
    -                    answer += msg
    -        self.S.settimeout(self.timeout)
    -        self.answer.update({"SUCCESS":self.pick(answer, "SUCCESS"), "RESULT":self.pick(answer, "RESULT"), "SDTOUT":self.pick(answer, "STDOUT"), "BASE64":self.pick(answer, "BASE64"), "IMAGE":self.pick(answer, "IMAGE"), "FILE":self.pick(answer, "FILE")})
    -        if (msgType != "*"):
    -            answer = self.pick(answer, msgType)
    -        return answer
    -
    -    def pick(self, answer, res='RESULT'):
    -        picked = ''
    -        for a in answer.split('\n'):
    -            if a.find(res) == 0:
    -                picked += a[1 + len(res):].strip('\r') + '\n'
    -        if len(picked) == 0:
    -            return res + ' not found.'
    -        return picked
    -
    -    def get_answer(self, key):
    -        return self.answer[key]
    -
    -    def save_image(self, imageName):
    -        npTypes = [np.bool_, np.ubyte, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, np.int_, np.uint, np.single, np.double]
    -        imageData = self.answer["BASE64"]
    -        decodedData = base64.b64decode((imageData))
    -        imageHeader = self.answer["IMAGE"].split()
    -        dtype = npTypes[int(imageHeader[4])]
    -        im = np.frombuffer(decodedData, dtype).reshape((int(imageHeader[1]),int(imageHeader[0])))
    -        Image.fromarray(im).save(imageName)
    -
    -    def receive_file(self, fileName):
    -        fileData = self.answer["BASE64"]
    -        decodedFile = base64.b64decode((fileData))
    -        artistFile = open(fileName, "wb")
    -        artistFile.write(decodedFile)
    -        artistFile.close()
    -
    -    def send_file(self, fileName):
    -        outFile = open(fileName, "br")
    -        fileBytes = outFile.read()
    -        encBytes = base64.b64encode((fileBytes))
    -        encString = str(encBytes)
    -        encString = encString.lstrip("b'").rstrip("'")
    -        fileExtension = pathlib.Path(fileName).suffix
    -        com = "::RemoteControl::ReceiveFile " + encString + " " + fileExtension
    -        recAnswer = self.send(com, "RESULT")
    -        return recAnswer
    -
    -
    -
    -
    -
    -
    -
    -
    -
    -

    Classes

    -
    -
    -class Junction -(host='localhost', port=3658, bufferSize=1024, timeout=5) -
    -
    -

    Remote control of aRTist simulator (this is a test)

    -
    - -Expand source code - -
    class Junction:
    -    """Remote control of aRTist simulator (this is a test)
    -    """
    -    def __init__(self, host="localhost", port=3658, bufferSize=1024, timeout=5):
    -        self.host = host
    -        self.port = port
    -        self.bufferSize = bufferSize
    -        self.timeout = timeout
    -        self.error = 0
    -        self.progress = 0
    -        self.answer = {}
    -
    -        self.connect()
    -
    -    def connect(self):
    -        self.S = socket.socket()                        # Create socket (for TCP)
    -        self.S.connect((self.host, self.port))          # Connect to aRTist
    -        self.S.settimeout(self.timeout)
    -        self.listen(0)
    -        return self
    -
    -    def send(self, command, msgType="RESULT"):
    -        c = command + '\n'
    -        self.S.send(c.encode())
    -        return self.listen(msgType=msgType)
    -
    -    def listen(self, command_no=1, msgType="RESULT"):
    -        answer = ""
    -        stop = False
    -        if (command_no == 0):
    -            self.S.settimeout(0.2)
    -        while (not stop):# and ("SUCCESS" not in total) and ("ERROR" not in total):     # Solange server antwortet und nicht "SUCCESS" enthält
    -            try:
    -                msg = self.S.recv(self.bufferSize).decode()
    -            except BaseException as e:
    -                err = e.args[0]
    -                if err == "timed out":
    -                    #print("Timeout\n")
    -                    answer += "RESULT Timeout\n"
    -                    #print(answer)
    -                    stop = True
    -                    continue
    -            else:
    -                if ("SUCCESS" in msg):
    -                    answer += msg
    -                    stop = True
    -                    continue
    -                elif ("ERROR" in msg):
    -                    answer += msg
    -                    stop = True
    -                    #global error
    -                    self.error = self.error + 1 
    -                    continue
    -                elif ("PROGRESS" in msg):
    -                    try:
    -                        self.progress = float(msg.strip('PROGRESS '))
    -                    except:
    -                        self.progress = 0
    -                    continue
    -                else:
    -                    if (command_no == 0):
    -                        print(msg)
    -                    answer += msg
    -        self.S.settimeout(self.timeout)
    -        self.answer.update({"SUCCESS":self.pick(answer, "SUCCESS"), "RESULT":self.pick(answer, "RESULT"), "SDTOUT":self.pick(answer, "STDOUT"), "BASE64":self.pick(answer, "BASE64"), "IMAGE":self.pick(answer, "IMAGE"), "FILE":self.pick(answer, "FILE")})
    -        if (msgType != "*"):
    -            answer = self.pick(answer, msgType)
    -        return answer
    -
    -    def pick(self, answer, res='RESULT'):
    -        picked = ''
    -        for a in answer.split('\n'):
    -            if a.find(res) == 0:
    -                picked += a[1 + len(res):].strip('\r') + '\n'
    -        if len(picked) == 0:
    -            return res + ' not found.'
    -        return picked
    -
    -    def get_answer(self, key):
    -        return self.answer[key]
    -
    -    def save_image(self, imageName):
    -        npTypes = [np.bool_, np.ubyte, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, np.int_, np.uint, np.single, np.double]
    -        imageData = self.answer["BASE64"]
    -        decodedData = base64.b64decode((imageData))
    -        imageHeader = self.answer["IMAGE"].split()
    -        dtype = npTypes[int(imageHeader[4])]
    -        im = np.frombuffer(decodedData, dtype).reshape((int(imageHeader[1]),int(imageHeader[0])))
    -        Image.fromarray(im).save(imageName)
    -
    -    def receive_file(self, fileName):
    -        fileData = self.answer["BASE64"]
    -        decodedFile = base64.b64decode((fileData))
    -        artistFile = open(fileName, "wb")
    -        artistFile.write(decodedFile)
    -        artistFile.close()
    -
    -    def send_file(self, fileName):
    -        outFile = open(fileName, "br")
    -        fileBytes = outFile.read()
    -        encBytes = base64.b64encode((fileBytes))
    -        encString = str(encBytes)
    -        encString = encString.lstrip("b'").rstrip("'")
    -        fileExtension = pathlib.Path(fileName).suffix
    -        com = "::RemoteControl::ReceiveFile " + encString + " " + fileExtension
    -        recAnswer = self.send(com, "RESULT")
    -        return recAnswer
    -
    -

    Methods

    -
    -
    -def connect(self) -
    -
    -
    -
    - -Expand source code - -
    def connect(self):
    -    self.S = socket.socket()                        # Create socket (for TCP)
    -    self.S.connect((self.host, self.port))          # Connect to aRTist
    -    self.S.settimeout(self.timeout)
    -    self.listen(0)
    -    return self
    -
    -
    -
    -def get_answer(self, key) -
    -
    -
    -
    - -Expand source code - -
    def get_answer(self, key):
    -    return self.answer[key]
    -
    -
    -
    -def listen(self, command_no=1, msgType='RESULT') -
    -
    -
    -
    - -Expand source code - -
    def listen(self, command_no=1, msgType="RESULT"):
    -    answer = ""
    -    stop = False
    -    if (command_no == 0):
    -        self.S.settimeout(0.2)
    -    while (not stop):# and ("SUCCESS" not in total) and ("ERROR" not in total):     # Solange server antwortet und nicht "SUCCESS" enthält
    -        try:
    -            msg = self.S.recv(self.bufferSize).decode()
    -        except BaseException as e:
    -            err = e.args[0]
    -            if err == "timed out":
    -                #print("Timeout\n")
    -                answer += "RESULT Timeout\n"
    -                #print(answer)
    -                stop = True
    -                continue
    -        else:
    -            if ("SUCCESS" in msg):
    -                answer += msg
    -                stop = True
    -                continue
    -            elif ("ERROR" in msg):
    -                answer += msg
    -                stop = True
    -                #global error
    -                self.error = self.error + 1 
    -                continue
    -            elif ("PROGRESS" in msg):
    -                try:
    -                    self.progress = float(msg.strip('PROGRESS '))
    -                except:
    -                    self.progress = 0
    -                continue
    -            else:
    -                if (command_no == 0):
    -                    print(msg)
    -                answer += msg
    -    self.S.settimeout(self.timeout)
    -    self.answer.update({"SUCCESS":self.pick(answer, "SUCCESS"), "RESULT":self.pick(answer, "RESULT"), "SDTOUT":self.pick(answer, "STDOUT"), "BASE64":self.pick(answer, "BASE64"), "IMAGE":self.pick(answer, "IMAGE"), "FILE":self.pick(answer, "FILE")})
    -    if (msgType != "*"):
    -        answer = self.pick(answer, msgType)
    -    return answer
    -
    -
    -
    -def pick(self, answer, res='RESULT') -
    -
    -
    -
    - -Expand source code - -
    def pick(self, answer, res='RESULT'):
    -    picked = ''
    -    for a in answer.split('\n'):
    -        if a.find(res) == 0:
    -            picked += a[1 + len(res):].strip('\r') + '\n'
    -    if len(picked) == 0:
    -        return res + ' not found.'
    -    return picked
    -
    -
    -
    -def receive_file(self, fileName) -
    -
    -
    -
    - -Expand source code - -
    def receive_file(self, fileName):
    -    fileData = self.answer["BASE64"]
    -    decodedFile = base64.b64decode((fileData))
    -    artistFile = open(fileName, "wb")
    -    artistFile.write(decodedFile)
    -    artistFile.close()
    -
    -
    -
    -def save_image(self, imageName) -
    -
    -
    -
    - -Expand source code - -
    def save_image(self, imageName):
    -    npTypes = [np.bool_, np.ubyte, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, np.int_, np.uint, np.single, np.double]
    -    imageData = self.answer["BASE64"]
    -    decodedData = base64.b64decode((imageData))
    -    imageHeader = self.answer["IMAGE"].split()
    -    dtype = npTypes[int(imageHeader[4])]
    -    im = np.frombuffer(decodedData, dtype).reshape((int(imageHeader[1]),int(imageHeader[0])))
    -    Image.fromarray(im).save(imageName)
    -
    -
    -
    -def send(self, command, msgType='RESULT') -
    -
    -
    -
    - -Expand source code - -
    def send(self, command, msgType="RESULT"):
    -    c = command + '\n'
    -    self.S.send(c.encode())
    -    return self.listen(msgType=msgType)
    -
    -
    -
    -def send_file(self, fileName) -
    -
    -
    -
    - -Expand source code - -
    def send_file(self, fileName):
    -    outFile = open(fileName, "br")
    -    fileBytes = outFile.read()
    -    encBytes = base64.b64encode((fileBytes))
    -    encString = str(encBytes)
    -    encString = encString.lstrip("b'").rstrip("'")
    -    fileExtension = pathlib.Path(fileName).suffix
    -    com = "::RemoteControl::ReceiveFile " + encString + " " + fileExtension
    -    recAnswer = self.send(com, "RESULT")
    -    return recAnswer
    -
    -
    -
    -
    -
    -
    -
    - -
    - - - \ No newline at end of file diff --git a/docs/templates/head.mako b/docs/templates/head.mako deleted file mode 100644 index 9897e5a..0000000 --- a/docs/templates/head.mako +++ /dev/null @@ -1,25 +0,0 @@ -<%! - from pdoc.html_helpers import minify_css -%> -<%def name="homelink()" filter="minify_css"> - .homelink { - display: block; - font-size: 2em; - font-weight: bold; - color: #555; - padding-bottom: .5em; - border-bottom: 1px solid silver; - } - .homelink:hover { - color: inherit; - } - .homelink img { - max-width:35%; - max-height: 5em; - margin: auto; - margin-bottom: .3em; - } - - - - diff --git a/docs/templates/logo.mako b/docs/templates/logo.mako deleted file mode 100644 index a327aae..0000000 --- a/docs/templates/logo.mako +++ /dev/null @@ -1,5 +0,0 @@ -
    - - artistlib - -
    diff --git a/docs/test.html b/docs/test.html deleted file mode 100644 index 0fe9040..0000000 --- a/docs/test.html +++ /dev/null @@ -1,5 +0,0 @@ - - - This is a second test! - - diff --git a/examples/01_api_example.py b/examples/01_api_example.py index 5ae477c..102cb52 100644 --- a/examples/01_api_example.py +++ b/examples/01_api_example.py @@ -15,8 +15,8 @@ import matplotlib.pyplot as plt from pathlib import Path -from artistlib import API -from artistlib.hardware import XraySource, XrayDetector +from artist_pythonlib import API +from artist_pythonlib.hardware import XraySource, XrayDetector def main(): @@ -59,9 +59,6 @@ def main(): # Make a projection an visualize it in python image = artist_api.get_image() - - artist_api.delete_part('test_object') - print(f'Inserted ID: {new_id}') # change material artist_api.set_material(new_id, 'Al') diff --git a/examples/02_circular_trajectory.py b/examples/02_circular_trajectory.py index 2f09b89..70b114f 100644 --- a/examples/02_circular_trajectory.py +++ b/examples/02_circular_trajectory.py @@ -15,8 +15,8 @@ from matplotlib import pyplot as plt -from artistlib import API -from artistlib.trajectory import circular_trajectory +from artist_pythonlib import API +from artist_pythonlib.trajectory import circular_trajectory NUMBER_OF_PROJECTIONS = 20 diff --git a/examples/04_save_image.py b/examples/04_save_image.py index d83f740..aa34c15 100644 --- a/examples/04_save_image.py +++ b/examples/04_save_image.py @@ -1,4 +1,5 @@ -from artistlib import SAVEMODES, API +from artist_pythonlib import SAVEMODES, API +from artist_pythonlib.common_types import PROJECTIONGEOMETRIES from pathlib import Path def main(): @@ -10,7 +11,7 @@ def main(): save_folder.mkdir(exist_ok=True) # Save image / Save images and load them is fastern than to send the images via the rc connection. - artist_api.save_image(save_folder / 'projection.tif', SAVEMODES.UINT16, save_projection_geometry=True) + artist_api.save_image(save_folder / 'projection.tif', SAVEMODES.UINT16, save_projection_geometry=PROJECTIONGEOMETRIES.THD) if __name__ == '__main__': main() \ No newline at end of file diff --git a/project.toml b/project.toml deleted file mode 100644 index d26117c..0000000 --- a/project.toml +++ /dev/null @@ -1,10 +0,0 @@ -[build-system] -requires = [ - "setuptools>=42", - "versioneer", - "wheel", - "scipy", - "numpy", - "matplotlib -] -build-backend = "setuptools.build_meta" diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..c76afce --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,28 @@ +[project] +name = "artist-pythonlib" +version = "0.1.0" +description = "Add your description here" +readme = "README.md" +authors = [ + { name = "swittl", email = "simon.wittl@th-deg.de" } +] +requires-python = ">=3.10" +dependencies = [ + "matplotlib>=3.9.2", + "numpy>=2.1.3", + "pillow>=11.0.0", + "scipy>=1.14.1", + "thd-json>=0.1.0", +] + +[project.optional-dependencies] +thd = [ + "thd-json", +] + +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[tool.uv.sources] +thd-json = { git = "https://mygit.th-deg.de/roboct/definitions/json_schemas" } diff --git a/setup.py b/setup.py deleted file mode 100644 index 27ce5c4..0000000 --- a/setup.py +++ /dev/null @@ -1,22 +0,0 @@ -from setuptools import setup - -setup(name='artistlib', - version='0.1', - description='THD: aRTist Python library', - author='Simon Wittl', - author_email='simon.wittl@th-deg.de', - license='Apache 2.0', - packages=['artistlib', - 'artistlib.hardware', - 'artistlib.trajectory', - 'artistlib.utility', - 'artistlib.objects'], - classifiers=[ - "Programming Language :: Python :: 3", - "License :: OSI Approved :: Apache Software License", - "Operating System :: OS Independent", - "Natural Language :: English", - "Topic :: Multimedia :: Graphics :: Graphics Conversion" - ], - zip_safe=False) - \ No newline at end of file diff --git a/artistlib/__init__.py b/src/artist_pythonlib/__init__.py similarity index 54% rename from artistlib/__init__.py rename to src/artist_pythonlib/__init__.py index 2586765..0b843ed 100644 --- a/artistlib/__init__.py +++ b/src/artist_pythonlib/__init__.py @@ -4,13 +4,10 @@ .. include:: ./documentation.md """ -__pdoc__ = {'console': False, 'remote_access': False} -from ._version import get_versions as __get_versions + from .remote_connection import Junction from .api import API -from .common_types import SAVEMODES, SOURCETYPES - +from .common_types import SAVEMODES, SOURCETYPES, PROJECTIONGEOMETRIES -__version__ = __get_versions()['version'] diff --git a/artistlib/api.py b/src/artist_pythonlib/api.py similarity index 83% rename from artistlib/api.py rename to src/artist_pythonlib/api.py index c333fc3..9176a52 100644 --- a/artistlib/api.py +++ b/src/artist_pythonlib/api.py @@ -13,15 +13,16 @@ # limitations under the License. from __future__ import annotations -from .remote_connection import Junction, _rc -from .common_types import SAVEMODES - import numpy as np from scipy.spatial.transform import Rotation from pathlib import Path import json +from artist_pythonlib.geometries import projection_geometry, thd_projection_geometry +from artist_pythonlib.common_types import PROJECTIONGEOMETRIES, SAVEMODES +from artist_pythonlib.remote_connection import Junction, _rc + class API(): def __init__(self, remote_control: Junction = None) -> None: @@ -46,7 +47,7 @@ def get_image(self) -> np.ndarray: def save_image(self, save_path: Path, save_mode: SAVEMODES = SAVEMODES.UINT16, - save_projection_geometry: bool = True): + save_projection_geometry: PROJECTIONGEOMETRIES = PROJECTIONGEOMETRIES.NONE): """Save the current scene as projection. The projection geometry can be stored in a .json file. Args: @@ -55,24 +56,38 @@ def save_image(self, save_projection_geometry (bool, optional): Projection geometry of the scene. Stem of save_path is used as path. Defaults to True. """ save_path = save_path.resolve() - if save_projection_geometry: - save_path_json = save_path.parent / (save_path.stem + '.json') + if save_projection_geometry > 0: + + + if save_projection_geometry == PROJECTIONGEOMETRIES.THD: + geom = self.projection_geometry(save_projection_geometry) + + name = f'{save_path.stem}_{geom["header"]["uuid"]}' + save_path = save_path.parent / f'{name}.tif' + save_path_json = save_path.parent / f'{name}.json' + else: + save_path_json = save_path.parent / f'{save_path.stem}.json' + + + with open(str(save_path_json), 'w') as f: - json.dump(self.projection_geometry(), f, indent=4) + json.dump(geom, f, indent=4) + + if save_mode == SAVEMODES.UINT8: self._save_image_uint8(save_path) elif save_mode == SAVEMODES.UINT16: self._save_image_uint16(save_path) elif save_mode == SAVEMODES.FLOAT_TIFF: - self._save_image_float_tiff(save_path, save_projection_geometry) + self._save_image_float_tiff(save_path) elif save_mode == SAVEMODES.FLOAT_RAW: self._save_image_float_raw(save_path) elif save_mode == SAVEMODES.PNG: self._save_image_png(save_path) def _save_image_uint16(self, save_path: Path): - """Saves the current scene as porjection (.tif) and geometry (.json). + """Saves the current scene as projection (.tif) and geometry (.json). Args: save_path (Path): Save path of the projection. @@ -82,7 +97,7 @@ def _save_image_uint16(self, save_path: Path): self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') def _save_image_uint8(self, save_path: Path): - """Saves the current scene as porjection (.tif) and geometry (.json). + """Saves the current scene as projection (.tif) and geometry (.json). Args: save_path (Path): Save path of the projection. @@ -95,23 +110,20 @@ def _save_image_uint8(self, save_path: Path): with open(str(save_path_json), 'w') as f: json.dump(self.projection_geometry(), f, indent=4) - def _save_image_float_tiff(self, save_path: Path, save_projection_geometry: bool = False): - """Saves the current scene as porjection (.tiff) and geometry (.json). + def _save_image_float_tiff(self, save_path: Path): + """Saves the current scene as projection (.tiff) and geometry (.json). Args: save_path (Path): Save path of the projection. """ # self.rc.send('set imgList [Engine::Go]') save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') - save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') # self.rc.send('foreach i $imgList {$i Delete}') - if save_projection_geometry: - with open(str(save_path_json), 'w') as f: - json.dump(self.projection_geometry(), f, indent=4) + def _save_image_float_raw(self, save_path: Path): - """Saves the current scene as porjection (.raw) and geometry (.json). + """Saves the current scene as projection (.raw) and geometry (.json). Args: save_path (Path): Save path of the projection. @@ -125,7 +137,7 @@ def _save_image_float_raw(self, save_path: Path): json.dump(self.projection_geometry(), f, indent=4) def _save_image_png(self, save_path: Path): - """Saves the current scene as porjection (.png) and geometry (.json). + """Saves the current scene as projection (.png) and geometry (.json). Args: save_path (Path): Save path of the projection. @@ -175,7 +187,7 @@ def rotate_from_rotation_matrix(self, id: int | str, rotation_matrix: np.ndarray Args: id (int | str): ID of the Object. - rotation_matrix (np.ndarray): Rotationmatix in world coordinate system. + rotation_matrix (np.ndarray): Rotation matrix in world coordinate system. """ rotation = Rotation.from_matrix(rotation_matrix) euler_scipy = rotation.as_euler("ZXY", degrees=True) @@ -236,18 +248,18 @@ def get_rotation_matrix(self, id: int | str) -> np.ndarray: return rotation def get_orientation(self, id) -> np.ndarray: - """Return the current orientation of the object as quarternion. + """Return the current orientation of the object as quaternion. Args: id (int | str): ID of the Object. Returns: - np.ndarray: Quarternion of the object in the wolrd coordinate system. + np.ndarray: Quaternion of the object in the world coordinate system. """ rotation = Rotation.from_matrix(self.get_rotation_matrix(id)) return rotation.as_quat() - def projection_geometry(self) -> dict: + def projection_geometry(self, mode: PROJECTIONGEOMETRIES = PROJECTIONGEOMETRIES.THD) -> dict: """Returns the current projection geometry of the scene. All positions are in [mm]. Returns: @@ -256,27 +268,11 @@ def projection_geometry(self) -> dict: 'detector_center_orientation_matrix', 'detector_center_orientation_quat', 'detector_count_px' and 'detector_resolution_mm' """ - source_position = np.array(self.get_position('S')) - source_orientation = np.array(self.get_rotation_matrix('S')) - detector_position = np.array(self.get_position('D')) - detector_orientation = np.array(self.get_rotation_matrix('D')) - - detector_resolution = self.get_detector_resolution() - detector_pixel_count = self.get_detector_pixel_count() - - data_dict = dict() - data_dict['focal_spot_position_mm'] = source_position.tolist() - data_dict['focal_spot_orientation_quat'] = Rotation.from_matrix(source_orientation).as_quat().tolist() - data_dict['detector_center_position_mm'] = detector_position.tolist() - data_dict['detector_center_orientation_quat'] = Rotation.from_matrix(detector_orientation).as_quat().tolist() - - data_dict['image_width_px'] = detector_pixel_count.tolist()[0] - data_dict['pixel_pitch_width_mm'] = detector_resolution.tolist()[0] - data_dict['image_height_px'] = detector_pixel_count.tolist()[1] - data_dict['pixel_pitch_height_mm'] = detector_resolution.tolist()[1] - - return data_dict - + if mode == PROJECTIONGEOMETRIES.STANDARD: + return projection_geometry(self) + elif mode == PROJECTIONGEOMETRIES.THD: + return thd_projection_geometry(self) + def get_detector_resolution(self) -> np.ndarray: """Returns the current pixel pitch of the detector as array diff --git a/artistlib/common_types.py b/src/artist_pythonlib/common_types.py similarity index 89% rename from artistlib/common_types.py rename to src/artist_pythonlib/common_types.py index b5b0b92..15c602b 100644 --- a/artistlib/common_types.py +++ b/src/artist_pythonlib/common_types.py @@ -23,4 +23,9 @@ class SAVEMODES(IntEnum): UINT16 = 1 FLOAT_TIFF = 2 FLOAT_RAW = 3 - PNG = 4 \ No newline at end of file + PNG = 4 + +class PROJECTIONGEOMETRIES(IntEnum): + NONE = 0 + STANDARD = 1 + THD = 2 \ No newline at end of file diff --git a/src/artist_pythonlib/geometries/__init__.py b/src/artist_pythonlib/geometries/__init__.py new file mode 100644 index 0000000..e27a357 --- /dev/null +++ b/src/artist_pythonlib/geometries/__init__.py @@ -0,0 +1,2 @@ +from .standard_format import projection_geometry +from .thd_format import thd_projection_geometry \ No newline at end of file diff --git a/src/artist_pythonlib/geometries/standard_format.py b/src/artist_pythonlib/geometries/standard_format.py new file mode 100644 index 0000000..89dabc3 --- /dev/null +++ b/src/artist_pythonlib/geometries/standard_format.py @@ -0,0 +1,35 @@ +from __future__ import annotations + +import numpy as np +from scipy.spatial.transform import Rotation + + +def projection_geometry(api) -> dict: + """Returns the current projection geometry of the scene. All positions are in [mm]. + + Returns: + dict: Dictionary of the projection geometry. Keys are: 'focal_spot_position_mm', + 'focal_spot_orientation_matrix', 'detector_center_position_mm', + 'detector_center_orientation_matrix', 'detector_center_orientation_quat', + 'detector_count_px' and 'detector_resolution_mm' + """ + source_position = np.array(api.get_position('S')) + source_orientation = np.array(api.get_rotation_matrix('S')) + detector_position = np.array(api.get_position('D')) + detector_orientation = np.array(api.get_rotation_matrix('D')) + + detector_resolution = api.get_detector_resolution() + detector_pixel_count = api.get_detector_pixel_count() + + data_dict = dict() + data_dict['focal_spot_position_mm'] = source_position.tolist() + data_dict['focal_spot_orientation_quat'] = Rotation.from_matrix(source_orientation).as_quat().tolist() + data_dict['detector_center_position_mm'] = detector_position.tolist() + data_dict['detector_center_orientation_quat'] = Rotation.from_matrix(detector_orientation).as_quat().tolist() + + data_dict['image_width_px'] = detector_pixel_count.tolist()[0] + data_dict['pixel_pitch_width_mm'] = detector_resolution.tolist()[0] + data_dict['image_height_px'] = detector_pixel_count.tolist()[1] + data_dict['pixel_pitch_height_mm'] = detector_resolution.tolist()[1] + + return data_dict \ No newline at end of file diff --git a/src/artist_pythonlib/geometries/thd_format.py b/src/artist_pythonlib/geometries/thd_format.py new file mode 100644 index 0000000..e7e0911 --- /dev/null +++ b/src/artist_pythonlib/geometries/thd_format.py @@ -0,0 +1,57 @@ +import numpy as np +from scipy.spatial.transform import Rotation +try: + from thd_json.header import generate_header +except ModuleNotFoundError: + from warnings import warn + warn('The optional modules of `thd` is not installed. THD Json geometry is not available.') + + + +def thd_projection_geometry(api) -> dict: + """Returns the current projection geometry of the scene. All positions are in [mm]. + + Returns: + dict: Dictionary of the projection geometry. Keys are: 'focal_spot_position_mm', + 'focal_spot_orientation_matrix', 'detector_center_position_mm', + 'detector_center_orientation_matrix', 'detector_center_orientation_quat', + 'detector_count_px' and 'detector_resolution_mm' + """ + source_position = np.array(api.get_position('S')) + source_orientation = np.array(api.get_rotation_matrix('S')) + detector_position = np.array(api.get_position('D')) + detector_orientation = np.array(api.get_rotation_matrix('D')) + + detector_resolution = api.get_detector_resolution() + detector_pixel_count = api.get_detector_pixel_count() + + data_dict = dict() + header_dict = dict() + projection_geometry = dict() + image = dict() + detector = dict() + + json_header = generate_header() + header_dict['uuid'] = json_header.uuid + header_dict['timestamp'] = json_header.timestamp + + projection_geometry['focal_spot_position_mm'] = source_position.tolist() + projection_geometry['focal_spot_orientation_quat'] = Rotation.from_matrix(source_orientation).as_quat().tolist() + projection_geometry['detector_center_position_mm'] = detector_position.tolist() + projection_geometry['detector_center_orientation_quat'] = Rotation.from_matrix(detector_orientation).as_quat().tolist() + + image['uuid'] = json_header.uuid + image['timestamp'] = json_header.timestamp + image['image_path'] = f'{json_header.uuid}.tif' + + detector['image_width_px'] = detector_pixel_count.tolist()[0] + detector['pixel_pitch_width_mm'] = detector_resolution.tolist()[0] + detector['image_height_px'] = detector_pixel_count.tolist()[1] + detector['pixel_pitch_height_mm'] = detector_resolution.tolist()[1] + + data_dict['projection_geometry'] = projection_geometry + data_dict['image'] = image + data_dict['detector'] = detector + data_dict['header'] = header_dict + + return data_dict \ No newline at end of file diff --git a/artistlib/hardware/__init__.py b/src/artist_pythonlib/hardware/__init__.py similarity index 100% rename from artistlib/hardware/__init__.py rename to src/artist_pythonlib/hardware/__init__.py diff --git a/artistlib/hardware/base_hardware.py b/src/artist_pythonlib/hardware/base_hardware.py similarity index 100% rename from artistlib/hardware/base_hardware.py rename to src/artist_pythonlib/hardware/base_hardware.py diff --git a/artistlib/hardware/xray_detector.py b/src/artist_pythonlib/hardware/xray_detector.py similarity index 96% rename from artistlib/hardware/xray_detector.py rename to src/artist_pythonlib/hardware/xray_detector.py index 1a5cef8..1d3f8a6 100644 --- a/artistlib/hardware/xray_detector.py +++ b/src/artist_pythonlib/hardware/xray_detector.py @@ -13,8 +13,8 @@ # limitations under the License. from __future__ import annotations -from artistlib.api import API -from artistlib.remote_connection import Junction +from artist_pythonlib.api import API +from artist_pythonlib.remote_connection import Junction from .base_hardware import BaseHardware import numpy as np diff --git a/artistlib/hardware/xray_source.py b/src/artist_pythonlib/hardware/xray_source.py similarity index 97% rename from artistlib/hardware/xray_source.py rename to src/artist_pythonlib/hardware/xray_source.py index 07975b6..a7272d2 100644 --- a/artistlib/hardware/xray_source.py +++ b/src/artist_pythonlib/hardware/xray_source.py @@ -14,8 +14,8 @@ from __future__ import annotations -from artistlib.api import API -from artistlib.remote_connection import Junction +from artist_pythonlib.api import API +from artist_pythonlib.remote_connection import Junction from .base_hardware import BaseHardware from ..common_types import SOURCETYPES diff --git a/artistlib/objects/__init__.py b/src/artist_pythonlib/py.typed similarity index 100% rename from artistlib/objects/__init__.py rename to src/artist_pythonlib/py.typed diff --git a/artistlib/remote_connection.py b/src/artist_pythonlib/remote_connection.py similarity index 100% rename from artistlib/remote_connection.py rename to src/artist_pythonlib/remote_connection.py diff --git a/artistlib/trajectory/__init__.py b/src/artist_pythonlib/trajectory/__init__.py similarity index 100% rename from artistlib/trajectory/__init__.py rename to src/artist_pythonlib/trajectory/__init__.py diff --git a/artistlib/trajectory/ct_trajectories.py b/src/artist_pythonlib/trajectory/ct_trajectories.py similarity index 100% rename from artistlib/trajectory/ct_trajectories.py rename to src/artist_pythonlib/trajectory/ct_trajectories.py diff --git a/artistlib/utility/__init__.py b/src/artist_pythonlib/utility/__init__.py similarity index 100% rename from artistlib/utility/__init__.py rename to src/artist_pythonlib/utility/__init__.py diff --git a/artistlib/utility/load_projection.py b/src/artist_pythonlib/utility/load_projection.py similarity index 100% rename from artistlib/utility/load_projection.py rename to src/artist_pythonlib/utility/load_projection.py diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..8debb34 --- /dev/null +++ b/uv.lock @@ -0,0 +1,663 @@ +version = 1 +requires-python = ">=3.10" + +[[package]] +name = "artist-pythonlib" +version = "0.1.0" +source = { editable = "." } +dependencies = [ + { name = "matplotlib" }, + { name = "numpy" }, + { name = "pillow" }, + { name = "scipy" }, + { name = "thd-json" }, +] + +[package.optional-dependencies] +thd = [ + { name = "thd-json" }, +] + +[package.metadata] +requires-dist = [ + { name = "matplotlib", specifier = ">=3.9.2" }, + { name = "numpy", specifier = ">=2.1.3" }, + { name = "pillow", specifier = ">=11.0.0" }, + { name = "scipy", specifier = ">=1.14.1" }, + { name = "thd-json", git = "https://mygit.th-deg.de/roboct/definitions/json_schemas" }, + { name = "thd-json", marker = "extra == 'thd'", git = "https://mygit.th-deg.de/roboct/definitions/json_schemas" }, +] + +[[package]] +name = "attrs" +version = "24.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/fc/0f/aafca9af9315aee06a89ffde799a10a582fe8de76c563ee80bbcdc08b3fb/attrs-24.2.0.tar.gz", hash = "sha256:5cfb1b9148b5b086569baec03f20d7b6bf3bcacc9a42bebf87ffaaca362f6346", size = 792678 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl", hash = "sha256:81921eb96de3191c8258c199618104dd27ac608d9366f5e35d011eae1867ede2", size = 63001 }, +] + +[[package]] +name = "contourpy" +version = "1.3.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/25/c2/fc7193cc5383637ff390a712e88e4ded0452c9fbcf84abe3de5ea3df1866/contourpy-1.3.1.tar.gz", hash = "sha256:dfd97abd83335045a913e3bcc4a09c0ceadbe66580cf573fe961f4a825efa699", size = 13465753 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b2/a3/80937fe3efe0edacf67c9a20b955139a1a622730042c1ea991956f2704ad/contourpy-1.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a045f341a77b77e1c5de31e74e966537bba9f3c4099b35bf4c2e3939dd54cdab", size = 268466 }, + { url = "https://files.pythonhosted.org/packages/82/1d/e3eaebb4aa2d7311528c048350ca8e99cdacfafd99da87bc0a5f8d81f2c2/contourpy-1.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:500360b77259914f7805af7462e41f9cb7ca92ad38e9f94d6c8641b089338124", size = 253314 }, + { url = "https://files.pythonhosted.org/packages/de/f3/d796b22d1a2b587acc8100ba8c07fb7b5e17fde265a7bb05ab967f4c935a/contourpy-1.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2f926efda994cdf3c8d3fdb40b9962f86edbc4457e739277b961eced3d0b4c1", size = 312003 }, + { url = "https://files.pythonhosted.org/packages/bf/f5/0e67902bc4394daee8daa39c81d4f00b50e063ee1a46cb3938cc65585d36/contourpy-1.3.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:adce39d67c0edf383647a3a007de0a45fd1b08dedaa5318404f1a73059c2512b", size = 351896 }, + { url = "https://files.pythonhosted.org/packages/1f/d6/e766395723f6256d45d6e67c13bb638dd1fa9dc10ef912dc7dd3dcfc19de/contourpy-1.3.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:abbb49fb7dac584e5abc6636b7b2a7227111c4f771005853e7d25176daaf8453", size = 320814 }, + { url = "https://files.pythonhosted.org/packages/a9/57/86c500d63b3e26e5b73a28b8291a67c5608d4aa87ebd17bd15bb33c178bc/contourpy-1.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0cffcbede75c059f535725c1680dfb17b6ba8753f0c74b14e6a9c68c29d7ea3", size = 324969 }, + { url = "https://files.pythonhosted.org/packages/b8/62/bb146d1289d6b3450bccc4642e7f4413b92ebffd9bf2e91b0404323704a7/contourpy-1.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:ab29962927945d89d9b293eabd0d59aea28d887d4f3be6c22deaefbb938a7277", size = 1265162 }, + { url = "https://files.pythonhosted.org/packages/18/04/9f7d132ce49a212c8e767042cc80ae390f728060d2eea47058f55b9eff1c/contourpy-1.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:974d8145f8ca354498005b5b981165b74a195abfae9a8129df3e56771961d595", size = 1324328 }, + { url = "https://files.pythonhosted.org/packages/46/23/196813901be3f97c83ababdab1382e13e0edc0bb4e7b49a7bff15fcf754e/contourpy-1.3.1-cp310-cp310-win32.whl", hash = "sha256:ac4578ac281983f63b400f7fe6c101bedc10651650eef012be1ccffcbacf3697", size = 173861 }, + { url = "https://files.pythonhosted.org/packages/e0/82/c372be3fc000a3b2005061ca623a0d1ecd2eaafb10d9e883a2fc8566e951/contourpy-1.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:174e758c66bbc1c8576992cec9599ce8b6672b741b5d336b5c74e35ac382b18e", size = 218566 }, + { url = "https://files.pythonhosted.org/packages/12/bb/11250d2906ee2e8b466b5f93e6b19d525f3e0254ac8b445b56e618527718/contourpy-1.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3e8b974d8db2c5610fb4e76307e265de0edb655ae8169e8b21f41807ccbeec4b", size = 269555 }, + { url = "https://files.pythonhosted.org/packages/67/71/1e6e95aee21a500415f5d2dbf037bf4567529b6a4e986594d7026ec5ae90/contourpy-1.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:20914c8c973f41456337652a6eeca26d2148aa96dd7ac323b74516988bea89fc", size = 254549 }, + { url = "https://files.pythonhosted.org/packages/31/2c/b88986e8d79ac45efe9d8801ae341525f38e087449b6c2f2e6050468a42c/contourpy-1.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:19d40d37c1c3a4961b4619dd9d77b12124a453cc3d02bb31a07d58ef684d3d86", size = 313000 }, + { url = "https://files.pythonhosted.org/packages/c4/18/65280989b151fcf33a8352f992eff71e61b968bef7432fbfde3a364f0730/contourpy-1.3.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:113231fe3825ebf6f15eaa8bc1f5b0ddc19d42b733345eae0934cb291beb88b6", size = 352925 }, + { url = "https://files.pythonhosted.org/packages/f5/c7/5fd0146c93220dbfe1a2e0f98969293b86ca9bc041d6c90c0e065f4619ad/contourpy-1.3.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4dbbc03a40f916a8420e420d63e96a1258d3d1b58cbdfd8d1f07b49fcbd38e85", size = 323693 }, + { url = "https://files.pythonhosted.org/packages/85/fc/7fa5d17daf77306840a4e84668a48ddff09e6bc09ba4e37e85ffc8e4faa3/contourpy-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a04ecd68acbd77fa2d39723ceca4c3197cb2969633836ced1bea14e219d077c", size = 326184 }, + { url = "https://files.pythonhosted.org/packages/ef/e7/104065c8270c7397c9571620d3ab880558957216f2b5ebb7e040f85eeb22/contourpy-1.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c414fc1ed8ee1dbd5da626cf3710c6013d3d27456651d156711fa24f24bd1291", size = 1268031 }, + { url = "https://files.pythonhosted.org/packages/e2/4a/c788d0bdbf32c8113c2354493ed291f924d4793c4a2e85b69e737a21a658/contourpy-1.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:31c1b55c1f34f80557d3830d3dd93ba722ce7e33a0b472cba0ec3b6535684d8f", size = 1325995 }, + { url = "https://files.pythonhosted.org/packages/a6/e6/a2f351a90d955f8b0564caf1ebe4b1451a3f01f83e5e3a414055a5b8bccb/contourpy-1.3.1-cp311-cp311-win32.whl", hash = "sha256:f611e628ef06670df83fce17805c344710ca5cde01edfdc72751311da8585375", size = 174396 }, + { url = "https://files.pythonhosted.org/packages/a8/7e/cd93cab453720a5d6cb75588cc17dcdc08fc3484b9de98b885924ff61900/contourpy-1.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:b2bdca22a27e35f16794cf585832e542123296b4687f9fd96822db6bae17bfc9", size = 219787 }, + { url = "https://files.pythonhosted.org/packages/37/6b/175f60227d3e7f5f1549fcb374592be311293132207e451c3d7c654c25fb/contourpy-1.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0ffa84be8e0bd33410b17189f7164c3589c229ce5db85798076a3fa136d0e509", size = 271494 }, + { url = "https://files.pythonhosted.org/packages/6b/6a/7833cfae2c1e63d1d8875a50fd23371394f540ce809d7383550681a1fa64/contourpy-1.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:805617228ba7e2cbbfb6c503858e626ab528ac2a32a04a2fe88ffaf6b02c32bc", size = 255444 }, + { url = "https://files.pythonhosted.org/packages/7f/b3/7859efce66eaca5c14ba7619791b084ed02d868d76b928ff56890d2d059d/contourpy-1.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ade08d343436a94e633db932e7e8407fe7de8083967962b46bdfc1b0ced39454", size = 307628 }, + { url = "https://files.pythonhosted.org/packages/48/b2/011415f5e3f0a50b1e285a0bf78eb5d92a4df000553570f0851b6e309076/contourpy-1.3.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:47734d7073fb4590b4a40122b35917cd77be5722d80683b249dac1de266aac80", size = 347271 }, + { url = "https://files.pythonhosted.org/packages/84/7d/ef19b1db0f45b151ac78c65127235239a8cf21a59d1ce8507ce03e89a30b/contourpy-1.3.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2ba94a401342fc0f8b948e57d977557fbf4d515f03c67682dd5c6191cb2d16ec", size = 318906 }, + { url = "https://files.pythonhosted.org/packages/ba/99/6794142b90b853a9155316c8f470d2e4821fe6f086b03e372aca848227dd/contourpy-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efa874e87e4a647fd2e4f514d5e91c7d493697127beb95e77d2f7561f6905bd9", size = 323622 }, + { url = "https://files.pythonhosted.org/packages/3c/0f/37d2c84a900cd8eb54e105f4fa9aebd275e14e266736778bb5dccbf3bbbb/contourpy-1.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1bf98051f1045b15c87868dbaea84f92408337d4f81d0e449ee41920ea121d3b", size = 1266699 }, + { url = "https://files.pythonhosted.org/packages/3a/8a/deb5e11dc7d9cc8f0f9c8b29d4f062203f3af230ba83c30a6b161a6effc9/contourpy-1.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:61332c87493b00091423e747ea78200659dc09bdf7fd69edd5e98cef5d3e9a8d", size = 1326395 }, + { url = "https://files.pythonhosted.org/packages/1a/35/7e267ae7c13aaf12322ccc493531f1e7f2eb8fba2927b9d7a05ff615df7a/contourpy-1.3.1-cp312-cp312-win32.whl", hash = "sha256:e914a8cb05ce5c809dd0fe350cfbb4e881bde5e2a38dc04e3afe1b3e58bd158e", size = 175354 }, + { url = "https://files.pythonhosted.org/packages/a1/35/c2de8823211d07e8a79ab018ef03960716c5dff6f4d5bff5af87fd682992/contourpy-1.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:08d9d449a61cf53033612cb368f3a1b26cd7835d9b8cd326647efe43bca7568d", size = 220971 }, + { url = "https://files.pythonhosted.org/packages/9a/e7/de62050dce687c5e96f946a93546910bc67e483fe05324439e329ff36105/contourpy-1.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a761d9ccfc5e2ecd1bf05534eda382aa14c3e4f9205ba5b1684ecfe400716ef2", size = 271548 }, + { url = "https://files.pythonhosted.org/packages/78/4d/c2a09ae014ae984c6bdd29c11e74d3121b25eaa117eca0bb76340efd7e1c/contourpy-1.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:523a8ee12edfa36f6d2a49407f705a6ef4c5098de4f498619787e272de93f2d5", size = 255576 }, + { url = "https://files.pythonhosted.org/packages/ab/8a/915380ee96a5638bda80cd061ccb8e666bfdccea38d5741cb69e6dbd61fc/contourpy-1.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece6df05e2c41bd46776fbc712e0996f7c94e0d0543af1656956d150c4ca7c81", size = 306635 }, + { url = "https://files.pythonhosted.org/packages/29/5c/c83ce09375428298acd4e6582aeb68b1e0d1447f877fa993d9bf6cd3b0a0/contourpy-1.3.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:573abb30e0e05bf31ed067d2f82500ecfdaec15627a59d63ea2d95714790f5c2", size = 345925 }, + { url = "https://files.pythonhosted.org/packages/29/63/5b52f4a15e80c66c8078a641a3bfacd6e07106835682454647aca1afc852/contourpy-1.3.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9fa36448e6a3a1a9a2ba23c02012c43ed88905ec80163f2ffe2421c7192a5d7", size = 318000 }, + { url = "https://files.pythonhosted.org/packages/9a/e2/30ca086c692691129849198659bf0556d72a757fe2769eb9620a27169296/contourpy-1.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ea9924d28fc5586bf0b42d15f590b10c224117e74409dd7a0be3b62b74a501c", size = 322689 }, + { url = "https://files.pythonhosted.org/packages/6b/77/f37812ef700f1f185d348394debf33f22d531e714cf6a35d13d68a7003c7/contourpy-1.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5b75aa69cb4d6f137b36f7eb2ace9280cfb60c55dc5f61c731fdf6f037f958a3", size = 1268413 }, + { url = "https://files.pythonhosted.org/packages/3f/6d/ce84e79cdd128542ebeb268f84abb4b093af78e7f8ec504676673d2675bc/contourpy-1.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:041b640d4ec01922083645a94bb3b2e777e6b626788f4095cf21abbe266413c1", size = 1326530 }, + { url = "https://files.pythonhosted.org/packages/72/22/8282f4eae20c73c89bee7a82a19c4e27af9b57bb602ecaa00713d5bdb54d/contourpy-1.3.1-cp313-cp313-win32.whl", hash = "sha256:36987a15e8ace5f58d4d5da9dca82d498c2bbb28dff6e5d04fbfcc35a9cb3a82", size = 175315 }, + { url = "https://files.pythonhosted.org/packages/e3/d5/28bca491f65312b438fbf076589dcde7f6f966b196d900777f5811b9c4e2/contourpy-1.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:a7895f46d47671fa7ceec40f31fae721da51ad34bdca0bee83e38870b1f47ffd", size = 220987 }, + { url = "https://files.pythonhosted.org/packages/2f/24/a4b285d6adaaf9746e4700932f579f1a7b6f9681109f694cfa233ae75c4e/contourpy-1.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:9ddeb796389dadcd884c7eb07bd14ef12408aaae358f0e2ae24114d797eede30", size = 285001 }, + { url = "https://files.pythonhosted.org/packages/48/1d/fb49a401b5ca4f06ccf467cd6c4f1fd65767e63c21322b29b04ec40b40b9/contourpy-1.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:19c1555a6801c2f084c7ddc1c6e11f02eb6a6016ca1318dd5452ba3f613a1751", size = 268553 }, + { url = "https://files.pythonhosted.org/packages/79/1e/4aef9470d13fd029087388fae750dccb49a50c012a6c8d1d634295caa644/contourpy-1.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:841ad858cff65c2c04bf93875e384ccb82b654574a6d7f30453a04f04af71342", size = 310386 }, + { url = "https://files.pythonhosted.org/packages/b0/34/910dc706ed70153b60392b5305c708c9810d425bde12499c9184a1100888/contourpy-1.3.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4318af1c925fb9a4fb190559ef3eec206845f63e80fb603d47f2d6d67683901c", size = 349806 }, + { url = "https://files.pythonhosted.org/packages/31/3c/faee6a40d66d7f2a87f7102236bf4780c57990dd7f98e5ff29881b1b1344/contourpy-1.3.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:14c102b0eab282427b662cb590f2e9340a9d91a1c297f48729431f2dcd16e14f", size = 321108 }, + { url = "https://files.pythonhosted.org/packages/17/69/390dc9b20dd4bb20585651d7316cc3054b7d4a7b4f8b710b2b698e08968d/contourpy-1.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05e806338bfeaa006acbdeba0ad681a10be63b26e1b17317bfac3c5d98f36cda", size = 327291 }, + { url = "https://files.pythonhosted.org/packages/ef/74/7030b67c4e941fe1e5424a3d988080e83568030ce0355f7c9fc556455b01/contourpy-1.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4d76d5993a34ef3df5181ba3c92fabb93f1eaa5729504fb03423fcd9f3177242", size = 1263752 }, + { url = "https://files.pythonhosted.org/packages/f0/ed/92d86f183a8615f13f6b9cbfc5d4298a509d6ce433432e21da838b4b63f4/contourpy-1.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:89785bb2a1980c1bd87f0cb1517a71cde374776a5f150936b82580ae6ead44a1", size = 1318403 }, + { url = "https://files.pythonhosted.org/packages/b3/0e/c8e4950c77dcfc897c71d61e56690a0a9df39543d2164040301b5df8e67b/contourpy-1.3.1-cp313-cp313t-win32.whl", hash = "sha256:8eb96e79b9f3dcadbad2a3891672f81cdcab7f95b27f28f1c67d75f045b6b4f1", size = 185117 }, + { url = "https://files.pythonhosted.org/packages/c1/31/1ae946f11dfbd229222e6d6ad8e7bd1891d3d48bde5fbf7a0beb9491f8e3/contourpy-1.3.1-cp313-cp313t-win_amd64.whl", hash = "sha256:287ccc248c9e0d0566934e7d606201abd74761b5703d804ff3df8935f523d546", size = 236668 }, + { url = "https://files.pythonhosted.org/packages/3e/4f/e56862e64b52b55b5ddcff4090085521fc228ceb09a88390a2b103dccd1b/contourpy-1.3.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b457d6430833cee8e4b8e9b6f07aa1c161e5e0d52e118dc102c8f9bd7dd060d6", size = 265605 }, + { url = "https://files.pythonhosted.org/packages/b0/2e/52bfeeaa4541889f23d8eadc6386b442ee2470bd3cff9baa67deb2dd5c57/contourpy-1.3.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cb76c1a154b83991a3cbbf0dfeb26ec2833ad56f95540b442c73950af2013750", size = 315040 }, + { url = "https://files.pythonhosted.org/packages/52/94/86bfae441707205634d80392e873295652fc313dfd93c233c52c4dc07874/contourpy-1.3.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:44a29502ca9c7b5ba389e620d44f2fbe792b1fb5734e8b931ad307071ec58c53", size = 218221 }, +] + +[[package]] +name = "cycler" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a9/95/a3dbbb5028f35eafb79008e7522a75244477d2838f38cbb722248dabc2a8/cycler-0.12.1.tar.gz", hash = "sha256:88bb128f02ba341da8ef447245a9e138fae777f6a23943da4540077d3601eb1c", size = 7615 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl", hash = "sha256:85cef7cff222d8644161529808465972e51340599459b8ac3ccbac5a854e0d30", size = 8321 }, +] + +[[package]] +name = "exceptiongroup" +version = "1.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/09/35/2495c4ac46b980e4ca1f6ad6db102322ef3ad2410b79fdde159a4b0f3b92/exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc", size = 28883 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/02/cc/b7e31358aac6ed1ef2bb790a9746ac2c69bcb3c8588b41616914eb106eaf/exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b", size = 16453 }, +] + +[[package]] +name = "fonttools" +version = "4.55.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d7/4e/053fe1b5c0ce346c0a9d0557492c654362bafb14f026eae0d3ee98009152/fonttools-4.55.0.tar.gz", hash = "sha256:7636acc6ab733572d5e7eec922b254ead611f1cdad17be3f0be7418e8bfaca71", size = 3490431 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d8/8c/57600ebff0b2119b725bc11eeea32b17b0220f3fae71b5fff082a1891270/fonttools-4.55.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:51c029d4c0608a21a3d3d169dfc3fb776fde38f00b35ca11fdab63ba10a16f61", size = 2770301 }, + { url = "https://files.pythonhosted.org/packages/02/94/dff7e57a751918b133a303418202b4f43e3dc3c887e2a648089e0463b1a7/fonttools-4.55.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bca35b4e411362feab28e576ea10f11268b1aeed883b9f22ed05675b1e06ac69", size = 2295806 }, + { url = "https://files.pythonhosted.org/packages/09/31/ff18d79d449510850fe4a96c0ba50ee6d0b9b815a6b5a2489d809e9a8db5/fonttools-4.55.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9ce4ba6981e10f7e0ccff6348e9775ce25ffadbee70c9fd1a3737e3e9f5fa74f", size = 4577709 }, + { url = "https://files.pythonhosted.org/packages/c4/03/8136887d1b0b7a9831c7e8e2598c0e5851e31cc2231295769350349a236b/fonttools-4.55.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:31d00f9852a6051dac23294a4cf2df80ced85d1d173a61ba90a3d8f5abc63c60", size = 4633411 }, + { url = "https://files.pythonhosted.org/packages/a7/37/86ac06a7505e57de2daaf0a1cc885b7767c74d376ef2cf82933e8ef79399/fonttools-4.55.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e198e494ca6e11f254bac37a680473a311a88cd40e58f9cc4dc4911dfb686ec6", size = 4572887 }, + { url = "https://files.pythonhosted.org/packages/0d/85/1e429359d1842a104b638433587ff62d9dc8339a8c467787087962502a53/fonttools-4.55.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7208856f61770895e79732e1dcbe49d77bd5783adf73ae35f87fcc267df9db81", size = 4745036 }, + { url = "https://files.pythonhosted.org/packages/81/65/763ac1fe2a3e52220f7a7fd2a5de0c784045e773aa9d299450019ac66f9e/fonttools-4.55.0-cp310-cp310-win32.whl", hash = "sha256:e7e6a352ff9e46e8ef8a3b1fe2c4478f8a553e1b5a479f2e899f9dc5f2055880", size = 2170126 }, + { url = "https://files.pythonhosted.org/packages/3e/67/93939482715e629c4bd6fd1f3d154c1bf45b81ee383f50e44d31fa542f83/fonttools-4.55.0-cp310-cp310-win_amd64.whl", hash = "sha256:636caaeefe586d7c84b5ee0734c1a5ab2dae619dc21c5cf336f304ddb8f6001b", size = 2213882 }, + { url = "https://files.pythonhosted.org/packages/17/50/75461e050ded02b9eaa8097df52c2a8752cf4c24db8b44b150755b76c8f1/fonttools-4.55.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:fa34aa175c91477485c44ddfbb51827d470011e558dfd5c7309eb31bef19ec51", size = 2771444 }, + { url = "https://files.pythonhosted.org/packages/de/5e/98130db3770e8d12f70aa61f2555c32284d4e9c592862469d32b7ee48626/fonttools-4.55.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:37dbb3fdc2ef7302d3199fb12468481cbebaee849e4b04bc55b77c24e3c49189", size = 2296439 }, + { url = "https://files.pythonhosted.org/packages/17/35/36fe271296fe7624811f5261a0662155e075b43b79ffacea85a03f36593d/fonttools-4.55.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b5263d8e7ef3c0ae87fbce7f3ec2f546dc898d44a337e95695af2cd5ea21a967", size = 4883141 }, + { url = "https://files.pythonhosted.org/packages/47/2b/9bf7527260d265281dd812951aa22f3d1c331bcc91e86e7038dc6b9737cb/fonttools-4.55.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f307f6b5bf9e86891213b293e538d292cd1677e06d9faaa4bf9c086ad5f132f6", size = 4931050 }, + { url = "https://files.pythonhosted.org/packages/0b/7b/7324d3aa8424c71b63ba2e76eb4a46d6947e23065996e755c1682e666f42/fonttools-4.55.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:f0a4b52238e7b54f998d6a56b46a2c56b59c74d4f8a6747fb9d4042190f37cd3", size = 4894154 }, + { url = "https://files.pythonhosted.org/packages/2c/53/a54926be69e43d277877106a6cbfab467cb02f9c756258c7c9932e8eb382/fonttools-4.55.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3e569711464f777a5d4ef522e781dc33f8095ab5efd7548958b36079a9f2f88c", size = 5064715 }, + { url = "https://files.pythonhosted.org/packages/0c/f7/9602868af9a2dfc4659637a752da8691655e81a2d6138231dcaa1efe8840/fonttools-4.55.0-cp311-cp311-win32.whl", hash = "sha256:2b3ab90ec0f7b76c983950ac601b58949f47aca14c3f21eed858b38d7ec42b05", size = 2169536 }, + { url = "https://files.pythonhosted.org/packages/30/57/9e2ddd16ad84ab26616ae4346b3b15e9a50669ca1b442cbe760af073807c/fonttools-4.55.0-cp311-cp311-win_amd64.whl", hash = "sha256:aa046f6a63bb2ad521004b2769095d4c9480c02c1efa7d7796b37826508980b6", size = 2215265 }, + { url = "https://files.pythonhosted.org/packages/ec/79/38209f8f6235021b6209147ec7b2f748afde65c59c6274ac96fef3912094/fonttools-4.55.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:838d2d8870f84fc785528a692e724f2379d5abd3fc9dad4d32f91cf99b41e4a7", size = 2765205 }, + { url = "https://files.pythonhosted.org/packages/e3/07/434a21eab80524613c9753db2ff21d6bc3cf264412d8833a85022fd39088/fonttools-4.55.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f46b863d74bab7bb0d395f3b68d3f52a03444964e67ce5c43ce43a75efce9246", size = 2293908 }, + { url = "https://files.pythonhosted.org/packages/c8/63/aa3274d9be36aaaef8c087e413cbc1dd682ff94776a82c111bad88482947/fonttools-4.55.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33b52a9cfe4e658e21b1f669f7309b4067910321757fec53802ca8f6eae96a5a", size = 4795901 }, + { url = "https://files.pythonhosted.org/packages/fc/0b/dbe13f2c8d745ffdf5c2bc25391263927d4ec2b927e44d5d5f70cd372873/fonttools-4.55.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:732a9a63d6ea4a81b1b25a1f2e5e143761b40c2e1b79bb2b68e4893f45139a40", size = 4879252 }, + { url = "https://files.pythonhosted.org/packages/46/85/eefb400ec66e9e7c159d13c72aba473d9c2a0c556d812b0916418aa9019e/fonttools-4.55.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7dd91ac3fcb4c491bb4763b820bcab6c41c784111c24172616f02f4bc227c17d", size = 4773177 }, + { url = "https://files.pythonhosted.org/packages/93/75/f06d175df4d7dbad97061c8698210ce4231cce9aa56cc263f3b6b5340540/fonttools-4.55.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1f0e115281a32ff532118aa851ef497a1b7cda617f4621c1cdf81ace3e36fb0c", size = 5032809 }, + { url = "https://files.pythonhosted.org/packages/78/eb/f3520ba63b5e4a034f2bfd34d8ab32eb95a1bf37a1f792ea48461fba08f6/fonttools-4.55.0-cp312-cp312-win32.whl", hash = "sha256:6c99b5205844f48a05cb58d4a8110a44d3038c67ed1d79eb733c4953c628b0f6", size = 2157762 }, + { url = "https://files.pythonhosted.org/packages/aa/d1/5f007861cab890f2a35a19a1d2a2815655ec10b0ea7fd881b1d3aaab0076/fonttools-4.55.0-cp312-cp312-win_amd64.whl", hash = "sha256:f8c8c76037d05652510ae45be1cd8fb5dd2fd9afec92a25374ac82255993d57c", size = 2203746 }, + { url = "https://files.pythonhosted.org/packages/c3/87/a669ac26c6077e37ffb06abf29c5571789eefe518d06c52df392181ee694/fonttools-4.55.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8118dc571921dc9e4b288d9cb423ceaf886d195a2e5329cc427df82bba872cd9", size = 2752519 }, + { url = "https://files.pythonhosted.org/packages/0c/e9/4822ad238fe215133c7df20f1cdb1a58cfb634a31523e77ff0fb2033970a/fonttools-4.55.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:01124f2ca6c29fad4132d930da69158d3f49b2350e4a779e1efbe0e82bd63f6c", size = 2286819 }, + { url = "https://files.pythonhosted.org/packages/3e/a4/d7941c3897129e60fe68d20e4819fda4d0c4858d77badae0e80ca6440b36/fonttools-4.55.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:81ffd58d2691f11f7c8438796e9f21c374828805d33e83ff4b76e4635633674c", size = 4770382 }, + { url = "https://files.pythonhosted.org/packages/31/cf/c51ea1348f9fba9c627439afad9dee0090040809ab431f4422b5bfdda34c/fonttools-4.55.0-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5435e5f1eb893c35c2bc2b9cd3c9596b0fcb0a59e7a14121562986dd4c47b8dd", size = 4858336 }, + { url = "https://files.pythonhosted.org/packages/73/be/36c1fe0e5c9a96b068ddd7e82001243bbe7fe12549c8d14e1bd025bf40c9/fonttools-4.55.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d12081729280c39d001edd0f4f06d696014c26e6e9a0a55488fabc37c28945e4", size = 4756072 }, + { url = "https://files.pythonhosted.org/packages/5c/18/6dd381c29f215a017f79aa9fea0722424a0046b47991c4390a78ff87ce0c/fonttools-4.55.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7ad1f1b98ab6cb927ab924a38a8649f1ffd7525c75fe5b594f5dab17af70e18", size = 5008668 }, + { url = "https://files.pythonhosted.org/packages/b8/95/316f20092b389b927dba1d1dccd3f541853f96e707e210f1b9f4e7bacdd5/fonttools-4.55.0-cp313-cp313-win32.whl", hash = "sha256:abe62987c37630dca69a104266277216de1023cf570c1643bb3a19a9509e7a1b", size = 2155841 }, + { url = "https://files.pythonhosted.org/packages/35/ca/b4638aa3e446184892e2f9cc8ef44bb506f47fea04580df7fb84f5a4363d/fonttools-4.55.0-cp313-cp313-win_amd64.whl", hash = "sha256:2863555ba90b573e4201feaf87a7e71ca3b97c05aa4d63548a4b69ea16c9e998", size = 2200587 }, + { url = "https://files.pythonhosted.org/packages/b4/4a/786589606d4989cb34d8bc766cd687d955aaf3039c367fe7104bcf82dc98/fonttools-4.55.0-py3-none-any.whl", hash = "sha256:12db5888cd4dd3fcc9f0ee60c6edd3c7e1fd44b7dd0f31381ea03df68f8a153f", size = 1100249 }, +] + +[[package]] +name = "hypothesis" +version = "6.119.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "sortedcontainers" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a5/6f/98262d753772030d140d8cd04eadebac545ba4945702f4471decc37b8cb5/hypothesis-6.119.3.tar.gz", hash = "sha256:1403676d95bc9f118a30ce2c97fcbdd28dd99f3a1ffe3456970d98a56b370f36", size = 412497 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/9d/32e2277a2dbc48b687f4acedbc6421c33a5f03177c8cb0d262d5ffc2ccf3/hypothesis-6.119.3-py3-none-any.whl", hash = "sha256:dff13689c4ceb0d84d92e0309fca3ccc1b547ac30552037c712a9080eb75cd05", size = 473632 }, +] + +[[package]] +name = "hypothesis-jsonschema" +version = "0.23.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "hypothesis" }, + { name = "jsonschema" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/4f/ad/2073dd29d8463a92c243d0c298370e50e0d4082bc67f156dc613634d0ec4/hypothesis-jsonschema-0.23.1.tar.gz", hash = "sha256:f4ac032024342a4149a10253984f5a5736b82b3fe2afb0888f3834a31153f215", size = 42896 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/17/44/635a8d2add845c9a2d99a93a379df77f7e70829f0a1d7d5a6998b61f9d01/hypothesis_jsonschema-0.23.1-py3-none-any.whl", hash = "sha256:a4d74d9516dd2784fbbae82e009f62486c9104ac6f4e3397091d98a1d5ee94a2", size = 29200 }, +] + +[[package]] +name = "json-schema" +version = "0.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2a/04/855eecfdd379ff774ce86770808c6663ad4fdf14c43ed4e6fd7156aa5cf9/json_schema-0.3.tar.gz", hash = "sha256:a164efbb405f535615e58aff191b55fbfdad61d2ff0e7bfce6acf086358ca4b3", size = 5425 } + +[[package]] +name = "jsonschema" +version = "4.23.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "jsonschema-specifications" }, + { name = "referencing" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/2e/03362ee4034a4c917f697890ccd4aec0800ccf9ded7f511971c75451deec/jsonschema-4.23.0.tar.gz", hash = "sha256:d71497fef26351a33265337fa77ffeb82423f3ea21283cd9467bb03999266bc4", size = 325778 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/69/4a/4f9dbeb84e8850557c02365a0eee0649abe5eb1d84af92a25731c6c0f922/jsonschema-4.23.0-py3-none-any.whl", hash = "sha256:fbadb6f8b144a8f8cf9f0b89ba94501d143e50411a1278633f56a7acf7fd5566", size = 88462 }, +] + +[[package]] +name = "jsonschema-specifications" +version = "2024.10.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "referencing" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/10/db/58f950c996c793472e336ff3655b13fbcf1e3b359dcf52dcf3ed3b52c352/jsonschema_specifications-2024.10.1.tar.gz", hash = "sha256:0f38b83639958ce1152d02a7f062902c41c8fd20d558b0c34344292d417ae272", size = 15561 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/0f/8910b19ac0670a0f80ce1008e5e751c4a57e14d2c4c13a482aa6079fa9d6/jsonschema_specifications-2024.10.1-py3-none-any.whl", hash = "sha256:a09a0680616357d9a0ecf05c12ad234479f549239d0f5b55f3deea67475da9bf", size = 18459 }, +] + +[[package]] +name = "kiwisolver" +version = "1.4.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/85/4d/2255e1c76304cbd60b48cee302b66d1dde4468dc5b1160e4b7cb43778f2a/kiwisolver-1.4.7.tar.gz", hash = "sha256:9893ff81bd7107f7b685d3017cc6583daadb4fc26e4a888350df530e41980a60", size = 97286 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/97/14/fc943dd65268a96347472b4fbe5dcc2f6f55034516f80576cd0dd3a8930f/kiwisolver-1.4.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:8a9c83f75223d5e48b0bc9cb1bf2776cf01563e00ade8775ffe13b0b6e1af3a6", size = 122440 }, + { url = "https://files.pythonhosted.org/packages/1e/46/e68fed66236b69dd02fcdb506218c05ac0e39745d696d22709498896875d/kiwisolver-1.4.7-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58370b1ffbd35407444d57057b57da5d6549d2d854fa30249771775c63b5fe17", size = 65758 }, + { url = "https://files.pythonhosted.org/packages/ef/fa/65de49c85838681fc9cb05de2a68067a683717321e01ddafb5b8024286f0/kiwisolver-1.4.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aa0abdf853e09aff551db11fce173e2177d00786c688203f52c87ad7fcd91ef9", size = 64311 }, + { url = "https://files.pythonhosted.org/packages/42/9c/cc8d90f6ef550f65443bad5872ffa68f3dee36de4974768628bea7c14979/kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:8d53103597a252fb3ab8b5845af04c7a26d5e7ea8122303dd7a021176a87e8b9", size = 1637109 }, + { url = "https://files.pythonhosted.org/packages/55/91/0a57ce324caf2ff5403edab71c508dd8f648094b18cfbb4c8cc0fde4a6ac/kiwisolver-1.4.7-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:88f17c5ffa8e9462fb79f62746428dd57b46eb931698e42e990ad63103f35e6c", size = 1617814 }, + { url = "https://files.pythonhosted.org/packages/12/5d/c36140313f2510e20207708adf36ae4919416d697ee0236b0ddfb6fd1050/kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:88a9ca9c710d598fd75ee5de59d5bda2684d9db36a9f50b6125eaea3969c2599", size = 1400881 }, + { url = "https://files.pythonhosted.org/packages/56/d0/786e524f9ed648324a466ca8df86298780ef2b29c25313d9a4f16992d3cf/kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f4d742cb7af1c28303a51b7a27aaee540e71bb8e24f68c736f6f2ffc82f2bf05", size = 1512972 }, + { url = "https://files.pythonhosted.org/packages/67/5a/77851f2f201e6141d63c10a0708e996a1363efaf9e1609ad0441b343763b/kiwisolver-1.4.7-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e28c7fea2196bf4c2f8d46a0415c77a1c480cc0724722f23d7410ffe9842c407", size = 1444787 }, + { url = "https://files.pythonhosted.org/packages/06/5f/1f5eaab84355885e224a6fc8d73089e8713dc7e91c121f00b9a1c58a2195/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e968b84db54f9d42046cf154e02911e39c0435c9801681e3fc9ce8a3c4130278", size = 2199212 }, + { url = "https://files.pythonhosted.org/packages/b5/28/9152a3bfe976a0ae21d445415defc9d1cd8614b2910b7614b30b27a47270/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:0c18ec74c0472de033e1bebb2911c3c310eef5649133dd0bedf2a169a1b269e5", size = 2346399 }, + { url = "https://files.pythonhosted.org/packages/26/f6/453d1904c52ac3b400f4d5e240ac5fec25263716723e44be65f4d7149d13/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:8f0ea6da6d393d8b2e187e6a5e3fb81f5862010a40c3945e2c6d12ae45cfb2ad", size = 2308688 }, + { url = "https://files.pythonhosted.org/packages/5a/9a/d4968499441b9ae187e81745e3277a8b4d7c60840a52dc9d535a7909fac3/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:f106407dda69ae456dd1227966bf445b157ccc80ba0dff3802bb63f30b74e895", size = 2445493 }, + { url = "https://files.pythonhosted.org/packages/07/c9/032267192e7828520dacb64dfdb1d74f292765f179e467c1cba97687f17d/kiwisolver-1.4.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:84ec80df401cfee1457063732d90022f93951944b5b58975d34ab56bb150dfb3", size = 2262191 }, + { url = "https://files.pythonhosted.org/packages/6c/ad/db0aedb638a58b2951da46ddaeecf204be8b4f5454df020d850c7fa8dca8/kiwisolver-1.4.7-cp310-cp310-win32.whl", hash = "sha256:71bb308552200fb2c195e35ef05de12f0c878c07fc91c270eb3d6e41698c3bcc", size = 46644 }, + { url = "https://files.pythonhosted.org/packages/12/ca/d0f7b7ffbb0be1e7c2258b53554efec1fd652921f10d7d85045aff93ab61/kiwisolver-1.4.7-cp310-cp310-win_amd64.whl", hash = "sha256:44756f9fd339de0fb6ee4f8c1696cfd19b2422e0d70b4cefc1cc7f1f64045a8c", size = 55877 }, + { url = "https://files.pythonhosted.org/packages/97/6c/cfcc128672f47a3e3c0d918ecb67830600078b025bfc32d858f2e2d5c6a4/kiwisolver-1.4.7-cp310-cp310-win_arm64.whl", hash = "sha256:78a42513018c41c2ffd262eb676442315cbfe3c44eed82385c2ed043bc63210a", size = 48347 }, + { url = "https://files.pythonhosted.org/packages/e9/44/77429fa0a58f941d6e1c58da9efe08597d2e86bf2b2cce6626834f49d07b/kiwisolver-1.4.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:d2b0e12a42fb4e72d509fc994713d099cbb15ebf1103545e8a45f14da2dfca54", size = 122442 }, + { url = "https://files.pythonhosted.org/packages/e5/20/8c75caed8f2462d63c7fd65e16c832b8f76cda331ac9e615e914ee80bac9/kiwisolver-1.4.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2a8781ac3edc42ea4b90bc23e7d37b665d89423818e26eb6df90698aa2287c95", size = 65762 }, + { url = "https://files.pythonhosted.org/packages/f4/98/fe010f15dc7230f45bc4cf367b012d651367fd203caaa992fd1f5963560e/kiwisolver-1.4.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:46707a10836894b559e04b0fd143e343945c97fd170d69a2d26d640b4e297935", size = 64319 }, + { url = "https://files.pythonhosted.org/packages/8b/1b/b5d618f4e58c0675654c1e5051bcf42c776703edb21c02b8c74135541f60/kiwisolver-1.4.7-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef97b8df011141c9b0f6caf23b29379f87dd13183c978a30a3c546d2c47314cb", size = 1334260 }, + { url = "https://files.pythonhosted.org/packages/b8/01/946852b13057a162a8c32c4c8d2e9ed79f0bb5d86569a40c0b5fb103e373/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ab58c12a2cd0fc769089e6d38466c46d7f76aced0a1f54c77652446733d2d02", size = 1426589 }, + { url = "https://files.pythonhosted.org/packages/70/d1/c9f96df26b459e15cf8a965304e6e6f4eb291e0f7a9460b4ad97b047561e/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:803b8e1459341c1bb56d1c5c010406d5edec8a0713a0945851290a7930679b51", size = 1541080 }, + { url = "https://files.pythonhosted.org/packages/d3/73/2686990eb8b02d05f3de759d6a23a4ee7d491e659007dd4c075fede4b5d0/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f9a9e8a507420fe35992ee9ecb302dab68550dedc0da9e2880dd88071c5fb052", size = 1470049 }, + { url = "https://files.pythonhosted.org/packages/a7/4b/2db7af3ed3af7c35f388d5f53c28e155cd402a55432d800c543dc6deb731/kiwisolver-1.4.7-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:18077b53dc3bb490e330669a99920c5e6a496889ae8c63b58fbc57c3d7f33a18", size = 1426376 }, + { url = "https://files.pythonhosted.org/packages/05/83/2857317d04ea46dc5d115f0df7e676997bbd968ced8e2bd6f7f19cfc8d7f/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6af936f79086a89b3680a280c47ea90b4df7047b5bdf3aa5c524bbedddb9e545", size = 2222231 }, + { url = "https://files.pythonhosted.org/packages/0d/b5/866f86f5897cd4ab6d25d22e403404766a123f138bd6a02ecb2cdde52c18/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:3abc5b19d24af4b77d1598a585b8a719beb8569a71568b66f4ebe1fb0449460b", size = 2368634 }, + { url = "https://files.pythonhosted.org/packages/c1/ee/73de8385403faba55f782a41260210528fe3273d0cddcf6d51648202d6d0/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:933d4de052939d90afbe6e9d5273ae05fb836cc86c15b686edd4b3560cc0ee36", size = 2329024 }, + { url = "https://files.pythonhosted.org/packages/a1/e7/cd101d8cd2cdfaa42dc06c433df17c8303d31129c9fdd16c0ea37672af91/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:65e720d2ab2b53f1f72fb5da5fb477455905ce2c88aaa671ff0a447c2c80e8e3", size = 2468484 }, + { url = "https://files.pythonhosted.org/packages/e1/72/84f09d45a10bc57a40bb58b81b99d8f22b58b2040c912b7eb97ebf625bf2/kiwisolver-1.4.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3bf1ed55088f214ba6427484c59553123fdd9b218a42bbc8c6496d6754b1e523", size = 2284078 }, + { url = "https://files.pythonhosted.org/packages/d2/d4/71828f32b956612dc36efd7be1788980cb1e66bfb3706e6dec9acad9b4f9/kiwisolver-1.4.7-cp311-cp311-win32.whl", hash = "sha256:4c00336b9dd5ad96d0a558fd18a8b6f711b7449acce4c157e7343ba92dd0cf3d", size = 46645 }, + { url = "https://files.pythonhosted.org/packages/a1/65/d43e9a20aabcf2e798ad1aff6c143ae3a42cf506754bcb6a7ed8259c8425/kiwisolver-1.4.7-cp311-cp311-win_amd64.whl", hash = "sha256:929e294c1ac1e9f615c62a4e4313ca1823ba37326c164ec720a803287c4c499b", size = 56022 }, + { url = "https://files.pythonhosted.org/packages/35/b3/9f75a2e06f1b4ca00b2b192bc2b739334127d27f1d0625627ff8479302ba/kiwisolver-1.4.7-cp311-cp311-win_arm64.whl", hash = "sha256:e33e8fbd440c917106b237ef1a2f1449dfbb9b6f6e1ce17c94cd6a1e0d438376", size = 48536 }, + { url = "https://files.pythonhosted.org/packages/97/9c/0a11c714cf8b6ef91001c8212c4ef207f772dd84540104952c45c1f0a249/kiwisolver-1.4.7-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:5360cc32706dab3931f738d3079652d20982511f7c0ac5711483e6eab08efff2", size = 121808 }, + { url = "https://files.pythonhosted.org/packages/f2/d8/0fe8c5f5d35878ddd135f44f2af0e4e1d379e1c7b0716f97cdcb88d4fd27/kiwisolver-1.4.7-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:942216596dc64ddb25adb215c3c783215b23626f8d84e8eff8d6d45c3f29f75a", size = 65531 }, + { url = "https://files.pythonhosted.org/packages/80/c5/57fa58276dfdfa612241d640a64ca2f76adc6ffcebdbd135b4ef60095098/kiwisolver-1.4.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:48b571ecd8bae15702e4f22d3ff6a0f13e54d3d00cd25216d5e7f658242065ee", size = 63894 }, + { url = "https://files.pythonhosted.org/packages/8b/e9/26d3edd4c4ad1c5b891d8747a4f81b1b0aba9fb9721de6600a4adc09773b/kiwisolver-1.4.7-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ad42ba922c67c5f219097b28fae965e10045ddf145d2928bfac2eb2e17673640", size = 1369296 }, + { url = "https://files.pythonhosted.org/packages/b6/67/3f4850b5e6cffb75ec40577ddf54f7b82b15269cc5097ff2e968ee32ea7d/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:612a10bdae23404a72941a0fc8fa2660c6ea1217c4ce0dbcab8a8f6543ea9e7f", size = 1461450 }, + { url = "https://files.pythonhosted.org/packages/52/be/86cbb9c9a315e98a8dc6b1d23c43cffd91d97d49318854f9c37b0e41cd68/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9e838bba3a3bac0fe06d849d29772eb1afb9745a59710762e4ba3f4cb8424483", size = 1579168 }, + { url = "https://files.pythonhosted.org/packages/0f/00/65061acf64bd5fd34c1f4ae53f20b43b0a017a541f242a60b135b9d1e301/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:22f499f6157236c19f4bbbd472fa55b063db77a16cd74d49afe28992dff8c258", size = 1507308 }, + { url = "https://files.pythonhosted.org/packages/21/e4/c0b6746fd2eb62fe702118b3ca0cb384ce95e1261cfada58ff693aeec08a/kiwisolver-1.4.7-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:693902d433cf585133699972b6d7c42a8b9f8f826ebcaf0132ff55200afc599e", size = 1464186 }, + { url = "https://files.pythonhosted.org/packages/0a/0f/529d0a9fffb4d514f2782c829b0b4b371f7f441d61aa55f1de1c614c4ef3/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:4e77f2126c3e0b0d055f44513ed349038ac180371ed9b52fe96a32aa071a5107", size = 2247877 }, + { url = "https://files.pythonhosted.org/packages/d1/e1/66603ad779258843036d45adcbe1af0d1a889a07af4635f8b4ec7dccda35/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:657a05857bda581c3656bfc3b20e353c232e9193eb167766ad2dc58b56504948", size = 2404204 }, + { url = "https://files.pythonhosted.org/packages/8d/61/de5fb1ca7ad1f9ab7970e340a5b833d735df24689047de6ae71ab9d8d0e7/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:4bfa75a048c056a411f9705856abfc872558e33c055d80af6a380e3658766038", size = 2352461 }, + { url = "https://files.pythonhosted.org/packages/ba/d2/0edc00a852e369827f7e05fd008275f550353f1f9bcd55db9363d779fc63/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:34ea1de54beef1c104422d210c47c7d2a4999bdecf42c7b5718fbe59a4cac383", size = 2501358 }, + { url = "https://files.pythonhosted.org/packages/84/15/adc15a483506aec6986c01fb7f237c3aec4d9ed4ac10b756e98a76835933/kiwisolver-1.4.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:90da3b5f694b85231cf93586dad5e90e2d71b9428f9aad96952c99055582f520", size = 2314119 }, + { url = "https://files.pythonhosted.org/packages/36/08/3a5bb2c53c89660863a5aa1ee236912269f2af8762af04a2e11df851d7b2/kiwisolver-1.4.7-cp312-cp312-win32.whl", hash = "sha256:18e0cca3e008e17fe9b164b55735a325140a5a35faad8de92dd80265cd5eb80b", size = 46367 }, + { url = "https://files.pythonhosted.org/packages/19/93/c05f0a6d825c643779fc3c70876bff1ac221f0e31e6f701f0e9578690d70/kiwisolver-1.4.7-cp312-cp312-win_amd64.whl", hash = "sha256:58cb20602b18f86f83a5c87d3ee1c766a79c0d452f8def86d925e6c60fbf7bfb", size = 55884 }, + { url = "https://files.pythonhosted.org/packages/d2/f9/3828d8f21b6de4279f0667fb50a9f5215e6fe57d5ec0d61905914f5b6099/kiwisolver-1.4.7-cp312-cp312-win_arm64.whl", hash = "sha256:f5a8b53bdc0b3961f8b6125e198617c40aeed638b387913bf1ce78afb1b0be2a", size = 48528 }, + { url = "https://files.pythonhosted.org/packages/c4/06/7da99b04259b0f18b557a4effd1b9c901a747f7fdd84cf834ccf520cb0b2/kiwisolver-1.4.7-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:2e6039dcbe79a8e0f044f1c39db1986a1b8071051efba3ee4d74f5b365f5226e", size = 121913 }, + { url = "https://files.pythonhosted.org/packages/97/f5/b8a370d1aa593c17882af0a6f6755aaecd643640c0ed72dcfd2eafc388b9/kiwisolver-1.4.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a1ecf0ac1c518487d9d23b1cd7139a6a65bc460cd101ab01f1be82ecf09794b6", size = 65627 }, + { url = "https://files.pythonhosted.org/packages/2a/fc/6c0374f7503522539e2d4d1b497f5ebad3f8ed07ab51aed2af988dd0fb65/kiwisolver-1.4.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7ab9ccab2b5bd5702ab0803676a580fffa2aa178c2badc5557a84cc943fcf750", size = 63888 }, + { url = "https://files.pythonhosted.org/packages/bf/3e/0b7172793d0f41cae5c923492da89a2ffcd1adf764c16159ca047463ebd3/kiwisolver-1.4.7-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f816dd2277f8d63d79f9c8473a79fe54047bc0467754962840782c575522224d", size = 1369145 }, + { url = "https://files.pythonhosted.org/packages/77/92/47d050d6f6aced2d634258123f2688fbfef8ded3c5baf2c79d94d91f1f58/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf8bcc23ceb5a1b624572a1623b9f79d2c3b337c8c455405ef231933a10da379", size = 1461448 }, + { url = "https://files.pythonhosted.org/packages/9c/1b/8f80b18e20b3b294546a1adb41701e79ae21915f4175f311a90d042301cf/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dea0bf229319828467d7fca8c7c189780aa9ff679c94539eed7532ebe33ed37c", size = 1578750 }, + { url = "https://files.pythonhosted.org/packages/a4/fe/fe8e72f3be0a844f257cadd72689c0848c6d5c51bc1d60429e2d14ad776e/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c06a4c7cf15ec739ce0e5971b26c93638730090add60e183530d70848ebdd34", size = 1507175 }, + { url = "https://files.pythonhosted.org/packages/39/fa/cdc0b6105d90eadc3bee525fecc9179e2b41e1ce0293caaf49cb631a6aaf/kiwisolver-1.4.7-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:913983ad2deb14e66d83c28b632fd35ba2b825031f2fa4ca29675e665dfecbe1", size = 1463963 }, + { url = "https://files.pythonhosted.org/packages/6e/5c/0c03c4e542720c6177d4f408e56d1c8315899db72d46261a4e15b8b33a41/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5337ec7809bcd0f424c6b705ecf97941c46279cf5ed92311782c7c9c2026f07f", size = 2248220 }, + { url = "https://files.pythonhosted.org/packages/3d/ee/55ef86d5a574f4e767df7da3a3a7ff4954c996e12d4fbe9c408170cd7dcc/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4c26ed10c4f6fa6ddb329a5120ba3b6db349ca192ae211e882970bfc9d91420b", size = 2404463 }, + { url = "https://files.pythonhosted.org/packages/0f/6d/73ad36170b4bff4825dc588acf4f3e6319cb97cd1fb3eb04d9faa6b6f212/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:c619b101e6de2222c1fcb0531e1b17bbffbe54294bfba43ea0d411d428618c27", size = 2352842 }, + { url = "https://files.pythonhosted.org/packages/0b/16/fa531ff9199d3b6473bb4d0f47416cdb08d556c03b8bc1cccf04e756b56d/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:073a36c8273647592ea332e816e75ef8da5c303236ec0167196793eb1e34657a", size = 2501635 }, + { url = "https://files.pythonhosted.org/packages/78/7e/aa9422e78419db0cbe75fb86d8e72b433818f2e62e2e394992d23d23a583/kiwisolver-1.4.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:3ce6b2b0231bda412463e152fc18335ba32faf4e8c23a754ad50ffa70e4091ee", size = 2314556 }, + { url = "https://files.pythonhosted.org/packages/a8/b2/15f7f556df0a6e5b3772a1e076a9d9f6c538ce5f05bd590eca8106508e06/kiwisolver-1.4.7-cp313-cp313-win32.whl", hash = "sha256:f4c9aee212bc89d4e13f58be11a56cc8036cabad119259d12ace14b34476fd07", size = 46364 }, + { url = "https://files.pythonhosted.org/packages/0b/db/32e897e43a330eee8e4770bfd2737a9584b23e33587a0812b8e20aac38f7/kiwisolver-1.4.7-cp313-cp313-win_amd64.whl", hash = "sha256:8a3ec5aa8e38fc4c8af308917ce12c536f1c88452ce554027e55b22cbbfbff76", size = 55887 }, + { url = "https://files.pythonhosted.org/packages/c8/a4/df2bdca5270ca85fd25253049eb6708d4127be2ed0e5c2650217450b59e9/kiwisolver-1.4.7-cp313-cp313-win_arm64.whl", hash = "sha256:76c8094ac20ec259471ac53e774623eb62e6e1f56cd8690c67ce6ce4fcb05650", size = 48530 }, + { url = "https://files.pythonhosted.org/packages/ac/59/741b79775d67ab67ced9bb38552da688c0305c16e7ee24bba7a2be253fb7/kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:94252291e3fe68001b1dd747b4c0b3be12582839b95ad4d1b641924d68fd4643", size = 59491 }, + { url = "https://files.pythonhosted.org/packages/58/cc/fb239294c29a5656e99e3527f7369b174dd9cc7c3ef2dea7cb3c54a8737b/kiwisolver-1.4.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:5b7dfa3b546da08a9f622bb6becdb14b3e24aaa30adba66749d38f3cc7ea9706", size = 57648 }, + { url = "https://files.pythonhosted.org/packages/3b/ef/2f009ac1f7aab9f81efb2d837301d255279d618d27b6015780115ac64bdd/kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd3de6481f4ed8b734da5df134cd5a6a64fe32124fe83dde1e5b5f29fe30b1e6", size = 84257 }, + { url = "https://files.pythonhosted.org/packages/81/e1/c64f50987f85b68b1c52b464bb5bf73e71570c0f7782d626d1eb283ad620/kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a91b5f9f1205845d488c928e8570dcb62b893372f63b8b6e98b863ebd2368ff2", size = 80906 }, + { url = "https://files.pythonhosted.org/packages/fd/71/1687c5c0a0be2cee39a5c9c389e546f9c6e215e46b691d00d9f646892083/kiwisolver-1.4.7-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:40fa14dbd66b8b8f470d5fc79c089a66185619d31645f9b0773b88b19f7223c4", size = 79951 }, + { url = "https://files.pythonhosted.org/packages/ea/8b/d7497df4a1cae9367adf21665dd1f896c2a7aeb8769ad77b662c5e2bcce7/kiwisolver-1.4.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:eb542fe7933aa09d8d8f9d9097ef37532a7df6497819d16efe4359890a2f417a", size = 55715 }, +] + +[[package]] +name = "matplotlib" +version = "3.9.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "contourpy" }, + { name = "cycler" }, + { name = "fonttools" }, + { name = "kiwisolver" }, + { name = "numpy" }, + { name = "packaging" }, + { name = "pillow" }, + { name = "pyparsing" }, + { name = "python-dateutil" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9e/d8/3d7f706c69e024d4287c1110d74f7dabac91d9843b99eadc90de9efc8869/matplotlib-3.9.2.tar.gz", hash = "sha256:96ab43906269ca64a6366934106fa01534454a69e471b7bf3d79083981aaab92", size = 36088381 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6a/9d/84eeb82ecdd3ba71b12dd6ab5c820c5cc1e868003ecb3717d41b589ec02a/matplotlib-3.9.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9d78bbc0cbc891ad55b4f39a48c22182e9bdaea7fc0e5dbd364f49f729ca1bbb", size = 7893310 }, + { url = "https://files.pythonhosted.org/packages/36/98/cbacbd30241369d099f9c13a2b6bc3b7068d85214f5b5795e583ac3d8aba/matplotlib-3.9.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:c375cc72229614632c87355366bdf2570c2dac01ac66b8ad048d2dabadf2d0d4", size = 7764089 }, + { url = "https://files.pythonhosted.org/packages/a8/a0/917f3c6d3a8774a3a1502d9f3dfc1456e07c1fa0c211a23b75a69e154180/matplotlib-3.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d94ff717eb2bd0b58fe66380bd8b14ac35f48a98e7c6765117fe67fb7684e64", size = 8192377 }, + { url = "https://files.pythonhosted.org/packages/8d/9d/d06860390f9d154fa884f1740a5456378fb153ff57443c91a4a32bab7092/matplotlib-3.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab68d50c06938ef28681073327795c5db99bb4666214d2d5f880ed11aeaded66", size = 8303983 }, + { url = "https://files.pythonhosted.org/packages/9e/a7/c0e848ed7de0766c605af62d8097472a37f1a81d93e9afe94faa5890f24d/matplotlib-3.9.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:65aacf95b62272d568044531e41de26285d54aec8cb859031f511f84bd8b495a", size = 9083318 }, + { url = "https://files.pythonhosted.org/packages/09/6c/0fa50c001340a45cde44853c116d6551aea741e59a7261c38f473b53553b/matplotlib-3.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:3fd595f34aa8a55b7fc8bf9ebea8aa665a84c82d275190a61118d33fbc82ccae", size = 7819628 }, + { url = "https://files.pythonhosted.org/packages/77/c2/f9d7fe80a8fcce9bb128d1381c6fe41a8d286d7e18395e273002e8e0fa34/matplotlib-3.9.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d8dd059447824eec055e829258ab092b56bb0579fc3164fa09c64f3acd478772", size = 7902925 }, + { url = "https://files.pythonhosted.org/packages/28/ba/8be09886eb56ac04a218a1dc3fa728a5c4cac60b019b4f1687885166da00/matplotlib-3.9.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c797dac8bb9c7a3fd3382b16fe8f215b4cf0f22adccea36f1545a6d7be310b41", size = 7773193 }, + { url = "https://files.pythonhosted.org/packages/e6/9a/5991972a560db3ab621312a7ca5efec339ae2122f25901c0846865c4b72f/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d719465db13267bcef19ea8954a971db03b9f48b4647e3860e4bc8e6ed86610f", size = 8202378 }, + { url = "https://files.pythonhosted.org/packages/01/75/6c7ce560e95714a10fcbb3367d1304975a1a3e620f72af28921b796403f3/matplotlib-3.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8912ef7c2362f7193b5819d17dae8629b34a95c58603d781329712ada83f9447", size = 8314361 }, + { url = "https://files.pythonhosted.org/packages/6e/49/dc7384c6c092958e0b75e754efbd9e52500154939c3d715789cee9fb8a53/matplotlib-3.9.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7741f26a58a240f43bee74965c4882b6c93df3e7eb3de160126d8c8f53a6ae6e", size = 9091428 }, + { url = "https://files.pythonhosted.org/packages/8b/ce/15b0bb2fb29b3d46211d8ca740b96b5232499fc49200b58b8d571292c9a6/matplotlib-3.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:ae82a14dab96fbfad7965403c643cafe6515e386de723e498cf3eeb1e0b70cc7", size = 7829377 }, + { url = "https://files.pythonhosted.org/packages/82/de/54f7f38ce6de79cb77d513bb3eaa4e0b1031e9fd6022214f47943fa53a88/matplotlib-3.9.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:ac43031375a65c3196bee99f6001e7fa5bdfb00ddf43379d3c0609bdca042df9", size = 7892511 }, + { url = "https://files.pythonhosted.org/packages/35/3e/5713b84a02b24b2a4bd4d6673bfc03017e6654e1d8793ece783b7ed4d484/matplotlib-3.9.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:be0fc24a5e4531ae4d8e858a1a548c1fe33b176bb13eff7f9d0d38ce5112a27d", size = 7769370 }, + { url = "https://files.pythonhosted.org/packages/5b/bd/c404502aa1824456d2862dd6b9b0c1917761a51a32f7f83ff8cf94b6d117/matplotlib-3.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf81de2926c2db243c9b2cbc3917619a0fc85796c6ba4e58f541df814bbf83c7", size = 8193260 }, + { url = "https://files.pythonhosted.org/packages/27/75/de5b9cd67648051cae40039da0c8cbc497a0d99acb1a1f3d087cd66d27b7/matplotlib-3.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6ee45bc4245533111ced13f1f2cace1e7f89d1c793390392a80c139d6cf0e6c", size = 8306310 }, + { url = "https://files.pythonhosted.org/packages/de/e3/2976e4e54d7ee76eaf54b7639fdc10a223d05c2bdded7045233e9871e469/matplotlib-3.9.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:306c8dfc73239f0e72ac50e5a9cf19cc4e8e331dd0c54f5e69ca8758550f1e1e", size = 9086717 }, + { url = "https://files.pythonhosted.org/packages/d2/92/c2b9464a0562feb6ae780bdc152364810862e07ef5e6affa2b7686028db2/matplotlib-3.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:5413401594cfaff0052f9d8b1aafc6d305b4bd7c4331dccd18f561ff7e1d3bd3", size = 7832805 }, + { url = "https://files.pythonhosted.org/packages/5c/7f/8932eac316b32f464b8f9069f151294dcd892c8fbde61fe8bcd7ba7f7f7e/matplotlib-3.9.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:18128cc08f0d3cfff10b76baa2f296fc28c4607368a8402de61bb3f2eb33c7d9", size = 7893012 }, + { url = "https://files.pythonhosted.org/packages/90/89/9db9db3dd0ff3e2c49e452236dfe29e60b5586a88f8928ca1d153d0da8b5/matplotlib-3.9.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4876d7d40219e8ae8bb70f9263bcbe5714415acfdf781086601211335e24f8aa", size = 7769810 }, + { url = "https://files.pythonhosted.org/packages/67/26/d2661cdc2e1410b8929c5f12dfd521e4528abfed1b3c3d5a28ac48258b43/matplotlib-3.9.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6d9f07a80deab4bb0b82858a9e9ad53d1382fd122be8cde11080f4e7dfedb38b", size = 8193779 }, + { url = "https://files.pythonhosted.org/packages/95/70/4839eaa672bf4eacc98ebc8d23633e02b6daf39e294e7433c4ab11a689be/matplotlib-3.9.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7c0410f181a531ec4e93bbc27692f2c71a15c2da16766f5ba9761e7ae518413", size = 8306260 }, + { url = "https://files.pythonhosted.org/packages/88/62/7b263b2cb2724b45d3a4f9c8c6137696cc3ef037d44383fb01ac2a9555c2/matplotlib-3.9.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:909645cce2dc28b735674ce0931a4ac94e12f5b13f6bb0b5a5e65e7cea2c192b", size = 9086073 }, + { url = "https://files.pythonhosted.org/packages/b0/6d/3572fe243c74112fef120f0bc86f5edd21f49b60e8322fc7f6a01fe945dd/matplotlib-3.9.2-cp313-cp313-win_amd64.whl", hash = "sha256:f32c7410c7f246838a77d6d1eff0c0f87f3cb0e7c4247aebea71a6d5a68cab49", size = 7833041 }, + { url = "https://files.pythonhosted.org/packages/03/8f/9d505be3eb2f40ec731674fb6b47d10cc3147bbd6a9ea7a08c8da55415c6/matplotlib-3.9.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:37e51dd1c2db16ede9cfd7b5cabdfc818b2c6397c83f8b10e0e797501c963a03", size = 7933657 }, + { url = "https://files.pythonhosted.org/packages/5d/68/44b458b9794bcff2a66921f8c9a8110a50a0bb099bd5f7cabb428a1dc765/matplotlib-3.9.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:b82c5045cebcecd8496a4d694d43f9cc84aeeb49fe2133e036b207abe73f4d30", size = 7799276 }, + { url = "https://files.pythonhosted.org/packages/47/79/8486d4ddcaaf676314b5fb58e8fe19d1a6210a443a7c31fa72d4215fcb87/matplotlib-3.9.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f053c40f94bc51bc03832a41b4f153d83f2062d88c72b5e79997072594e97e51", size = 8221027 }, + { url = "https://files.pythonhosted.org/packages/56/62/72a472181578c3d035dcda0d0fa2e259ba2c4cb91132588a348bb705b70d/matplotlib-3.9.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbe196377a8248972f5cede786d4c5508ed5f5ca4a1e09b44bda889958b33f8c", size = 8329097 }, + { url = "https://files.pythonhosted.org/packages/01/8a/760f7fce66b39f447ad160800619d0bd5d0936d2b4633587116534a4afe0/matplotlib-3.9.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5816b1e1fe8c192cbc013f8f3e3368ac56fbecf02fb41b8f8559303f24c5015e", size = 9093770 }, +] + +[[package]] +name = "numpy" +version = "2.1.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/25/ca/1166b75c21abd1da445b97bf1fa2f14f423c6cfb4fc7c4ef31dccf9f6a94/numpy-2.1.3.tar.gz", hash = "sha256:aa08e04e08aaf974d4458def539dece0d28146d866a39da5639596f4921fd761", size = 20166090 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/80/d572a4737626372915bca41c3afbfec9d173561a39a0a61bacbbfd1dafd4/numpy-2.1.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c894b4305373b9c5576d7a12b473702afdf48ce5369c074ba304cc5ad8730dff", size = 21152472 }, + { url = "https://files.pythonhosted.org/packages/6f/bb/7bfba10c791ae3bb6716da77ad85a82d5fac07fc96fb0023ef0571df9d20/numpy-2.1.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b47fbb433d3260adcd51eb54f92a2ffbc90a4595f8970ee00e064c644ac788f5", size = 13747967 }, + { url = "https://files.pythonhosted.org/packages/da/d6/2df7bde35f0478455f0be5934877b3e5a505f587b00230f54a519a6b55a5/numpy-2.1.3-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:825656d0743699c529c5943554d223c021ff0494ff1442152ce887ef4f7561a1", size = 5354921 }, + { url = "https://files.pythonhosted.org/packages/d1/bb/75b945874f931494891eac6ca06a1764d0e8208791f3addadb2963b83527/numpy-2.1.3-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:6a4825252fcc430a182ac4dee5a505053d262c807f8a924603d411f6718b88fd", size = 6888603 }, + { url = "https://files.pythonhosted.org/packages/68/a7/fde73636f6498dbfa6d82fc336164635fe592f1ad0d13285fcb6267fdc1c/numpy-2.1.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e711e02f49e176a01d0349d82cb5f05ba4db7d5e7e0defd026328e5cfb3226d3", size = 13889862 }, + { url = "https://files.pythonhosted.org/packages/05/db/5d9c91b2e1e2e72be1369278f696356d44975befcae830daf2e667dcb54f/numpy-2.1.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78574ac2d1a4a02421f25da9559850d59457bac82f2b8d7a44fe83a64f770098", size = 16328151 }, + { url = "https://files.pythonhosted.org/packages/3e/6a/7eb732109b53ae64a29e25d7e68eb9d6611037f6354875497008a49e74d3/numpy-2.1.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c7662f0e3673fe4e832fe07b65c50342ea27d989f92c80355658c7f888fcc83c", size = 16704107 }, + { url = "https://files.pythonhosted.org/packages/88/cc/278113b66a1141053cbda6f80e4200c6da06b3079c2d27bda1fde41f2c1f/numpy-2.1.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:fa2d1337dc61c8dc417fbccf20f6d1e139896a30721b7f1e832b2bb6ef4eb6c4", size = 14385789 }, + { url = "https://files.pythonhosted.org/packages/f5/69/eb20f5e1bfa07449bc67574d2f0f7c1e6b335fb41672e43861a7727d85f2/numpy-2.1.3-cp310-cp310-win32.whl", hash = "sha256:72dcc4a35a8515d83e76b58fdf8113a5c969ccd505c8a946759b24e3182d1f23", size = 6536706 }, + { url = "https://files.pythonhosted.org/packages/8e/8b/1c131ab5a94c1086c289c6e1da1d843de9dbd95fe5f5ee6e61904c9518e2/numpy-2.1.3-cp310-cp310-win_amd64.whl", hash = "sha256:ecc76a9ba2911d8d37ac01de72834d8849e55473457558e12995f4cd53e778e0", size = 12864165 }, + { url = "https://files.pythonhosted.org/packages/ad/81/c8167192eba5247593cd9d305ac236847c2912ff39e11402e72ae28a4985/numpy-2.1.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4d1167c53b93f1f5d8a139a742b3c6f4d429b54e74e6b57d0eff40045187b15d", size = 21156252 }, + { url = "https://files.pythonhosted.org/packages/da/74/5a60003fc3d8a718d830b08b654d0eea2d2db0806bab8f3c2aca7e18e010/numpy-2.1.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c80e4a09b3d95b4e1cac08643f1152fa71a0a821a2d4277334c88d54b2219a41", size = 13784119 }, + { url = "https://files.pythonhosted.org/packages/47/7c/864cb966b96fce5e63fcf25e1e4d957fe5725a635e5f11fe03f39dd9d6b5/numpy-2.1.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:576a1c1d25e9e02ed7fa5477f30a127fe56debd53b8d2c89d5578f9857d03ca9", size = 5352978 }, + { url = "https://files.pythonhosted.org/packages/09/ac/61d07930a4993dd9691a6432de16d93bbe6aa4b1c12a5e573d468eefc1ca/numpy-2.1.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:973faafebaae4c0aaa1a1ca1ce02434554d67e628b8d805e61f874b84e136b09", size = 6892570 }, + { url = "https://files.pythonhosted.org/packages/27/2f/21b94664f23af2bb52030653697c685022119e0dc93d6097c3cb45bce5f9/numpy-2.1.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:762479be47a4863e261a840e8e01608d124ee1361e48b96916f38b119cfda04a", size = 13896715 }, + { url = "https://files.pythonhosted.org/packages/7a/f0/80811e836484262b236c684a75dfc4ba0424bc670e765afaa911468d9f39/numpy-2.1.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bc6f24b3d1ecc1eebfbf5d6051faa49af40b03be1aaa781ebdadcbc090b4539b", size = 16339644 }, + { url = "https://files.pythonhosted.org/packages/fa/81/ce213159a1ed8eb7d88a2a6ef4fbdb9e4ffd0c76b866c350eb4e3c37e640/numpy-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:17ee83a1f4fef3c94d16dc1802b998668b5419362c8a4f4e8a491de1b41cc3ee", size = 16712217 }, + { url = "https://files.pythonhosted.org/packages/7d/84/4de0b87d5a72f45556b2a8ee9fc8801e8518ec867fc68260c1f5dcb3903f/numpy-2.1.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15cb89f39fa6d0bdfb600ea24b250e5f1a3df23f901f51c8debaa6a5d122b2f0", size = 14399053 }, + { url = "https://files.pythonhosted.org/packages/7e/1c/e5fabb9ad849f9d798b44458fd12a318d27592d4bc1448e269dec070ff04/numpy-2.1.3-cp311-cp311-win32.whl", hash = "sha256:d9beb777a78c331580705326d2367488d5bc473b49a9bc3036c154832520aca9", size = 6534741 }, + { url = "https://files.pythonhosted.org/packages/1e/48/a9a4b538e28f854bfb62e1dea3c8fea12e90216a276c7777ae5345ff29a7/numpy-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:d89dd2b6da69c4fff5e39c28a382199ddedc3a5be5390115608345dec660b9e2", size = 12869487 }, + { url = "https://files.pythonhosted.org/packages/8a/f0/385eb9970309643cbca4fc6eebc8bb16e560de129c91258dfaa18498da8b/numpy-2.1.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f55ba01150f52b1027829b50d70ef1dafd9821ea82905b63936668403c3b471e", size = 20849658 }, + { url = "https://files.pythonhosted.org/packages/54/4a/765b4607f0fecbb239638d610d04ec0a0ded9b4951c56dc68cef79026abf/numpy-2.1.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:13138eadd4f4da03074851a698ffa7e405f41a0845a6b1ad135b81596e4e9958", size = 13492258 }, + { url = "https://files.pythonhosted.org/packages/bd/a7/2332679479c70b68dccbf4a8eb9c9b5ee383164b161bee9284ac141fbd33/numpy-2.1.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:a6b46587b14b888e95e4a24d7b13ae91fa22386c199ee7b418f449032b2fa3b8", size = 5090249 }, + { url = "https://files.pythonhosted.org/packages/c1/67/4aa00316b3b981a822c7a239d3a8135be2a6945d1fd11d0efb25d361711a/numpy-2.1.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:0fa14563cc46422e99daef53d725d0c326e99e468a9320a240affffe87852564", size = 6621704 }, + { url = "https://files.pythonhosted.org/packages/5e/da/1a429ae58b3b6c364eeec93bf044c532f2ff7b48a52e41050896cf15d5b1/numpy-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8637dcd2caa676e475503d1f8fdb327bc495554e10838019651b76d17b98e512", size = 13606089 }, + { url = "https://files.pythonhosted.org/packages/9e/3e/3757f304c704f2f0294a6b8340fcf2be244038be07da4cccf390fa678a9f/numpy-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2312b2aa89e1f43ecea6da6ea9a810d06aae08321609d8dc0d0eda6d946a541b", size = 16043185 }, + { url = "https://files.pythonhosted.org/packages/43/97/75329c28fea3113d00c8d2daf9bc5828d58d78ed661d8e05e234f86f0f6d/numpy-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a38c19106902bb19351b83802531fea19dee18e5b37b36454f27f11ff956f7fc", size = 16410751 }, + { url = "https://files.pythonhosted.org/packages/ad/7a/442965e98b34e0ae9da319f075b387bcb9a1e0658276cc63adb8c9686f7b/numpy-2.1.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02135ade8b8a84011cbb67dc44e07c58f28575cf9ecf8ab304e51c05528c19f0", size = 14082705 }, + { url = "https://files.pythonhosted.org/packages/ac/b6/26108cf2cfa5c7e03fb969b595c93131eab4a399762b51ce9ebec2332e80/numpy-2.1.3-cp312-cp312-win32.whl", hash = "sha256:e6988e90fcf617da2b5c78902fe8e668361b43b4fe26dbf2d7b0f8034d4cafb9", size = 6239077 }, + { url = "https://files.pythonhosted.org/packages/a6/84/fa11dad3404b7634aaab50733581ce11e5350383311ea7a7010f464c0170/numpy-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:0d30c543f02e84e92c4b1f415b7c6b5326cbe45ee7882b6b77db7195fb971e3a", size = 12566858 }, + { url = "https://files.pythonhosted.org/packages/4d/0b/620591441457e25f3404c8057eb924d04f161244cb8a3680d529419aa86e/numpy-2.1.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:96fe52fcdb9345b7cd82ecd34547fca4321f7656d500eca497eb7ea5a926692f", size = 20836263 }, + { url = "https://files.pythonhosted.org/packages/45/e1/210b2d8b31ce9119145433e6ea78046e30771de3fe353f313b2778142f34/numpy-2.1.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f653490b33e9c3a4c1c01d41bc2aef08f9475af51146e4a7710c450cf9761598", size = 13507771 }, + { url = "https://files.pythonhosted.org/packages/55/44/aa9ee3caee02fa5a45f2c3b95cafe59c44e4b278fbbf895a93e88b308555/numpy-2.1.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dc258a761a16daa791081d026f0ed4399b582712e6fc887a95af09df10c5ca57", size = 5075805 }, + { url = "https://files.pythonhosted.org/packages/78/d6/61de6e7e31915ba4d87bbe1ae859e83e6582ea14c6add07c8f7eefd8488f/numpy-2.1.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:016d0f6f5e77b0f0d45d77387ffa4bb89816b57c835580c3ce8e099ef830befe", size = 6608380 }, + { url = "https://files.pythonhosted.org/packages/3e/46/48bdf9b7241e317e6cf94276fe11ba673c06d1fdf115d8b4ebf616affd1a/numpy-2.1.3-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c181ba05ce8299c7aa3125c27b9c2167bca4a4445b7ce73d5febc411ca692e43", size = 13602451 }, + { url = "https://files.pythonhosted.org/packages/70/50/73f9a5aa0810cdccda9c1d20be3cbe4a4d6ea6bfd6931464a44c95eef731/numpy-2.1.3-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5641516794ca9e5f8a4d17bb45446998c6554704d888f86df9b200e66bdcce56", size = 16039822 }, + { url = "https://files.pythonhosted.org/packages/ad/cd/098bc1d5a5bc5307cfc65ee9369d0ca658ed88fbd7307b0d49fab6ca5fa5/numpy-2.1.3-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:ea4dedd6e394a9c180b33c2c872b92f7ce0f8e7ad93e9585312b0c5a04777a4a", size = 16411822 }, + { url = "https://files.pythonhosted.org/packages/83/a2/7d4467a2a6d984549053b37945620209e702cf96a8bc658bc04bba13c9e2/numpy-2.1.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0df3635b9c8ef48bd3be5f862cf71b0a4716fa0e702155c45067c6b711ddcef", size = 14079598 }, + { url = "https://files.pythonhosted.org/packages/e9/6a/d64514dcecb2ee70bfdfad10c42b76cab657e7ee31944ff7a600f141d9e9/numpy-2.1.3-cp313-cp313-win32.whl", hash = "sha256:50ca6aba6e163363f132b5c101ba078b8cbd3fa92c7865fd7d4d62d9779ac29f", size = 6236021 }, + { url = "https://files.pythonhosted.org/packages/bb/f9/12297ed8d8301a401e7d8eb6b418d32547f1d700ed3c038d325a605421a4/numpy-2.1.3-cp313-cp313-win_amd64.whl", hash = "sha256:747641635d3d44bcb380d950679462fae44f54b131be347d5ec2bce47d3df9ed", size = 12560405 }, + { url = "https://files.pythonhosted.org/packages/a7/45/7f9244cd792e163b334e3a7f02dff1239d2890b6f37ebf9e82cbe17debc0/numpy-2.1.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:996bb9399059c5b82f76b53ff8bb686069c05acc94656bb259b1d63d04a9506f", size = 20859062 }, + { url = "https://files.pythonhosted.org/packages/b1/b4/a084218e7e92b506d634105b13e27a3a6645312b93e1c699cc9025adb0e1/numpy-2.1.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:45966d859916ad02b779706bb43b954281db43e185015df6eb3323120188f9e4", size = 13515839 }, + { url = "https://files.pythonhosted.org/packages/27/45/58ed3f88028dcf80e6ea580311dc3edefdd94248f5770deb980500ef85dd/numpy-2.1.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:baed7e8d7481bfe0874b566850cb0b85243e982388b7b23348c6db2ee2b2ae8e", size = 5116031 }, + { url = "https://files.pythonhosted.org/packages/37/a8/eb689432eb977d83229094b58b0f53249d2209742f7de529c49d61a124a0/numpy-2.1.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f7f672a3388133335589cfca93ed468509cb7b93ba3105fce780d04a6576a0", size = 6629977 }, + { url = "https://files.pythonhosted.org/packages/42/a3/5355ad51ac73c23334c7caaed01adadfda49544f646fcbfbb4331deb267b/numpy-2.1.3-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7aac50327da5d208db2eec22eb11e491e3fe13d22653dce51b0f4109101b408", size = 13575951 }, + { url = "https://files.pythonhosted.org/packages/c4/70/ea9646d203104e647988cb7d7279f135257a6b7e3354ea6c56f8bafdb095/numpy-2.1.3-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4394bc0dbd074b7f9b52024832d16e019decebf86caf909d94f6b3f77a8ee3b6", size = 16022655 }, + { url = "https://files.pythonhosted.org/packages/14/ce/7fc0612903e91ff9d0b3f2eda4e18ef9904814afcae5b0f08edb7f637883/numpy-2.1.3-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:50d18c4358a0a8a53f12a8ba9d772ab2d460321e6a93d6064fc22443d189853f", size = 16399902 }, + { url = "https://files.pythonhosted.org/packages/ef/62/1d3204313357591c913c32132a28f09a26357e33ea3c4e2fe81269e0dca1/numpy-2.1.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:14e253bd43fc6b37af4921b10f6add6925878a42a0c5fe83daee390bca80bc17", size = 14067180 }, + { url = "https://files.pythonhosted.org/packages/24/d7/78a40ed1d80e23a774cb8a34ae8a9493ba1b4271dde96e56ccdbab1620ef/numpy-2.1.3-cp313-cp313t-win32.whl", hash = "sha256:08788d27a5fd867a663f6fc753fd7c3ad7e92747efc73c53bca2f19f8bc06f48", size = 6291907 }, + { url = "https://files.pythonhosted.org/packages/86/09/a5ab407bd7f5f5599e6a9261f964ace03a73e7c6928de906981c31c38082/numpy-2.1.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2564fbdf2b99b3f815f2107c1bbc93e2de8ee655a69c261363a1172a79a257d4", size = 12644098 }, + { url = "https://files.pythonhosted.org/packages/00/e7/8d8bb791b62586cc432ecbb70632b4f23b7b7c88df41878de7528264f6d7/numpy-2.1.3-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:4f2015dfe437dfebbfce7c85c7b53d81ba49e71ba7eadbf1df40c915af75979f", size = 20983893 }, + { url = "https://files.pythonhosted.org/packages/5e/f3/cb8118a044b5007586245a650360c9f5915b2f4232dd7658bb7a63dd1d02/numpy-2.1.3-pp310-pypy310_pp73-macosx_14_0_x86_64.whl", hash = "sha256:3522b0dfe983a575e6a9ab3a4a4dfe156c3e428468ff08ce582b9bb6bd1d71d4", size = 6752501 }, + { url = "https://files.pythonhosted.org/packages/53/f5/365b46439b518d2ec6ebb880cc0edf90f225145dfd4db7958334f7164530/numpy-2.1.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c006b607a865b07cd981ccb218a04fc86b600411d83d6fc261357f1c0966755d", size = 16142601 }, + { url = "https://files.pythonhosted.org/packages/03/c2/d1fee6ba999aa7cd41ca6856937f2baaf604c3eec1565eae63451ec31e5e/numpy-2.1.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:e14e26956e6f1696070788252dcdff11b4aca4c3e8bd166e0df1bb8f315a67cb", size = 12771397 }, +] + +[[package]] +name = "packaging" +version = "24.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d0/63/68dbb6eb2de9cb10ee4c9c14a0148804425e13c4fb20d61cce69f53106da/packaging-24.2.tar.gz", hash = "sha256:c228a6dc5e932d346bc5739379109d49e8853dd8223571c7c5b55260edc0b97f", size = 163950 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/ef/eb23f262cca3c0c4eb7ab1933c3b1f03d021f2c48f54763065b6f0e321be/packaging-24.2-py3-none-any.whl", hash = "sha256:09abb1bccd265c01f4a3aa3f7a7db064b36514d2cba19a2f694fe6150451a759", size = 65451 }, +] + +[[package]] +name = "pillow" +version = "11.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a5/26/0d95c04c868f6bdb0c447e3ee2de5564411845e36a858cfd63766bc7b563/pillow-11.0.0.tar.gz", hash = "sha256:72bacbaf24ac003fea9bff9837d1eedb6088758d41e100c1552930151f677739", size = 46737780 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/98/fb/a6ce6836bd7fd93fbf9144bf54789e02babc27403b50a9e1583ee877d6da/pillow-11.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:6619654954dc4936fcff82db8eb6401d3159ec6be81e33c6000dfd76ae189947", size = 3154708 }, + { url = "https://files.pythonhosted.org/packages/6a/1d/1f51e6e912d8ff316bb3935a8cda617c801783e0b998bf7a894e91d3bd4c/pillow-11.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b3c5ac4bed7519088103d9450a1107f76308ecf91d6dabc8a33a2fcfb18d0fba", size = 2979223 }, + { url = "https://files.pythonhosted.org/packages/90/83/e2077b0192ca8a9ef794dbb74700c7e48384706467067976c2a95a0f40a1/pillow-11.0.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a65149d8ada1055029fcb665452b2814fe7d7082fcb0c5bed6db851cb69b2086", size = 4183167 }, + { url = "https://files.pythonhosted.org/packages/0e/74/467af0146970a98349cdf39e9b79a6cc8a2e7558f2c01c28a7b6b85c5bda/pillow-11.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88a58d8ac0cc0e7f3a014509f0455248a76629ca9b604eca7dc5927cc593c5e9", size = 4283912 }, + { url = "https://files.pythonhosted.org/packages/85/b1/d95d4f7ca3a6c1ae120959605875a31a3c209c4e50f0029dc1a87566cf46/pillow-11.0.0-cp310-cp310-manylinux_2_28_aarch64.whl", hash = "sha256:c26845094b1af3c91852745ae78e3ea47abf3dbcd1cf962f16b9a5fbe3ee8488", size = 4195815 }, + { url = "https://files.pythonhosted.org/packages/41/c3/94f33af0762ed76b5a237c5797e088aa57f2b7fa8ee7932d399087be66a8/pillow-11.0.0-cp310-cp310-manylinux_2_28_x86_64.whl", hash = "sha256:1a61b54f87ab5786b8479f81c4b11f4d61702830354520837f8cc791ebba0f5f", size = 4366117 }, + { url = "https://files.pythonhosted.org/packages/ba/3c/443e7ef01f597497268899e1cca95c0de947c9bbf77a8f18b3c126681e5d/pillow-11.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:674629ff60030d144b7bca2b8330225a9b11c482ed408813924619c6f302fdbb", size = 4278607 }, + { url = "https://files.pythonhosted.org/packages/26/95/1495304448b0081e60c0c5d63f928ef48bb290acee7385804426fa395a21/pillow-11.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:598b4e238f13276e0008299bd2482003f48158e2b11826862b1eb2ad7c768b97", size = 4410685 }, + { url = "https://files.pythonhosted.org/packages/45/da/861e1df971ef0de9870720cb309ca4d553b26a9483ec9be3a7bf1de4a095/pillow-11.0.0-cp310-cp310-win32.whl", hash = "sha256:9a0f748eaa434a41fccf8e1ee7a3eed68af1b690e75328fd7a60af123c193b50", size = 2249185 }, + { url = "https://files.pythonhosted.org/packages/d5/4e/78f7c5202ea2a772a5ab05069c1b82503e6353cd79c7e474d4945f4b82c3/pillow-11.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:a5629742881bcbc1f42e840af185fd4d83a5edeb96475a575f4da50d6ede337c", size = 2566726 }, + { url = "https://files.pythonhosted.org/packages/77/e4/6e84eada35cbcc646fc1870f72ccfd4afacb0fae0c37ffbffe7f5dc24bf1/pillow-11.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:ee217c198f2e41f184f3869f3e485557296d505b5195c513b2bfe0062dc537f1", size = 2254585 }, + { url = "https://files.pythonhosted.org/packages/f0/eb/f7e21b113dd48a9c97d364e0915b3988c6a0b6207652f5a92372871b7aa4/pillow-11.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:1c1d72714f429a521d8d2d018badc42414c3077eb187a59579f28e4270b4b0fc", size = 3154705 }, + { url = "https://files.pythonhosted.org/packages/25/b3/2b54a1d541accebe6bd8b1358b34ceb2c509f51cb7dcda8687362490da5b/pillow-11.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:499c3a1b0d6fc8213519e193796eb1a86a1be4b1877d678b30f83fd979811d1a", size = 2979222 }, + { url = "https://files.pythonhosted.org/packages/20/12/1a41eddad8265c5c19dda8fb6c269ce15ee25e0b9f8f26286e6202df6693/pillow-11.0.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c8b2351c85d855293a299038e1f89db92a2f35e8d2f783489c6f0b2b5f3fe8a3", size = 4190220 }, + { url = "https://files.pythonhosted.org/packages/a9/9b/8a8c4d07d77447b7457164b861d18f5a31ae6418ef5c07f6f878fa09039a/pillow-11.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f4dba50cfa56f910241eb7f883c20f1e7b1d8f7d91c750cd0b318bad443f4d5", size = 4291399 }, + { url = "https://files.pythonhosted.org/packages/fc/e4/130c5fab4a54d3991129800dd2801feeb4b118d7630148cd67f0e6269d4c/pillow-11.0.0-cp311-cp311-manylinux_2_28_aarch64.whl", hash = "sha256:5ddbfd761ee00c12ee1be86c9c0683ecf5bb14c9772ddbd782085779a63dd55b", size = 4202709 }, + { url = "https://files.pythonhosted.org/packages/39/63/b3fc299528d7df1f678b0666002b37affe6b8751225c3d9c12cf530e73ed/pillow-11.0.0-cp311-cp311-manylinux_2_28_x86_64.whl", hash = "sha256:45c566eb10b8967d71bf1ab8e4a525e5a93519e29ea071459ce517f6b903d7fa", size = 4372556 }, + { url = "https://files.pythonhosted.org/packages/c6/a6/694122c55b855b586c26c694937d36bb8d3b09c735ff41b2f315c6e66a10/pillow-11.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b4fd7bd29610a83a8c9b564d457cf5bd92b4e11e79a4ee4716a63c959699b306", size = 4287187 }, + { url = "https://files.pythonhosted.org/packages/ba/a9/f9d763e2671a8acd53d29b1e284ca298bc10a595527f6be30233cdb9659d/pillow-11.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:cb929ca942d0ec4fac404cbf520ee6cac37bf35be479b970c4ffadf2b6a1cad9", size = 4418468 }, + { url = "https://files.pythonhosted.org/packages/6e/0e/b5cbad2621377f11313a94aeb44ca55a9639adabcaaa073597a1925f8c26/pillow-11.0.0-cp311-cp311-win32.whl", hash = "sha256:006bcdd307cc47ba43e924099a038cbf9591062e6c50e570819743f5607404f5", size = 2249249 }, + { url = "https://files.pythonhosted.org/packages/dc/83/1470c220a4ff06cd75fc609068f6605e567ea51df70557555c2ab6516b2c/pillow-11.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:52a2d8323a465f84faaba5236567d212c3668f2ab53e1c74c15583cf507a0291", size = 2566769 }, + { url = "https://files.pythonhosted.org/packages/52/98/def78c3a23acee2bcdb2e52005fb2810ed54305602ec1bfcfab2bda6f49f/pillow-11.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:16095692a253047fe3ec028e951fa4221a1f3ed3d80c397e83541a3037ff67c9", size = 2254611 }, + { url = "https://files.pythonhosted.org/packages/1c/a3/26e606ff0b2daaf120543e537311fa3ae2eb6bf061490e4fea51771540be/pillow-11.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d2c0a187a92a1cb5ef2c8ed5412dd8d4334272617f532d4ad4de31e0495bd923", size = 3147642 }, + { url = "https://files.pythonhosted.org/packages/4f/d5/1caabedd8863526a6cfa44ee7a833bd97f945dc1d56824d6d76e11731939/pillow-11.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:084a07ef0821cfe4858fe86652fffac8e187b6ae677e9906e192aafcc1b69903", size = 2978999 }, + { url = "https://files.pythonhosted.org/packages/d9/ff/5a45000826a1aa1ac6874b3ec5a856474821a1b59d838c4f6ce2ee518fe9/pillow-11.0.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8069c5179902dcdce0be9bfc8235347fdbac249d23bd90514b7a47a72d9fecf4", size = 4196794 }, + { url = "https://files.pythonhosted.org/packages/9d/21/84c9f287d17180f26263b5f5c8fb201de0f88b1afddf8a2597a5c9fe787f/pillow-11.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f02541ef64077f22bf4924f225c0fd1248c168f86e4b7abdedd87d6ebaceab0f", size = 4300762 }, + { url = "https://files.pythonhosted.org/packages/84/39/63fb87cd07cc541438b448b1fed467c4d687ad18aa786a7f8e67b255d1aa/pillow-11.0.0-cp312-cp312-manylinux_2_28_aarch64.whl", hash = "sha256:fcb4621042ac4b7865c179bb972ed0da0218a076dc1820ffc48b1d74c1e37fe9", size = 4210468 }, + { url = "https://files.pythonhosted.org/packages/7f/42/6e0f2c2d5c60f499aa29be14f860dd4539de322cd8fb84ee01553493fb4d/pillow-11.0.0-cp312-cp312-manylinux_2_28_x86_64.whl", hash = "sha256:00177a63030d612148e659b55ba99527803288cea7c75fb05766ab7981a8c1b7", size = 4381824 }, + { url = "https://files.pythonhosted.org/packages/31/69/1ef0fb9d2f8d2d114db982b78ca4eeb9db9a29f7477821e160b8c1253f67/pillow-11.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8853a3bf12afddfdf15f57c4b02d7ded92c7a75a5d7331d19f4f9572a89c17e6", size = 4296436 }, + { url = "https://files.pythonhosted.org/packages/44/ea/dad2818c675c44f6012289a7c4f46068c548768bc6c7f4e8c4ae5bbbc811/pillow-11.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3107c66e43bda25359d5ef446f59c497de2b5ed4c7fdba0894f8d6cf3822dafc", size = 4429714 }, + { url = "https://files.pythonhosted.org/packages/af/3a/da80224a6eb15bba7a0dcb2346e2b686bb9bf98378c0b4353cd88e62b171/pillow-11.0.0-cp312-cp312-win32.whl", hash = "sha256:86510e3f5eca0ab87429dd77fafc04693195eec7fd6a137c389c3eeb4cfb77c6", size = 2249631 }, + { url = "https://files.pythonhosted.org/packages/57/97/73f756c338c1d86bb802ee88c3cab015ad7ce4b838f8a24f16b676b1ac7c/pillow-11.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:8ec4a89295cd6cd4d1058a5e6aec6bf51e0eaaf9714774e1bfac7cfc9051db47", size = 2567533 }, + { url = "https://files.pythonhosted.org/packages/0b/30/2b61876e2722374558b871dfbfcbe4e406626d63f4f6ed92e9c8e24cac37/pillow-11.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:27a7860107500d813fcd203b4ea19b04babe79448268403172782754870dac25", size = 2254890 }, + { url = "https://files.pythonhosted.org/packages/63/24/e2e15e392d00fcf4215907465d8ec2a2f23bcec1481a8ebe4ae760459995/pillow-11.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:bcd1fb5bb7b07f64c15618c89efcc2cfa3e95f0e3bcdbaf4642509de1942a699", size = 3147300 }, + { url = "https://files.pythonhosted.org/packages/43/72/92ad4afaa2afc233dc44184adff289c2e77e8cd916b3ddb72ac69495bda3/pillow-11.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0e038b0745997c7dcaae350d35859c9715c71e92ffb7e0f4a8e8a16732150f38", size = 2978742 }, + { url = "https://files.pythonhosted.org/packages/9e/da/c8d69c5bc85d72a8523fe862f05ababdc52c0a755cfe3d362656bb86552b/pillow-11.0.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ae08bd8ffc41aebf578c2af2f9d8749d91f448b3bfd41d7d9ff573d74f2a6b2", size = 4194349 }, + { url = "https://files.pythonhosted.org/packages/cd/e8/686d0caeed6b998351d57796496a70185376ed9c8ec7d99e1d19ad591fc6/pillow-11.0.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d69bfd8ec3219ae71bcde1f942b728903cad25fafe3100ba2258b973bd2bc1b2", size = 4298714 }, + { url = "https://files.pythonhosted.org/packages/ec/da/430015cec620d622f06854be67fd2f6721f52fc17fca8ac34b32e2d60739/pillow-11.0.0-cp313-cp313-manylinux_2_28_aarch64.whl", hash = "sha256:61b887f9ddba63ddf62fd02a3ba7add935d053b6dd7d58998c630e6dbade8527", size = 4208514 }, + { url = "https://files.pythonhosted.org/packages/44/ae/7e4f6662a9b1cb5f92b9cc9cab8321c381ffbee309210940e57432a4063a/pillow-11.0.0-cp313-cp313-manylinux_2_28_x86_64.whl", hash = "sha256:c6a660307ca9d4867caa8d9ca2c2658ab685de83792d1876274991adec7b93fa", size = 4380055 }, + { url = "https://files.pythonhosted.org/packages/74/d5/1a807779ac8a0eeed57f2b92a3c32ea1b696e6140c15bd42eaf908a261cd/pillow-11.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:73e3a0200cdda995c7e43dd47436c1548f87a30bb27fb871f352a22ab8dcf45f", size = 4296751 }, + { url = "https://files.pythonhosted.org/packages/38/8c/5fa3385163ee7080bc13026d59656267daaaaf3c728c233d530e2c2757c8/pillow-11.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:fba162b8872d30fea8c52b258a542c5dfd7b235fb5cb352240c8d63b414013eb", size = 4430378 }, + { url = "https://files.pythonhosted.org/packages/ca/1d/ad9c14811133977ff87035bf426875b93097fb50af747793f013979facdb/pillow-11.0.0-cp313-cp313-win32.whl", hash = "sha256:f1b82c27e89fffc6da125d5eb0ca6e68017faf5efc078128cfaa42cf5cb38798", size = 2249588 }, + { url = "https://files.pythonhosted.org/packages/fb/01/3755ba287dac715e6afdb333cb1f6d69740a7475220b4637b5ce3d78cec2/pillow-11.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:8ba470552b48e5835f1d23ecb936bb7f71d206f9dfeee64245f30c3270b994de", size = 2567509 }, + { url = "https://files.pythonhosted.org/packages/c0/98/2c7d727079b6be1aba82d195767d35fcc2d32204c7a5820f822df5330152/pillow-11.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:846e193e103b41e984ac921b335df59195356ce3f71dcfd155aa79c603873b84", size = 2254791 }, + { url = "https://files.pythonhosted.org/packages/eb/38/998b04cc6f474e78b563716b20eecf42a2fa16a84589d23c8898e64b0ffd/pillow-11.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4ad70c4214f67d7466bea6a08061eba35c01b1b89eaa098040a35272a8efb22b", size = 3150854 }, + { url = "https://files.pythonhosted.org/packages/13/8e/be23a96292113c6cb26b2aa3c8b3681ec62b44ed5c2bd0b258bd59503d3c/pillow-11.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:6ec0d5af64f2e3d64a165f490d96368bb5dea8b8f9ad04487f9ab60dc4bb6003", size = 2982369 }, + { url = "https://files.pythonhosted.org/packages/97/8a/3db4eaabb7a2ae8203cd3a332a005e4aba00067fc514aaaf3e9721be31f1/pillow-11.0.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c809a70e43c7977c4a42aefd62f0131823ebf7dd73556fa5d5950f5b354087e2", size = 4333703 }, + { url = "https://files.pythonhosted.org/packages/28/ac/629ffc84ff67b9228fe87a97272ab125bbd4dc462745f35f192d37b822f1/pillow-11.0.0-cp313-cp313t-manylinux_2_28_x86_64.whl", hash = "sha256:4b60c9520f7207aaf2e1d94de026682fc227806c6e1f55bba7606d1c94dd623a", size = 4412550 }, + { url = "https://files.pythonhosted.org/packages/d6/07/a505921d36bb2df6868806eaf56ef58699c16c388e378b0dcdb6e5b2fb36/pillow-11.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:1e2688958a840c822279fda0086fec1fdab2f95bf2b717b66871c4ad9859d7e8", size = 4461038 }, + { url = "https://files.pythonhosted.org/packages/d6/b9/fb620dd47fc7cc9678af8f8bd8c772034ca4977237049287e99dda360b66/pillow-11.0.0-cp313-cp313t-win32.whl", hash = "sha256:607bbe123c74e272e381a8d1957083a9463401f7bd01287f50521ecb05a313f8", size = 2253197 }, + { url = "https://files.pythonhosted.org/packages/df/86/25dde85c06c89d7fc5db17940f07aae0a56ac69aa9ccb5eb0f09798862a8/pillow-11.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:5c39ed17edea3bc69c743a8dd3e9853b7509625c2462532e62baa0732163a904", size = 2572169 }, + { url = "https://files.pythonhosted.org/packages/51/85/9c33f2517add612e17f3381aee7c4072779130c634921a756c97bc29fb49/pillow-11.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:75acbbeb05b86bc53cbe7b7e6fe00fbcf82ad7c684b3ad82e3d711da9ba287d3", size = 2256828 }, + { url = "https://files.pythonhosted.org/packages/36/57/42a4dd825eab762ba9e690d696d894ba366e06791936056e26e099398cda/pillow-11.0.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:1187739620f2b365de756ce086fdb3604573337cc28a0d3ac4a01ab6b2d2a6d2", size = 3119239 }, + { url = "https://files.pythonhosted.org/packages/98/f7/25f9f9e368226a1d6cf3507081a1a7944eddd3ca7821023377043f5a83c8/pillow-11.0.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fbbcb7b57dc9c794843e3d1258c0fbf0f48656d46ffe9e09b63bbd6e8cd5d0a2", size = 2950803 }, + { url = "https://files.pythonhosted.org/packages/59/01/98ead48a6c2e31e6185d4c16c978a67fe3ccb5da5c2ff2ba8475379bb693/pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d203af30149ae339ad1b4f710d9844ed8796e97fda23ffbc4cc472968a47d0b", size = 3281098 }, + { url = "https://files.pythonhosted.org/packages/51/c0/570255b2866a0e4d500a14f950803a2ec273bac7badc43320120b9262450/pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21a0d3b115009ebb8ac3d2ebec5c2982cc693da935f4ab7bb5c8ebe2f47d36f2", size = 3323665 }, + { url = "https://files.pythonhosted.org/packages/0e/75/689b4ec0483c42bfc7d1aacd32ade7a226db4f4fac57c6fdcdf90c0731e3/pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:73853108f56df97baf2bb8b522f3578221e56f646ba345a372c78326710d3830", size = 3310533 }, + { url = "https://files.pythonhosted.org/packages/3d/30/38bd6149cf53da1db4bad304c543ade775d225961c4310f30425995cb9ec/pillow-11.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:e58876c91f97b0952eb766123bfef372792ab3f4e3e1f1a2267834c2ab131734", size = 3414886 }, + { url = "https://files.pythonhosted.org/packages/ec/3d/c32a51d848401bd94cabb8767a39621496491ee7cd5199856b77da9b18ad/pillow-11.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316", size = 2567508 }, +] + +[[package]] +name = "pyparsing" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/8c/d5/e5aeee5387091148a19e1145f63606619cb5f20b83fccb63efae6474e7b2/pyparsing-3.2.0.tar.gz", hash = "sha256:cbf74e27246d595d9a74b186b810f6fbb86726dbf3b9532efb343f6d7294fe9c", size = 920984 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/be/ec/2eb3cd785efd67806c46c13a17339708ddc346cbb684eade7a6e6f79536a/pyparsing-3.2.0-py3-none-any.whl", hash = "sha256:93d9577b88da0bbea8cc8334ee8b918ed014968fd2ec383e868fb8afb1ccef84", size = 106921 }, +] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892 }, +] + +[[package]] +name = "referencing" +version = "0.35.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "attrs" }, + { name = "rpds-py" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/99/5b/73ca1f8e72fff6fa52119dbd185f73a907b1989428917b24cff660129b6d/referencing-0.35.1.tar.gz", hash = "sha256:25b42124a6c8b632a425174f24087783efb348a6f1e0008e63cd4466fedf703c", size = 62991 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/59/2056f61236782a2c86b33906c025d4f4a0b17be0161b63b70fd9e8775d36/referencing-0.35.1-py3-none-any.whl", hash = "sha256:eda6d3234d62814d1c64e305c1331c9a3a6132da475ab6382eaa997b21ee75de", size = 26684 }, +] + +[[package]] +name = "rpds-py" +version = "0.21.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/23/80/afdf96daf9b27d61483ef05b38f282121db0e38f5fd4e89f40f5c86c2a4f/rpds_py-0.21.0.tar.gz", hash = "sha256:ed6378c9d66d0de903763e7706383d60c33829581f0adff47b6535f1802fa6db", size = 26335 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4c/a4/91747f902f166c589f1753cbd8bda713aceb75817c8bb597058a38aa85e6/rpds_py-0.21.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:a017f813f24b9df929674d0332a374d40d7f0162b326562daae8066b502d0590", size = 327473 }, + { url = "https://files.pythonhosted.org/packages/8a/72/75a30a07f96ae210e732c50c7339e742945fdc83661e65a1c80fcf39ceea/rpds_py-0.21.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:20cc1ed0bcc86d8e1a7e968cce15be45178fd16e2ff656a243145e0b439bd250", size = 318359 }, + { url = "https://files.pythonhosted.org/packages/dc/63/87d469d7628cd71366fd1baa32573acd37385843b8d39b6e2b69f16eec48/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad116dda078d0bc4886cb7840e19811562acdc7a8e296ea6ec37e70326c1b41c", size = 361377 }, + { url = "https://files.pythonhosted.org/packages/dd/b1/78da258a4cafa1d8606a21b7d9ed4cc9d72d1c663583060ab02444b9bd9c/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:808f1ac7cf3b44f81c9475475ceb221f982ef548e44e024ad5f9e7060649540e", size = 369494 }, + { url = "https://files.pythonhosted.org/packages/44/47/6fdb7273cc80066d434e83cd49a3cfedb6d96ff70908480870877fb64b1e/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de552f4a1916e520f2703ec474d2b4d3f86d41f353e7680b597512ffe7eac5d0", size = 403639 }, + { url = "https://files.pythonhosted.org/packages/5f/4a/8c6c46afc050b5243be579be7f7b194d00b9731e83cc0845e9c70db127bb/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:efec946f331349dfc4ae9d0e034c263ddde19414fe5128580f512619abed05f1", size = 430551 }, + { url = "https://files.pythonhosted.org/packages/d4/31/2dd40abc26fc0fc037b86006583276dc375d38ac821d4ca2394274e8045b/rpds_py-0.21.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b80b4690bbff51a034bfde9c9f6bf9357f0a8c61f548942b80f7b66356508bf5", size = 360795 }, + { url = "https://files.pythonhosted.org/packages/9d/2a/665b9ebef76f54764f1437ac03373a95a69480b7ce56c480360f88730cae/rpds_py-0.21.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:085ed25baac88953d4283e5b5bd094b155075bb40d07c29c4f073e10623f9f2e", size = 382663 }, + { url = "https://files.pythonhosted.org/packages/e8/8c/e056f0c887d29baa256f8c8d7f7079a72d80395c35c14219de45ab19dce2/rpds_py-0.21.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:daa8efac2a1273eed2354397a51216ae1e198ecbce9036fba4e7610b308b6153", size = 546477 }, + { url = "https://files.pythonhosted.org/packages/33/11/588568f6c2ed5c9d6d121c188c71ca0f76e0e369a6d66f835737189e5a75/rpds_py-0.21.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:95a5bad1ac8a5c77b4e658671642e4af3707f095d2b78a1fdd08af0dfb647624", size = 549477 }, + { url = "https://files.pythonhosted.org/packages/15/86/c1401e2f70fbdf963c2ac9157994ebeb00c101ddf87975a90507f27cb2f4/rpds_py-0.21.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:3e53861b29a13d5b70116ea4230b5f0f3547b2c222c5daa090eb7c9c82d7f664", size = 527966 }, + { url = "https://files.pythonhosted.org/packages/66/f2/452420f1493112825e975c87b3b4fd8b334e0e228cdb641597a92e0c3267/rpds_py-0.21.0-cp310-none-win32.whl", hash = "sha256:ea3a6ac4d74820c98fcc9da4a57847ad2cc36475a8bd9683f32ab6d47a2bd682", size = 200978 }, + { url = "https://files.pythonhosted.org/packages/35/4c/674b2e2d75607acdbc7a162ace36dcaad225c9e760cef5defa5c0f5ddd2d/rpds_py-0.21.0-cp310-none-win_amd64.whl", hash = "sha256:b8f107395f2f1d151181880b69a2869c69e87ec079c49c0016ab96860b6acbe5", size = 218549 }, + { url = "https://files.pythonhosted.org/packages/80/61/615929ea79f5fd0b3aca000411a33bcc1753607ccc1af0ce7b05b56e6e56/rpds_py-0.21.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:5555db3e618a77034954b9dc547eae94166391a98eb867905ec8fcbce1308d95", size = 327267 }, + { url = "https://files.pythonhosted.org/packages/a5/f5/28e89dda55b731d78cbfea284dc9789d265a8a06523f0adf60e9b05cade7/rpds_py-0.21.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:97ef67d9bbc3e15584c2f3c74bcf064af36336c10d2e21a2131e123ce0f924c9", size = 318227 }, + { url = "https://files.pythonhosted.org/packages/e4/ef/eb90feb3e384543c48e2f867551075c43a429aa4c9a44e9c4bd71f4f786b/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4ab2c2a26d2f69cdf833174f4d9d86118edc781ad9a8fa13970b527bf8236027", size = 361235 }, + { url = "https://files.pythonhosted.org/packages/ed/e7/8ea2d3d3398266c5c8ddd957d86003493b6d14f8f158b726dd09c8f43dee/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4e8921a259f54bfbc755c5bbd60c82bb2339ae0324163f32868f63f0ebb873d9", size = 369467 }, + { url = "https://files.pythonhosted.org/packages/51/25/a286abda9da7820c971a0b1abcf1d31fb81c44a1088a128ad26c77206622/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8a7ff941004d74d55a47f916afc38494bd1cfd4b53c482b77c03147c91ac0ac3", size = 403482 }, + { url = "https://files.pythonhosted.org/packages/7a/1e/9c3c0463fe142456dcd9e9be0ffd15b66a77adfcdf3ecf94fa2b12d95fcb/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5145282a7cd2ac16ea0dc46b82167754d5e103a05614b724457cffe614f25bd8", size = 429943 }, + { url = "https://files.pythonhosted.org/packages/e1/fd/f1fd7e77fef8e5a442ce7fd80ba957730877515fe18d7195f646408a60ce/rpds_py-0.21.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:de609a6f1b682f70bb7163da745ee815d8f230d97276db049ab447767466a09d", size = 360437 }, + { url = "https://files.pythonhosted.org/packages/55/83/347932db075847f4f8172c3b53ad70fe725edd9058f0d4098080ad45e3bc/rpds_py-0.21.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40c91c6e34cf016fa8e6b59d75e3dbe354830777fcfd74c58b279dceb7975b75", size = 382400 }, + { url = "https://files.pythonhosted.org/packages/22/9b/2a6eeab4e6752adba751cfee19bdf35d11e1073509f74883cbf14d42d682/rpds_py-0.21.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d2132377f9deef0c4db89e65e8bb28644ff75a18df5293e132a8d67748397b9f", size = 546560 }, + { url = "https://files.pythonhosted.org/packages/3c/19/6e51a141fe6f017d07b7d899b10a4af9e0f268deffacc1107d70fcd9257b/rpds_py-0.21.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:0a9e0759e7be10109645a9fddaaad0619d58c9bf30a3f248a2ea57a7c417173a", size = 549334 }, + { url = "https://files.pythonhosted.org/packages/cf/40/4ae09a07e4531278e6bee41ef3e4f166c23468135afc2c6c98917bfc28e6/rpds_py-0.21.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:9e20da3957bdf7824afdd4b6eeb29510e83e026473e04952dca565170cd1ecc8", size = 527855 }, + { url = "https://files.pythonhosted.org/packages/eb/45/2135be31543677687a426117c56d8b33e8b581bc4a8b7abfa53721012162/rpds_py-0.21.0-cp311-none-win32.whl", hash = "sha256:f71009b0d5e94c0e86533c0b27ed7cacc1239cb51c178fd239c3cfefefb0400a", size = 200968 }, + { url = "https://files.pythonhosted.org/packages/68/fa/e66c3aaf13ef91c203ba47c102cd7c5dca92dde8837e5093577968d6d36d/rpds_py-0.21.0-cp311-none-win_amd64.whl", hash = "sha256:e168afe6bf6ab7ab46c8c375606298784ecbe3ba31c0980b7dcbb9631dcba97e", size = 218502 }, + { url = "https://files.pythonhosted.org/packages/d9/5a/3aa6f5d8bacbe4f55ebf9a3c9628dad40cdb57f845124cf13c78895ea156/rpds_py-0.21.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:30b912c965b2aa76ba5168fd610087bad7fcde47f0a8367ee8f1876086ee6d1d", size = 329516 }, + { url = "https://files.pythonhosted.org/packages/df/c0/67c8c8ac850c6e3681e356a59d46315bf73bc77cb50c9a32db8ae44325b7/rpds_py-0.21.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ca9989d5d9b1b300bc18e1801c67b9f6d2c66b8fd9621b36072ed1df2c977f72", size = 321245 }, + { url = "https://files.pythonhosted.org/packages/64/83/bf31341f21fa594035891ff04a497dc86b210cc1a903a9cc01b097cc614f/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6f54e7106f0001244a5f4cf810ba8d3f9c542e2730821b16e969d6887b664266", size = 363951 }, + { url = "https://files.pythonhosted.org/packages/a2/e1/8218bba36737621262df316fbb729639af25ff611cc07bfeaadc1bfa6292/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:fed5dfefdf384d6fe975cc026886aece4f292feaf69d0eeb716cfd3c5a4dd8be", size = 373113 }, + { url = "https://files.pythonhosted.org/packages/39/8d/4afcd688e3ad33ec273900f42e6a41e9bd9f43cfc509b6d498683d2d0338/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:590ef88db231c9c1eece44dcfefd7515d8bf0d986d64d0caf06a81998a9e8cab", size = 405944 }, + { url = "https://files.pythonhosted.org/packages/fa/65/3326efa721b6ecd70262aab69a26c9bc19398cdb0a2a416ef30b58326460/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f983e4c2f603c95dde63df633eec42955508eefd8d0f0e6d236d31a044c882d7", size = 422874 }, + { url = "https://files.pythonhosted.org/packages/31/fb/48a647d0afab74289dd21a4128002d58684c22600a22c4bfb76cb9e3bfb0/rpds_py-0.21.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b229ce052ddf1a01c67d68166c19cb004fb3612424921b81c46e7ea7ccf7c3bf", size = 364227 }, + { url = "https://files.pythonhosted.org/packages/f1/b0/1cdd179d7382dd52d65b1fd19c54d090b6bd0688dfbe259bb5ab7548c359/rpds_py-0.21.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ebf64e281a06c904a7636781d2e973d1f0926a5b8b480ac658dc0f556e7779f4", size = 386447 }, + { url = "https://files.pythonhosted.org/packages/dc/41/84ace07f31aac3a96b73a374d89106cf252f7d3274e7cae85d17a27c602d/rpds_py-0.21.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:998a8080c4495e4f72132f3d66ff91f5997d799e86cec6ee05342f8f3cda7dca", size = 549386 }, + { url = "https://files.pythonhosted.org/packages/33/ce/bf51bc5a3aa539171ea8c7737ab5ac06cef54c79b6b2a0511afc41533c89/rpds_py-0.21.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:98486337f7b4f3c324ab402e83453e25bb844f44418c066623db88e4c56b7c7b", size = 554777 }, + { url = "https://files.pythonhosted.org/packages/76/b1/950568e55a94c2979c2b61ec24e76e648a525fbc7551ccfc1f2841e39d44/rpds_py-0.21.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a78d8b634c9df7f8d175451cfeac3810a702ccb85f98ec95797fa98b942cea11", size = 530918 }, + { url = "https://files.pythonhosted.org/packages/78/84/93f00e3613426c8a7a9ca16782d2828f2ac55296dd5c6b599379d9f59ee2/rpds_py-0.21.0-cp312-none-win32.whl", hash = "sha256:a58ce66847711c4aa2ecfcfaff04cb0327f907fead8945ffc47d9407f41ff952", size = 203112 }, + { url = "https://files.pythonhosted.org/packages/e6/08/7a186847dd78881a781d2be9b42c8e49c3261c0f4a6d0289ba9a1e4cde71/rpds_py-0.21.0-cp312-none-win_amd64.whl", hash = "sha256:e860f065cc4ea6f256d6f411aba4b1251255366e48e972f8a347cf88077b24fd", size = 220735 }, + { url = "https://files.pythonhosted.org/packages/32/3a/e69ec108eefb9b1f19ee00dde7a800b485942e62b123f01d9156a6d8569c/rpds_py-0.21.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:ee4eafd77cc98d355a0d02f263efc0d3ae3ce4a7c24740010a8b4012bbb24937", size = 329206 }, + { url = "https://files.pythonhosted.org/packages/f6/c0/fa689498fa3415565306398c8d2a596207c2a13d3cc03724f32514bddfbc/rpds_py-0.21.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:688c93b77e468d72579351a84b95f976bd7b3e84aa6686be6497045ba84be560", size = 320245 }, + { url = "https://files.pythonhosted.org/packages/68/d0/466b61007005f1b2fd8501f23e4bdee4d71c7381b61358750920d1882ac9/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c38dbf31c57032667dd5a2f0568ccde66e868e8f78d5a0d27dcc56d70f3fcd3b", size = 363585 }, + { url = "https://files.pythonhosted.org/packages/1e/e2/787ea3a0f4b197893c62c254e6f14929c40bbcff86922928ac4eafaa8edf/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2d6129137f43f7fa02d41542ffff4871d4aefa724a5fe38e2c31a4e0fd343fb0", size = 372302 }, + { url = "https://files.pythonhosted.org/packages/b5/ef/99f2cfe6aa128c21f1b30c66ecd348cbd59792953ca35eeb6efa38b88aa1/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520ed8b99b0bf86a176271f6fe23024323862ac674b1ce5b02a72bfeff3fff44", size = 405344 }, + { url = "https://files.pythonhosted.org/packages/30/3c/9d12d0b76ecfe80a7ba4770459828dda495d72b18cafd6dfd54c67b2e282/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aaeb25ccfb9b9014a10eaf70904ebf3f79faaa8e60e99e19eef9f478651b9b74", size = 422322 }, + { url = "https://files.pythonhosted.org/packages/f9/22/387aec1cd6e124adbc3b1f40c4e4152c3963ae47d78d3ca650102ea72c4f/rpds_py-0.21.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:af04ac89c738e0f0f1b913918024c3eab6e3ace989518ea838807177d38a2e94", size = 363739 }, + { url = "https://files.pythonhosted.org/packages/d1/3e/0ad65b776db13d13f002ab363fe3821cd1adec500d8e05e0a81047a75f9d/rpds_py-0.21.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b9b76e2afd585803c53c5b29e992ecd183f68285b62fe2668383a18e74abe7a3", size = 386579 }, + { url = "https://files.pythonhosted.org/packages/4f/3b/c68c1067b24a7df47edcc0325a825908601aba399e2d372a156edc631ad1/rpds_py-0.21.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:5afb5efde74c54724e1a01118c6e5c15e54e642c42a1ba588ab1f03544ac8c7a", size = 548924 }, + { url = "https://files.pythonhosted.org/packages/ab/1c/35f1a5cce4bca71c49664f00140010a96b126e5f443ebaf6db741c25b9b7/rpds_py-0.21.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:52c041802a6efa625ea18027a0723676a778869481d16803481ef6cc02ea8cb3", size = 554217 }, + { url = "https://files.pythonhosted.org/packages/c8/d0/48154c152f9adb8304b21d867d28e79be3b352633fb195c03c7107a4da9a/rpds_py-0.21.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ee1e4fc267b437bb89990b2f2abf6c25765b89b72dd4a11e21934df449e0c976", size = 530540 }, + { url = "https://files.pythonhosted.org/packages/50/e8/78847f4e112e99fd5b7bc30fea3e4a44c20b811473d6755f944c5bf0aec7/rpds_py-0.21.0-cp313-none-win32.whl", hash = "sha256:0c025820b78817db6a76413fff6866790786c38f95ea3f3d3c93dbb73b632202", size = 202604 }, + { url = "https://files.pythonhosted.org/packages/60/31/083e6337775e133fb0217ed0ab0752380efa6e5112f2250d592d4135a228/rpds_py-0.21.0-cp313-none-win_amd64.whl", hash = "sha256:320c808df533695326610a1b6a0a6e98f033e49de55d7dc36a13c8a30cfa756e", size = 220448 }, + { url = "https://files.pythonhosted.org/packages/ff/d3/ffb04445d29c03d380047c62bed01b979adb9204424e2c833817012f679e/rpds_py-0.21.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:6b4ef7725386dc0762857097f6b7266a6cdd62bfd209664da6712cb26acef035", size = 328265 }, + { url = "https://files.pythonhosted.org/packages/dc/9d/894ff29a2be8f85fd1acff6e0c1b52b629aee019da8651125af9ee4894e1/rpds_py-0.21.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:6bc0e697d4d79ab1aacbf20ee5f0df80359ecf55db33ff41481cf3e24f206919", size = 319238 }, + { url = "https://files.pythonhosted.org/packages/43/3d/0e5b835c22933a5bdc4413e4a91de55a8c1ef33f55eb2514a5cf24729173/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da52d62a96e61c1c444f3998c434e8b263c384f6d68aca8274d2e08d1906325c", size = 362136 }, + { url = "https://files.pythonhosted.org/packages/67/81/c9f29da910ac19758f170633c0937fc2f0898b84389bd05bfc255c985f19/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:98e4fe5db40db87ce1c65031463a760ec7906ab230ad2249b4572c2fc3ef1f9f", size = 370411 }, + { url = "https://files.pythonhosted.org/packages/a8/df/b989044f90b81093e454eb54799e7ee5b085ebf957a75d07d5e21eac2fb5/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:30bdc973f10d28e0337f71d202ff29345320f8bc49a31c90e6c257e1ccef4333", size = 404598 }, + { url = "https://files.pythonhosted.org/packages/8f/09/f79cd575f503932f41138c4bec4c902eb3b71ea8570436688145cc77b8ef/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:faa5e8496c530f9c71f2b4e1c49758b06e5f4055e17144906245c99fa6d45356", size = 430224 }, + { url = "https://files.pythonhosted.org/packages/34/46/7fae3500bc188df2feee09dd72df262b97d31e8e4bd2ff4a8be4e28bf1d3/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:32eb88c30b6a4f0605508023b7141d043a79b14acb3b969aa0b4f99b25bc7d4a", size = 361660 }, + { url = "https://files.pythonhosted.org/packages/5b/1d/d850242d30e68f99ad80815576f38b378b5aba393613e3357ed5e593499e/rpds_py-0.21.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a89a8ce9e4e75aeb7fa5d8ad0f3fecdee813802592f4f46a15754dcb2fd6b061", size = 384008 }, + { url = "https://files.pythonhosted.org/packages/c9/16/df4cfd1de216c25de24f8631f17380f8edee92201ec7810d1e2ba1dd9f85/rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:241e6c125568493f553c3d0fdbb38c74babf54b45cef86439d4cd97ff8feb34d", size = 546855 }, + { url = "https://files.pythonhosted.org/packages/c0/b8/03d4561095d4fbf2ab62ed651a2b5cb674fe5245b1ab2f7909e8056bd014/rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:3b766a9f57663396e4f34f5140b3595b233a7b146e94777b97a8413a1da1be18", size = 550599 }, + { url = "https://files.pythonhosted.org/packages/f4/54/d93867e2bf4acf57314798181faf3bd7d1a4f51a3aa81cb6211d56f74d3f/rpds_py-0.21.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:af4a644bf890f56e41e74be7d34e9511e4954894d544ec6b8efe1e21a1a8da6c", size = 528963 }, + { url = "https://files.pythonhosted.org/packages/66/86/6f72984a284d720d84fba5ee7b0d1b0d320978b516497cbfd6e335e95a3e/rpds_py-0.21.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:3e30a69a706e8ea20444b98a49f386c17b26f860aa9245329bab0851ed100677", size = 219621 }, +] + +[[package]] +name = "scipy" +version = "1.14.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/62/11/4d44a1f274e002784e4dbdb81e0ea96d2de2d1045b2132d5af62cc31fd28/scipy-1.14.1.tar.gz", hash = "sha256:5a275584e726026a5699459aa72f828a610821006228e841b94275c4a7c08417", size = 58620554 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/64/68/3bc0cfaf64ff507d82b1e5d5b64521df4c8bf7e22bc0b897827cbee9872c/scipy-1.14.1-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:b28d2ca4add7ac16ae8bb6632a3c86e4b9e4d52d3e34267f6e1b0c1f8d87e389", size = 39069598 }, + { url = "https://files.pythonhosted.org/packages/43/a5/8d02f9c372790326ad405d94f04d4339482ec082455b9e6e288f7100513b/scipy-1.14.1-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:d0d2821003174de06b69e58cef2316a6622b60ee613121199cb2852a873f8cf3", size = 29879676 }, + { url = "https://files.pythonhosted.org/packages/07/42/0e0bea9666fcbf2cb6ea0205db42c81b1f34d7b729ba251010edf9c80ebd/scipy-1.14.1-cp310-cp310-macosx_14_0_arm64.whl", hash = "sha256:8bddf15838ba768bb5f5083c1ea012d64c9a444e16192762bd858f1e126196d0", size = 23088696 }, + { url = "https://files.pythonhosted.org/packages/15/47/298ab6fef5ebf31b426560e978b8b8548421d4ed0bf99263e1eb44532306/scipy-1.14.1-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:97c5dddd5932bd2a1a31c927ba5e1463a53b87ca96b5c9bdf5dfd6096e27efc3", size = 25470699 }, + { url = "https://files.pythonhosted.org/packages/d8/df/cdb6be5274bc694c4c22862ac3438cb04f360ed9df0aecee02ce0b798380/scipy-1.14.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2ff0a7e01e422c15739ecd64432743cf7aae2b03f3084288f399affcefe5222d", size = 35606631 }, + { url = "https://files.pythonhosted.org/packages/47/78/b0c2c23880dd1e99e938ad49ccfb011ae353758a2dc5ed7ee59baff684c3/scipy-1.14.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e32dced201274bf96899e6491d9ba3e9a5f6b336708656466ad0522d8528f69", size = 41178528 }, + { url = "https://files.pythonhosted.org/packages/5d/aa/994b45c34b897637b853ec04334afa55a85650a0d11dacfa67232260fb0a/scipy-1.14.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8426251ad1e4ad903a4514712d2fa8fdd5382c978010d1c6f5f37ef286a713ad", size = 42784535 }, + { url = "https://files.pythonhosted.org/packages/e7/1c/8daa6df17a945cb1a2a1e3bae3c49643f7b3b94017ff01a4787064f03f84/scipy-1.14.1-cp310-cp310-win_amd64.whl", hash = "sha256:a49f6ed96f83966f576b33a44257d869756df6cf1ef4934f59dd58b25e0327e5", size = 44772117 }, + { url = "https://files.pythonhosted.org/packages/b2/ab/070ccfabe870d9f105b04aee1e2860520460ef7ca0213172abfe871463b9/scipy-1.14.1-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:2da0469a4ef0ecd3693761acbdc20f2fdeafb69e6819cc081308cc978153c675", size = 39076999 }, + { url = "https://files.pythonhosted.org/packages/a7/c5/02ac82f9bb8f70818099df7e86c3ad28dae64e1347b421d8e3adf26acab6/scipy-1.14.1-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:c0ee987efa6737242745f347835da2cc5bb9f1b42996a4d97d5c7ff7928cb6f2", size = 29894570 }, + { url = "https://files.pythonhosted.org/packages/ed/05/7f03e680cc5249c4f96c9e4e845acde08eb1aee5bc216eff8a089baa4ddb/scipy-1.14.1-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:3a1b111fac6baec1c1d92f27e76511c9e7218f1695d61b59e05e0fe04dc59617", size = 23103567 }, + { url = "https://files.pythonhosted.org/packages/5e/fc/9f1413bef53171f379d786aabc104d4abeea48ee84c553a3e3d8c9f96a9c/scipy-1.14.1-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:8475230e55549ab3f207bff11ebfc91c805dc3463ef62eda3ccf593254524ce8", size = 25499102 }, + { url = "https://files.pythonhosted.org/packages/c2/4b/b44bee3c2ddc316b0159b3d87a3d467ef8d7edfd525e6f7364a62cd87d90/scipy-1.14.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:278266012eb69f4a720827bdd2dc54b2271c97d84255b2faaa8f161a158c3b37", size = 35586346 }, + { url = "https://files.pythonhosted.org/packages/93/6b/701776d4bd6bdd9b629c387b5140f006185bd8ddea16788a44434376b98f/scipy-1.14.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fef8c87f8abfb884dac04e97824b61299880c43f4ce675dd2cbeadd3c9b466d2", size = 41165244 }, + { url = "https://files.pythonhosted.org/packages/06/57/e6aa6f55729a8f245d8a6984f2855696c5992113a5dc789065020f8be753/scipy-1.14.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b05d43735bb2f07d689f56f7b474788a13ed8adc484a85aa65c0fd931cf9ccd2", size = 42817917 }, + { url = "https://files.pythonhosted.org/packages/ea/c2/5ecadc5fcccefaece775feadcd795060adf5c3b29a883bff0e678cfe89af/scipy-1.14.1-cp311-cp311-win_amd64.whl", hash = "sha256:716e389b694c4bb564b4fc0c51bc84d381735e0d39d3f26ec1af2556ec6aad94", size = 44781033 }, + { url = "https://files.pythonhosted.org/packages/c0/04/2bdacc8ac6387b15db6faa40295f8bd25eccf33f1f13e68a72dc3c60a99e/scipy-1.14.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:631f07b3734d34aced009aaf6fedfd0eb3498a97e581c3b1e5f14a04164a456d", size = 39128781 }, + { url = "https://files.pythonhosted.org/packages/c8/53/35b4d41f5fd42f5781dbd0dd6c05d35ba8aa75c84ecddc7d44756cd8da2e/scipy-1.14.1-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:af29a935803cc707ab2ed7791c44288a682f9c8107bc00f0eccc4f92c08d6e07", size = 29939542 }, + { url = "https://files.pythonhosted.org/packages/66/67/6ef192e0e4d77b20cc33a01e743b00bc9e68fb83b88e06e636d2619a8767/scipy-1.14.1-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2843f2d527d9eebec9a43e6b406fb7266f3af25a751aa91d62ff416f54170bc5", size = 23148375 }, + { url = "https://files.pythonhosted.org/packages/f6/32/3a6dedd51d68eb7b8e7dc7947d5d841bcb699f1bf4463639554986f4d782/scipy-1.14.1-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:eb58ca0abd96911932f688528977858681a59d61a7ce908ffd355957f7025cfc", size = 25578573 }, + { url = "https://files.pythonhosted.org/packages/f0/5a/efa92a58dc3a2898705f1dc9dbaf390ca7d4fba26d6ab8cfffb0c72f656f/scipy-1.14.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30ac8812c1d2aab7131a79ba62933a2a76f582d5dbbc695192453dae67ad6310", size = 35319299 }, + { url = "https://files.pythonhosted.org/packages/8e/ee/8a26858ca517e9c64f84b4c7734b89bda8e63bec85c3d2f432d225bb1886/scipy-1.14.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f9ea80f2e65bdaa0b7627fb00cbeb2daf163caa015e59b7516395fe3bd1e066", size = 40849331 }, + { url = "https://files.pythonhosted.org/packages/a5/cd/06f72bc9187840f1c99e1a8750aad4216fc7dfdd7df46e6280add14b4822/scipy-1.14.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:edaf02b82cd7639db00dbff629995ef185c8df4c3ffa71a5562a595765a06ce1", size = 42544049 }, + { url = "https://files.pythonhosted.org/packages/aa/7d/43ab67228ef98c6b5dd42ab386eae2d7877036970a0d7e3dd3eb47a0d530/scipy-1.14.1-cp312-cp312-win_amd64.whl", hash = "sha256:2ff38e22128e6c03ff73b6bb0f85f897d2362f8c052e3b8ad00532198fbdae3f", size = 44521212 }, + { url = "https://files.pythonhosted.org/packages/50/ef/ac98346db016ff18a6ad7626a35808f37074d25796fd0234c2bb0ed1e054/scipy-1.14.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1729560c906963fc8389f6aac023739ff3983e727b1a4d87696b7bf108316a79", size = 39091068 }, + { url = "https://files.pythonhosted.org/packages/b9/cc/70948fe9f393b911b4251e96b55bbdeaa8cca41f37c26fd1df0232933b9e/scipy-1.14.1-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:4079b90df244709e675cdc8b93bfd8a395d59af40b72e339c2287c91860deb8e", size = 29875417 }, + { url = "https://files.pythonhosted.org/packages/3b/2e/35f549b7d231c1c9f9639f9ef49b815d816bf54dd050da5da1c11517a218/scipy-1.14.1-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:e0cf28db0f24a38b2a0ca33a85a54852586e43cf6fd876365c86e0657cfe7d73", size = 23084508 }, + { url = "https://files.pythonhosted.org/packages/3f/d6/b028e3f3e59fae61fb8c0f450db732c43dd1d836223a589a8be9f6377203/scipy-1.14.1-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:0c2f95de3b04e26f5f3ad5bb05e74ba7f68b837133a4492414b3afd79dfe540e", size = 25503364 }, + { url = "https://files.pythonhosted.org/packages/a7/2f/6c142b352ac15967744d62b165537a965e95d557085db4beab2a11f7943b/scipy-1.14.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b99722ea48b7ea25e8e015e8341ae74624f72e5f21fc2abd45f3a93266de4c5d", size = 35292639 }, + { url = "https://files.pythonhosted.org/packages/56/46/2449e6e51e0d7c3575f289f6acb7f828938eaab8874dbccfeb0cd2b71a27/scipy-1.14.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5149e3fd2d686e42144a093b206aef01932a0059c2a33ddfa67f5f035bdfe13e", size = 40798288 }, + { url = "https://files.pythonhosted.org/packages/32/cd/9d86f7ed7f4497c9fd3e39f8918dd93d9f647ba80d7e34e4946c0c2d1a7c/scipy-1.14.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:e4f5a7c49323533f9103d4dacf4e4f07078f360743dec7f7596949149efeec06", size = 42524647 }, + { url = "https://files.pythonhosted.org/packages/f5/1b/6ee032251bf4cdb0cc50059374e86a9f076308c1512b61c4e003e241efb7/scipy-1.14.1-cp313-cp313-win_amd64.whl", hash = "sha256:baff393942b550823bfce952bb62270ee17504d02a1801d7fd0719534dfb9c84", size = 44469524 }, +] + +[[package]] +name = "six" +version = "1.16.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/71/39/171f1c67cd00715f190ba0b100d606d440a28c93c7714febeca8b79af85e/six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", size = 34041 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/5a/e7c31adbe875f2abbb91bd84cf2dc52d792b5a01506781dbcf25c91daf11/six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254", size = 11053 }, +] + +[[package]] +name = "sortedcontainers" +version = "2.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e8/c4/ba2f8066cceb6f23394729afe52f3bf7adec04bf9ed2c820b39e19299111/sortedcontainers-2.4.0.tar.gz", hash = "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", size = 30594 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, +] + +[[package]] +name = "thd-json" +version = "0.1.0" +source = { git = "https://mygit.th-deg.de/roboct/definitions/json_schemas#b5e4c2ca23aa4a68e954ddaa3e19828bf8c872f6" } +dependencies = [ + { name = "hypothesis" }, + { name = "hypothesis-jsonschema" }, + { name = "json-schema" }, + { name = "jsonschema" }, +] From 8aaf55d0ec6f438afde253c632d050bdcb1c5bf7 Mon Sep 17 00:00:00 2001 From: swittl Date: Tue, 19 Nov 2024 21:11:19 +0100 Subject: [PATCH 18/21] linter fixes --- src/artist_pythonlib/__init__.py | 7 +++++++ src/artist_pythonlib/api.py | 4 ++-- src/artist_pythonlib/geometries/__init__.py | 7 ++++++- src/artist_pythonlib/hardware/__init__.py | 7 ++++++- src/artist_pythonlib/hardware/xray_source.py | 12 ++++++------ src/artist_pythonlib/remote_connection.py | 7 ++----- src/artist_pythonlib/trajectory/__init__.py | 7 +++++++ src/artist_pythonlib/utility/__init__.py | 7 ++++++- src/artist_pythonlib/utility/load_projection.py | 2 +- 9 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/artist_pythonlib/__init__.py b/src/artist_pythonlib/__init__.py index 0b843ed..96febeb 100644 --- a/src/artist_pythonlib/__init__.py +++ b/src/artist_pythonlib/__init__.py @@ -11,3 +11,10 @@ from .common_types import SAVEMODES, SOURCETYPES, PROJECTIONGEOMETRIES +__all__ = [ + 'SAVEMODES', + 'SOURCETYPES', + 'PROJECTIONGEOMETRIES', + 'Junction', + 'API' +] \ No newline at end of file diff --git a/src/artist_pythonlib/api.py b/src/artist_pythonlib/api.py index 9176a52..1e9ac9f 100644 --- a/src/artist_pythonlib/api.py +++ b/src/artist_pythonlib/api.py @@ -279,7 +279,7 @@ def get_detector_resolution(self) -> np.ndarray: Returns: np.ndarray: Pixel pitch of the detector (u, v). """ - result = self.rc.send(f'::XDetector::GetResolution') + result = self.rc.send('::XDetector::GetResolution') return np.array(np.float32(result.split(" "))) def get_detector_pixel_count(self) -> np.ndarray: @@ -288,7 +288,7 @@ def get_detector_pixel_count(self) -> np.ndarray: Returns: np.ndarray: Pixel count (u, v). """ - result = self.rc.send(f'::XDetector::GetPixelSize') + result = self.rc.send('::XDetector::GetPixelSize') return np.array(np.int32(result.split(" "))) def set_material(self, id: int | str, material: str): diff --git a/src/artist_pythonlib/geometries/__init__.py b/src/artist_pythonlib/geometries/__init__.py index e27a357..103bd15 100644 --- a/src/artist_pythonlib/geometries/__init__.py +++ b/src/artist_pythonlib/geometries/__init__.py @@ -1,2 +1,7 @@ from .standard_format import projection_geometry -from .thd_format import thd_projection_geometry \ No newline at end of file +from .thd_format import thd_projection_geometry + +__all__ = [ + 'projection_geometry', + 'thd_projection_geometry' +] \ No newline at end of file diff --git a/src/artist_pythonlib/hardware/__init__.py b/src/artist_pythonlib/hardware/__init__.py index 0032278..ef5f600 100644 --- a/src/artist_pythonlib/hardware/__init__.py +++ b/src/artist_pythonlib/hardware/__init__.py @@ -13,4 +13,9 @@ # limitations under the License. from .xray_source import XraySource -from .xray_detector import XrayDetector \ No newline at end of file +from .xray_detector import XrayDetector + +__all__ = [ + 'XraySource', + 'XrayDetector' +] \ No newline at end of file diff --git a/src/artist_pythonlib/hardware/xray_source.py b/src/artist_pythonlib/hardware/xray_source.py index a7272d2..ab740a8 100644 --- a/src/artist_pythonlib/hardware/xray_source.py +++ b/src/artist_pythonlib/hardware/xray_source.py @@ -44,7 +44,7 @@ def voltage_kv(self) -> float: @voltage_kv.setter def voltage_kv(self, voltage_kv: float) -> None: self.rc.send(f'set ::Xsource(Voltage) {voltage_kv}') - self.rc.send(f'::XSource::ComputeSpectrum') + self.rc.send('::XSource::ComputeSpectrum') @property def exposure_ma(self) -> float: @@ -75,7 +75,7 @@ def filter_material(self) -> str: @filter_material.setter def filter_material(self, filter_material: float) -> None: self.rc.send(f'set ::Xsource(FilterMaterial) {filter_material}') - self.rc.send(f'::XSource::ComputeSpectrum') + self.rc.send('::XSource::ComputeSpectrum') @property def filter_thickness_mm(self) -> float: @@ -91,7 +91,7 @@ def filter_thickness_mm(self) -> float: @filter_thickness_mm.setter def filter_thickness_mm(self, filter_thickness_mm: float) -> None: self.rc.send(f'set ::Xsource(FilterThickness) {filter_thickness_mm}') - self.rc.send(f'::XSource::ComputeSpectrum') + self.rc.send('::XSource::ComputeSpectrum') @property def source_type(self) -> int: @@ -111,7 +111,7 @@ def source_type(self) -> int: @source_type.setter def source_type(self, source_type: SOURCETYPES) -> None: if source_type == SOURCETYPES.MONOCHROMATIC: - self.rc.send(f'set ::Xsource(Tube) Mono') + self.rc.send('set ::Xsource(Tube) Mono') elif source_type == SOURCETYPES.GENERAL: - self.rc.send(f'set ::Xsource(Tube) General') - self.rc.send(f'::XSource::ComputeSpectrum') + self.rc.send('set ::Xsource(Tube) General') + self.rc.send('::XSource::ComputeSpectrum') diff --git a/src/artist_pythonlib/remote_connection.py b/src/artist_pythonlib/remote_connection.py index 1811348..e1d2c50 100644 --- a/src/artist_pythonlib/remote_connection.py +++ b/src/artist_pythonlib/remote_connection.py @@ -81,7 +81,7 @@ def listen(self, command_no=1, msgType="RESULT"): elif ("PROGRESS" in msg): try: self.progress = float(msg.strip('PROGRESS ')) - except: + except ValueError: self.progress = 0 continue else: @@ -112,13 +112,10 @@ def get_answer(self, key): return self.answer[key] def save_image(self, imageName: str): - npTypes = [np.bool_, np.ubyte, np.byte, np.ubyte, np.short, np.ushort, np.intc, np.uintc, np.int_, np.uint, np.single, np.double] imageData = self.answer["BASE64"] decodedData = base64.b64decode((imageData)) imageHeader = self.answer["IMAGE"].split() - # dtype = npTypes[int(imageHeader[np.double])] - dtype = np.double - im = np.frombuffer(decodedData, dtype).reshape((int(imageHeader[1]),int(imageHeader[2]))) + im = np.frombuffer(decodedData, np.double).reshape((int(imageHeader[1]),int(imageHeader[2]))) Image.fromarray(im).save(imageName) def receive_file(self, fileName): diff --git a/src/artist_pythonlib/trajectory/__init__.py b/src/artist_pythonlib/trajectory/__init__.py index 5f83328..dc88815 100644 --- a/src/artist_pythonlib/trajectory/__init__.py +++ b/src/artist_pythonlib/trajectory/__init__.py @@ -13,3 +13,10 @@ # limitations under the License. from .ct_trajectories import circular_trajectory, look_at_orientation, sphere_trajectory, arbitary_circular_trajectory + +__all__ = [ + 'circular_trajectory', + 'look_at_orientation', + 'sphere_trajectory', + 'arbitary_circular_trajectory' +] diff --git a/src/artist_pythonlib/utility/__init__.py b/src/artist_pythonlib/utility/__init__.py index 6bca333..65000c5 100644 --- a/src/artist_pythonlib/utility/__init__.py +++ b/src/artist_pythonlib/utility/__init__.py @@ -1 +1,6 @@ -from .load_projection import load_projection, load_header \ No newline at end of file +from .load_projection import load_projection, load_header + +__all__ = [ + 'load_projection', + 'load_header' +] \ No newline at end of file diff --git a/src/artist_pythonlib/utility/load_projection.py b/src/artist_pythonlib/utility/load_projection.py index 5c0a097..4957056 100644 --- a/src/artist_pythonlib/utility/load_projection.py +++ b/src/artist_pythonlib/utility/load_projection.py @@ -8,7 +8,7 @@ def load_projection(projection_path: Path, load_projection_geometry: bool = True) -> tuple[np.ndarray, dict]: try: projection_array = np.array(Image.open(projection_path)) - except: + except FileNotFoundError: time.sleep(1) projection_array = np.array(Image.open(projection_path)) From 108dfee0db45dfe944bb9435b91b688076a05838 Mon Sep 17 00:00:00 2001 From: swittl Date: Tue, 19 Nov 2024 21:12:15 +0100 Subject: [PATCH 19/21] ruff format --- src/artist_pythonlib/__init__.py | 10 +- src/artist_pythonlib/api.py | 193 +++++++++++------- src/artist_pythonlib/common_types.py | 11 +- src/artist_pythonlib/geometries/__init__.py | 5 +- .../geometries/standard_format.py | 38 ++-- src/artist_pythonlib/geometries/thd_format.py | 67 +++--- src/artist_pythonlib/hardware/__init__.py | 11 +- .../hardware/base_hardware.py | 10 +- .../hardware/xray_detector.py | 33 ++- src/artist_pythonlib/hardware/xray_source.py | 62 +++--- src/artist_pythonlib/remote_connection.py | 83 ++++---- src/artist_pythonlib/trajectory/__init__.py | 21 +- .../trajectory/ct_trajectories.py | 88 +++++--- src/artist_pythonlib/utility/__init__.py | 5 +- .../utility/load_projection.py | 11 +- 15 files changed, 361 insertions(+), 287 deletions(-) diff --git a/src/artist_pythonlib/__init__.py b/src/artist_pythonlib/__init__.py index 96febeb..2aa4ad2 100644 --- a/src/artist_pythonlib/__init__.py +++ b/src/artist_pythonlib/__init__.py @@ -4,17 +4,9 @@ .. include:: ./documentation.md """ - - from .remote_connection import Junction from .api import API from .common_types import SAVEMODES, SOURCETYPES, PROJECTIONGEOMETRIES -__all__ = [ - 'SAVEMODES', - 'SOURCETYPES', - 'PROJECTIONGEOMETRIES', - 'Junction', - 'API' -] \ No newline at end of file +__all__ = ["SAVEMODES", "SOURCETYPES", "PROJECTIONGEOMETRIES", "Junction", "API"] diff --git a/src/artist_pythonlib/api.py b/src/artist_pythonlib/api.py index 1e9ac9f..b3ecc79 100644 --- a/src/artist_pythonlib/api.py +++ b/src/artist_pythonlib/api.py @@ -1,11 +1,11 @@ # Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -24,7 +24,7 @@ from artist_pythonlib.remote_connection import Junction, _rc -class API(): +class API: def __init__(self, remote_control: Junction = None) -> None: if remote_control is None: remote_control = _rc @@ -32,7 +32,7 @@ def __init__(self, remote_control: Junction = None) -> None: @staticmethod def path_to_artist(path: Path) -> str: - return str(path.absolute()).replace('\\', '\\\\') + return str(path.absolute()).replace("\\", "\\\\") def get_image(self) -> np.ndarray: """Make a projection of the current scene. @@ -40,14 +40,16 @@ def get_image(self) -> np.ndarray: Returns: np.ndarray: projection as ndarray. """ - self.rc.send('set imgList [Engine::Go]') - self.rc.send('RemoteControl::SendImage [lindex $imgList 0]') + self.rc.send("set imgList [Engine::Go]") + self.rc.send("RemoteControl::SendImage [lindex $imgList 0]") return self.rc.get_image() - - def save_image(self, - save_path: Path, - save_mode: SAVEMODES = SAVEMODES.UINT16, - save_projection_geometry: PROJECTIONGEOMETRIES = PROJECTIONGEOMETRIES.NONE): + + def save_image( + self, + save_path: Path, + save_mode: SAVEMODES = SAVEMODES.UINT16, + save_projection_geometry: PROJECTIONGEOMETRIES = PROJECTIONGEOMETRIES.NONE, + ): """Save the current scene as projection. The projection geometry can be stored in a .json file. Args: @@ -57,24 +59,18 @@ def save_image(self, """ save_path = save_path.resolve() if save_projection_geometry > 0: - - if save_projection_geometry == PROJECTIONGEOMETRIES.THD: geom = self.projection_geometry(save_projection_geometry) name = f'{save_path.stem}_{geom["header"]["uuid"]}' - save_path = save_path.parent / f'{name}.tif' - save_path_json = save_path.parent / f'{name}.json' + save_path = save_path.parent / f"{name}.tif" + save_path_json = save_path.parent / f"{name}.json" else: - save_path_json = save_path.parent / f'{save_path.stem}.json' - - - - with open(str(save_path_json), 'w') as f: + save_path_json = save_path.parent / f"{save_path.stem}.json" + + with open(str(save_path_json), "w") as f: json.dump(geom, f, indent=4) - - - + if save_mode == SAVEMODES.UINT8: self._save_image_uint8(save_path) elif save_mode == SAVEMODES.UINT16: @@ -85,7 +81,7 @@ def save_image(self, self._save_image_float_raw(save_path) elif save_mode == SAVEMODES.PNG: self._save_image_png(save_path) - + def _save_image_uint16(self, save_path: Path): """Saves the current scene as projection (.tif) and geometry (.json). @@ -93,8 +89,10 @@ def _save_image_uint16(self, save_path: Path): save_path (Path): Save path of the projection. """ # self.rc.send('set imgList [Engine::Go]') - save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') - self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') + save_path_projection = str(save_path.absolute()).replace("\\", "\\\\") + self.rc.send( + f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}' + ) def _save_image_uint8(self, save_path: Path): """Saves the current scene as projection (.tif) and geometry (.json). @@ -103,11 +101,15 @@ def _save_image_uint8(self, save_path: Path): save_path (Path): Save path of the projection. """ # self.rc.send('set imgList [Engine::Go]') - save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') - save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', - self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') - - with open(str(save_path_json), 'w') as f: + save_path_projection = str(save_path.absolute()).replace("\\", "\\\\") + save_path_json = ( + save_path.parent / (save_path.stem + ".json") + ) # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', + self.rc.send( + f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}' + ) + + with open(str(save_path_json), "w") as f: json.dump(self.projection_geometry(), f, indent=4) def _save_image_float_tiff(self, save_path: Path): @@ -117,10 +119,11 @@ def _save_image_float_tiff(self, save_path: Path): save_path (Path): Save path of the projection. """ # self.rc.send('set imgList [Engine::Go]') - save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') - self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') + save_path_projection = str(save_path.absolute()).replace("\\", "\\\\") + self.rc.send( + f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}' + ) # self.rc.send('foreach i $imgList {$i Delete}') - def _save_image_float_raw(self, save_path: Path): """Saves the current scene as projection (.raw) and geometry (.json). @@ -129,11 +132,15 @@ def _save_image_float_raw(self, save_path: Path): save_path (Path): Save path of the projection. """ # self.rc.send('set imgList [Engine::Go]') - save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') - save_path_json = save_path.parent / (save_path.stem + '.json') # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', - self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') - - with open(str(save_path_json), 'w') as f: + save_path_projection = str(save_path.absolute()).replace("\\", "\\\\") + save_path_json = ( + save_path.parent / (save_path.stem + ".json") + ) # Image::SaveFile [lindex $imgList 0] [file join $env(HOME) Pictures/artistlib2.tif] true', + self.rc.send( + f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}' + ) + + with open(str(save_path_json), "w") as f: json.dump(self.projection_geometry(), f, indent=4) def _save_image_png(self, save_path: Path): @@ -143,10 +150,14 @@ def _save_image_png(self, save_path: Path): save_path (Path): Save path of the projection. """ # self.rc.send('set imgList [Engine::Go]') - save_path_projection = str(save_path.absolute()).replace('\\', '\\\\') - self.rc.send(f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}') - - def translate(self, id: int | str, x: float = 0.0, y: float = 0.0, z: float = 0.0) -> None: + save_path_projection = str(save_path.absolute()).replace("\\", "\\\\") + self.rc.send( + f'set imgList [Engine::Go]; Image::SaveFloatTIFF [lindex $imgList 0] {save_path_projection} True; {r"foreach i $imgList {$i Delete}"}' + ) + + def translate( + self, id: int | str, x: float = 0.0, y: float = 0.0, z: float = 0.0 + ) -> None: """Moves an object to an absolute position. All values in [mm]. Args: @@ -155,8 +166,12 @@ def translate(self, id: int | str, x: float = 0.0, y: float = 0.0, z: float = 0. y (float, optional): Absolute Y position. Defaults to 0.0. z (float, optional): Absolute Z position. Defaults to 0.0. """ - self.rc.send(f'::PartList::Invoke {str(id)} SetPosition {str(x)} {str(y)} {str(z)};') - self.rc.send(f'::PartList::Invoke {str(id)} SetRefPos {str(x)} {str(y)} {str(z)};') + self.rc.send( + f"::PartList::Invoke {str(id)} SetPosition {str(x)} {str(y)} {str(z)};" + ) + self.rc.send( + f"::PartList::Invoke {str(id)} SetRefPos {str(x)} {str(y)} {str(z)};" + ) def scale(self, id: int | str, x: float = 1.0) -> None: """Moves an object to an absolute position. All values in [mm]. @@ -167,9 +182,13 @@ def scale(self, id: int | str, x: float = 1.0) -> None: y (float, optional): Absolute Y position. Defaults to 0.0. z (float, optional): Absolute Z position. Defaults to 0.0. """ - self.rc.send(f'::PartList::Invoke {str(id)} SetScale {str(x)} {str(x)} {str(x)};') + self.rc.send( + f"::PartList::Invoke {str(id)} SetScale {str(x)} {str(x)} {str(x)};" + ) - def rotate(self, id: int | str, alpha: float = 0.0, beta: float = 0.0, gamma: float = 0.0) -> None: + def rotate( + self, id: int | str, alpha: float = 0.0, beta: float = 0.0, gamma: float = 0.0 + ) -> None: """Rotates an object to an absolute position. All values in [°]. Args: @@ -179,10 +198,16 @@ def rotate(self, id: int | str, alpha: float = 0.0, beta: float = 0.0, gamma: fl gamma (float, optional): Absolute gamma rotation. Defaults to 0.0. """ position = self.get_position(id) - self.rc.send(f'::PartList::Invoke {str(id)} SetRefPos {str(position[0])} {str(position[1])} {str(position[2])};') - self.rc.send(f'::PartList::Invoke {str(id)} SetOrientation {str(alpha)} {str(beta)} {str(gamma)};') - - def rotate_from_rotation_matrix(self, id: int | str, rotation_matrix: np.ndarray) -> None: + self.rc.send( + f"::PartList::Invoke {str(id)} SetRefPos {str(position[0])} {str(position[1])} {str(position[2])};" + ) + self.rc.send( + f"::PartList::Invoke {str(id)} SetOrientation {str(alpha)} {str(beta)} {str(gamma)};" + ) + + def rotate_from_rotation_matrix( + self, id: int | str, rotation_matrix: np.ndarray + ) -> None: """Rotates an object to an absolute position. Args: @@ -201,8 +226,10 @@ def rotate_from_quat(self, id: int | str, qaurternion: np.ndarray) -> None: id (int | str): ID of the Object. qaurternion (np.ndarray): Quarternion in world coordinate system. """ - self.rotate_from_rotation_matrix(id, Rotation.from_quat(qaurternion).as_matrix()) - + self.rotate_from_rotation_matrix( + id, Rotation.from_quat(qaurternion).as_matrix() + ) + def get_position(self, id: int | str) -> np.ndarray: """Returns the current position of the object in [mm]. @@ -212,9 +239,9 @@ def get_position(self, id: int | str) -> np.ndarray: Returns: np.ndarray: position (x,y,z) in [mm]. """ - result = self.rc.send(f'[::PartList::Get {id} Obj] GetPosition') + result = self.rc.send(f"[::PartList::Get {id} Obj] GetPosition") return np.float32(result[1:-1].split(" ")) - + def get_euler_angles(self, id: int | str) -> np.ndarray: """Returns the current orientation of the object as euler angles in the ZXY convention. @@ -225,9 +252,9 @@ def get_euler_angles(self, id: int | str) -> np.ndarray: Returns: np.ndarray: Euler angle in ZXY convention. """ - result = self.rc.send(f'[::PartList::Get {id} Obj] GetOrientation') + result = self.rc.send(f"[::PartList::Get {id} Obj] GetOrientation") return np.float32(result[1:-1].split(" ")) - + def get_rotation_matrix(self, id: int | str) -> np.ndarray: euler_angles = self.get_euler_angles(id) @@ -246,7 +273,7 @@ def get_rotation_matrix(self, id: int | str) -> np.ndarray: # rotation = rotation.dot(R_z) return rotation - + def get_orientation(self, id) -> np.ndarray: """Return the current orientation of the object as quaternion. @@ -258,13 +285,15 @@ def get_orientation(self, id) -> np.ndarray: """ rotation = Rotation.from_matrix(self.get_rotation_matrix(id)) return rotation.as_quat() - - def projection_geometry(self, mode: PROJECTIONGEOMETRIES = PROJECTIONGEOMETRIES.THD) -> dict: + + def projection_geometry( + self, mode: PROJECTIONGEOMETRIES = PROJECTIONGEOMETRIES.THD + ) -> dict: """Returns the current projection geometry of the scene. All positions are in [mm]. Returns: - dict: Dictionary of the projection geometry. Keys are: 'focal_spot_position_mm', - 'focal_spot_orientation_matrix', 'detector_center_position_mm', + dict: Dictionary of the projection geometry. Keys are: 'focal_spot_position_mm', + 'focal_spot_orientation_matrix', 'detector_center_position_mm', 'detector_center_orientation_matrix', 'detector_center_orientation_quat', 'detector_count_px' and 'detector_resolution_mm' """ @@ -279,7 +308,7 @@ def get_detector_resolution(self) -> np.ndarray: Returns: np.ndarray: Pixel pitch of the detector (u, v). """ - result = self.rc.send('::XDetector::GetResolution') + result = self.rc.send("::XDetector::GetResolution") return np.array(np.float32(result.split(" "))) def get_detector_pixel_count(self) -> np.ndarray: @@ -288,9 +317,9 @@ def get_detector_pixel_count(self) -> np.ndarray: Returns: np.ndarray: Pixel count (u, v). """ - result = self.rc.send('::XDetector::GetPixelSize') + result = self.rc.send("::XDetector::GetPixelSize") return np.array(np.int32(result.split(" "))) - + def set_material(self, id: int | str, material: str): """Changes the material of the object. @@ -298,7 +327,7 @@ def set_material(self, id: int | str, material: str): id (int | str): ID of the Object. material (str): Matiral as string. !!!Must be in the material database of artist!!! """ - self.rc.send(f'::PartList::SetMaterial {material} {id}') + self.rc.send(f"::PartList::SetMaterial {material} {id}") def get_material(self, id: int | str): """Returns the material of the object. @@ -306,10 +335,12 @@ def get_material(self, id: int | str): Args: id (int | str): ID of the Object. """ - return_value = self.rc.send(f'::PartList::Get {id} Material') + return_value = self.rc.send(f"::PartList::Get {id} Material") return return_value - def load_part(self, load_path: Path, material: str = 'Al', name: str = 'Object') -> int: + def load_part( + self, load_path: Path, material: str = "Al", name: str = "Object" + ) -> int: """Loads a mesh file into the artist scene. Returns the object id for further mainpulations. Args: @@ -320,9 +351,11 @@ def load_part(self, load_path: Path, material: str = 'Al', name: str = 'Object') Returns: int: Object ID for further Manipulations. """ - return_value = self.rc.send(f'set obj [::PartList::LoadPart "{self.path_to_artist(load_path)}" "{material}" "{name}"]') + return_value = self.rc.send( + f'set obj [::PartList::LoadPart "{self.path_to_artist(load_path)}" "{material}" "{name}"]' + ) return int(return_value) - + def delete_part(self, id: int | str): """Delets the object from the scene. @@ -338,16 +371,18 @@ def set_visibility(self, id: int | str, visible: bool = True): id (int | str): ID of the Object. visible (bool, optional): Visible: True. Defaults to True. """ - visible = 'on' if visible else 'off' + visible = "on" if visible else "off" self.rc.send(f'[::PartList::Get {id} Obj] SetVisibility "{visible}"') def clear_scene(self): - """Clears all objects from the scene. - """ - self.rc.send('::PartList::Clear') + """Clears all objects from the scene.""" + self.rc.send("::PartList::Clear") def load_project(self, project_file: Path): - if project_file.suffix != '.aRTist': - raise ValueError('Wrong File / Path. The *project_file* path must be a .aRTist File!') - self.rc.send(f'::XRayProject::LoadProject "{self.path_to_artist(project_file)}"') - + if project_file.suffix != ".aRTist": + raise ValueError( + "Wrong File / Path. The *project_file* path must be a .aRTist File!" + ) + self.rc.send( + f'::XRayProject::LoadProject "{self.path_to_artist(project_file)}"' + ) diff --git a/src/artist_pythonlib/common_types.py b/src/artist_pythonlib/common_types.py index 15c602b..c83a03a 100644 --- a/src/artist_pythonlib/common_types.py +++ b/src/artist_pythonlib/common_types.py @@ -1,11 +1,11 @@ # Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,10 +14,12 @@ from enum import IntEnum + class SOURCETYPES(IntEnum): MONOCHROMATIC = 0 GENERAL = 1 + class SAVEMODES(IntEnum): UINT8 = 0 UINT16 = 1 @@ -25,7 +27,8 @@ class SAVEMODES(IntEnum): FLOAT_RAW = 3 PNG = 4 + class PROJECTIONGEOMETRIES(IntEnum): NONE = 0 STANDARD = 1 - THD = 2 \ No newline at end of file + THD = 2 diff --git a/src/artist_pythonlib/geometries/__init__.py b/src/artist_pythonlib/geometries/__init__.py index 103bd15..890a2cb 100644 --- a/src/artist_pythonlib/geometries/__init__.py +++ b/src/artist_pythonlib/geometries/__init__.py @@ -1,7 +1,4 @@ from .standard_format import projection_geometry from .thd_format import thd_projection_geometry -__all__ = [ - 'projection_geometry', - 'thd_projection_geometry' -] \ No newline at end of file +__all__ = ["projection_geometry", "thd_projection_geometry"] diff --git a/src/artist_pythonlib/geometries/standard_format.py b/src/artist_pythonlib/geometries/standard_format.py index 89dabc3..144dcf5 100644 --- a/src/artist_pythonlib/geometries/standard_format.py +++ b/src/artist_pythonlib/geometries/standard_format.py @@ -8,28 +8,32 @@ def projection_geometry(api) -> dict: """Returns the current projection geometry of the scene. All positions are in [mm]. Returns: - dict: Dictionary of the projection geometry. Keys are: 'focal_spot_position_mm', - 'focal_spot_orientation_matrix', 'detector_center_position_mm', + dict: Dictionary of the projection geometry. Keys are: 'focal_spot_position_mm', + 'focal_spot_orientation_matrix', 'detector_center_position_mm', 'detector_center_orientation_matrix', 'detector_center_orientation_quat', 'detector_count_px' and 'detector_resolution_mm' """ - source_position = np.array(api.get_position('S')) - source_orientation = np.array(api.get_rotation_matrix('S')) - detector_position = np.array(api.get_position('D')) - detector_orientation = np.array(api.get_rotation_matrix('D')) + source_position = np.array(api.get_position("S")) + source_orientation = np.array(api.get_rotation_matrix("S")) + detector_position = np.array(api.get_position("D")) + detector_orientation = np.array(api.get_rotation_matrix("D")) detector_resolution = api.get_detector_resolution() detector_pixel_count = api.get_detector_pixel_count() data_dict = dict() - data_dict['focal_spot_position_mm'] = source_position.tolist() - data_dict['focal_spot_orientation_quat'] = Rotation.from_matrix(source_orientation).as_quat().tolist() - data_dict['detector_center_position_mm'] = detector_position.tolist() - data_dict['detector_center_orientation_quat'] = Rotation.from_matrix(detector_orientation).as_quat().tolist() - - data_dict['image_width_px'] = detector_pixel_count.tolist()[0] - data_dict['pixel_pitch_width_mm'] = detector_resolution.tolist()[0] - data_dict['image_height_px'] = detector_pixel_count.tolist()[1] - data_dict['pixel_pitch_height_mm'] = detector_resolution.tolist()[1] - - return data_dict \ No newline at end of file + data_dict["focal_spot_position_mm"] = source_position.tolist() + data_dict["focal_spot_orientation_quat"] = ( + Rotation.from_matrix(source_orientation).as_quat().tolist() + ) + data_dict["detector_center_position_mm"] = detector_position.tolist() + data_dict["detector_center_orientation_quat"] = ( + Rotation.from_matrix(detector_orientation).as_quat().tolist() + ) + + data_dict["image_width_px"] = detector_pixel_count.tolist()[0] + data_dict["pixel_pitch_width_mm"] = detector_resolution.tolist()[0] + data_dict["image_height_px"] = detector_pixel_count.tolist()[1] + data_dict["pixel_pitch_height_mm"] = detector_resolution.tolist()[1] + + return data_dict diff --git a/src/artist_pythonlib/geometries/thd_format.py b/src/artist_pythonlib/geometries/thd_format.py index e7e0911..0614591 100644 --- a/src/artist_pythonlib/geometries/thd_format.py +++ b/src/artist_pythonlib/geometries/thd_format.py @@ -1,26 +1,29 @@ import numpy as np from scipy.spatial.transform import Rotation + try: from thd_json.header import generate_header except ModuleNotFoundError: from warnings import warn - warn('The optional modules of `thd` is not installed. THD Json geometry is not available.') + warn( + "The optional modules of `thd` is not installed. THD Json geometry is not available." + ) def thd_projection_geometry(api) -> dict: """Returns the current projection geometry of the scene. All positions are in [mm]. Returns: - dict: Dictionary of the projection geometry. Keys are: 'focal_spot_position_mm', - 'focal_spot_orientation_matrix', 'detector_center_position_mm', + dict: Dictionary of the projection geometry. Keys are: 'focal_spot_position_mm', + 'focal_spot_orientation_matrix', 'detector_center_position_mm', 'detector_center_orientation_matrix', 'detector_center_orientation_quat', 'detector_count_px' and 'detector_resolution_mm' """ - source_position = np.array(api.get_position('S')) - source_orientation = np.array(api.get_rotation_matrix('S')) - detector_position = np.array(api.get_position('D')) - detector_orientation = np.array(api.get_rotation_matrix('D')) + source_position = np.array(api.get_position("S")) + source_orientation = np.array(api.get_rotation_matrix("S")) + detector_position = np.array(api.get_position("D")) + detector_orientation = np.array(api.get_rotation_matrix("D")) detector_resolution = api.get_detector_resolution() detector_pixel_count = api.get_detector_pixel_count() @@ -32,26 +35,30 @@ def thd_projection_geometry(api) -> dict: detector = dict() json_header = generate_header() - header_dict['uuid'] = json_header.uuid - header_dict['timestamp'] = json_header.timestamp - - projection_geometry['focal_spot_position_mm'] = source_position.tolist() - projection_geometry['focal_spot_orientation_quat'] = Rotation.from_matrix(source_orientation).as_quat().tolist() - projection_geometry['detector_center_position_mm'] = detector_position.tolist() - projection_geometry['detector_center_orientation_quat'] = Rotation.from_matrix(detector_orientation).as_quat().tolist() - - image['uuid'] = json_header.uuid - image['timestamp'] = json_header.timestamp - image['image_path'] = f'{json_header.uuid}.tif' - - detector['image_width_px'] = detector_pixel_count.tolist()[0] - detector['pixel_pitch_width_mm'] = detector_resolution.tolist()[0] - detector['image_height_px'] = detector_pixel_count.tolist()[1] - detector['pixel_pitch_height_mm'] = detector_resolution.tolist()[1] - - data_dict['projection_geometry'] = projection_geometry - data_dict['image'] = image - data_dict['detector'] = detector - data_dict['header'] = header_dict - - return data_dict \ No newline at end of file + header_dict["uuid"] = json_header.uuid + header_dict["timestamp"] = json_header.timestamp + + projection_geometry["focal_spot_position_mm"] = source_position.tolist() + projection_geometry["focal_spot_orientation_quat"] = ( + Rotation.from_matrix(source_orientation).as_quat().tolist() + ) + projection_geometry["detector_center_position_mm"] = detector_position.tolist() + projection_geometry["detector_center_orientation_quat"] = ( + Rotation.from_matrix(detector_orientation).as_quat().tolist() + ) + + image["uuid"] = json_header.uuid + image["timestamp"] = json_header.timestamp + image["image_path"] = f"{json_header.uuid}.tif" + + detector["image_width_px"] = detector_pixel_count.tolist()[0] + detector["pixel_pitch_width_mm"] = detector_resolution.tolist()[0] + detector["image_height_px"] = detector_pixel_count.tolist()[1] + detector["pixel_pitch_height_mm"] = detector_resolution.tolist()[1] + + data_dict["projection_geometry"] = projection_geometry + data_dict["image"] = image + data_dict["detector"] = detector + data_dict["header"] = header_dict + + return data_dict diff --git a/src/artist_pythonlib/hardware/__init__.py b/src/artist_pythonlib/hardware/__init__.py index ef5f600..e675328 100644 --- a/src/artist_pythonlib/hardware/__init__.py +++ b/src/artist_pythonlib/hardware/__init__.py @@ -1,11 +1,11 @@ # Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -15,7 +15,4 @@ from .xray_source import XraySource from .xray_detector import XrayDetector -__all__ = [ - 'XraySource', - 'XrayDetector' -] \ No newline at end of file +__all__ = ["XraySource", "XrayDetector"] diff --git a/src/artist_pythonlib/hardware/base_hardware.py b/src/artist_pythonlib/hardware/base_hardware.py index 10a13cf..782cb37 100644 --- a/src/artist_pythonlib/hardware/base_hardware.py +++ b/src/artist_pythonlib/hardware/base_hardware.py @@ -1,11 +1,11 @@ # Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,7 +17,7 @@ from ..api import API -class BaseHardware(): +class BaseHardware: def __init__(self, remote_control: Junction | API = None) -> None: if isinstance(remote_control, Junction): self.rc = remote_control @@ -26,4 +26,4 @@ def __init__(self, remote_control: Junction | API = None) -> None: elif remote_control is None: self.rc = _rc else: - raise ValueError('Wrong remote_control argument?') + raise ValueError("Wrong remote_control argument?") diff --git a/src/artist_pythonlib/hardware/xray_detector.py b/src/artist_pythonlib/hardware/xray_detector.py index 1d3f8a6..5e4a094 100644 --- a/src/artist_pythonlib/hardware/xray_detector.py +++ b/src/artist_pythonlib/hardware/xray_detector.py @@ -1,11 +1,11 @@ # Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -36,14 +36,14 @@ def detector_resolution_mm(self) -> np.ndarray: Returns: np.ndarray: Detector resolution (u, v) in [mm]. """ - return_value = self.rc.send('::XDetector::GetResolution') - return_value = np.array(np.float32(return_value.split(" "))) + return_value = self.rc.send("::XDetector::GetResolution") + return_value = np.array(np.float32(return_value.split(" "))) return return_value - + @detector_resolution_mm.setter def detector_resolution_mm(self, detector_resolution_mm: np.ndarray) -> None: - self.rc.send(f'set ::Xsetup_private(DGdx) {detector_resolution_mm[0]}') - self.rc.send(f'set ::Xsetup_private(DGdy) {detector_resolution_mm[1]}') + self.rc.send(f"set ::Xsetup_private(DGdx) {detector_resolution_mm[0]}") + self.rc.send(f"set ::Xsetup_private(DGdy) {detector_resolution_mm[1]}") @property def detector_count_px(self) -> np.ndarray: @@ -52,14 +52,14 @@ def detector_count_px(self) -> np.ndarray: Returns: np.ndarray: Detector pixel count (u, v) in [n]. """ - return_value = self.rc.send('::XDetector::GetPixelSize') - return_value = np.array(np.int32(return_value.split(" "))) + return_value = self.rc.send("::XDetector::GetPixelSize") + return_value = np.array(np.int32(return_value.split(" "))) return return_value - + @detector_count_px.setter def detector_count_px(self, detector_count_px: np.ndarray) -> None: - self.rc.send(f'set ::Xsetup(DetectorPixelX) {detector_count_px[0]}') - self.rc.send(f'set ::Xsetup(DetectorPixelY) {detector_count_px[1]}') + self.rc.send(f"set ::Xsetup(DetectorPixelX) {detector_count_px[0]}") + self.rc.send(f"set ::Xsetup(DetectorPixelY) {detector_count_px[1]}") @property def flatfield_correction(self) -> bool: @@ -68,9 +68,6 @@ def flatfield_correction(self) -> bool: Returns: bool: Return wheter the projection is flatfield corrected or not. """ - return_value = self.rc.send('array get Xdetector FFCorrRun') - return_value = return_value.split(' ')[1] + return_value = self.rc.send("array get Xdetector FFCorrRun") + return_value = return_value.split(" ")[1] return bool(return_value) - - - diff --git a/src/artist_pythonlib/hardware/xray_source.py b/src/artist_pythonlib/hardware/xray_source.py index ab740a8..f1f7878 100644 --- a/src/artist_pythonlib/hardware/xray_source.py +++ b/src/artist_pythonlib/hardware/xray_source.py @@ -1,11 +1,11 @@ # Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -29,7 +29,7 @@ def __init__(self, remote_control: Junction | API = None) -> None: remote_control (Junction | API, optional): remote connection to communicate with aRTist. Defaults to None. """ super().__init__(remote_control) - + @property def voltage_kv(self) -> float: """Current voltage setting of the XRay source. @@ -37,14 +37,14 @@ def voltage_kv(self) -> float: Returns: float: Voltage value in [kV]. """ - return_value = self.rc.send('array get Xsource Voltage') - return_value = return_value.split(' ')[1] + return_value = self.rc.send("array get Xsource Voltage") + return_value = return_value.split(" ")[1] return float(return_value) - + @voltage_kv.setter def voltage_kv(self, voltage_kv: float) -> None: - self.rc.send(f'set ::Xsource(Voltage) {voltage_kv}') - self.rc.send('::XSource::ComputeSpectrum') + self.rc.send(f"set ::Xsource(Voltage) {voltage_kv}") + self.rc.send("::XSource::ComputeSpectrum") @property def exposure_ma(self) -> float: @@ -53,13 +53,13 @@ def exposure_ma(self) -> float: Returns: float: Exposure in [µA]. """ - return_value = self.rc.send('array get Xsource Exposure') - return_value = return_value.split(' ')[1] + return_value = self.rc.send("array get Xsource Exposure") + return_value = return_value.split(" ")[1] return float(return_value) - + @exposure_ma.setter def exposure_ma(self, exposure_ma: float) -> None: - self.rc.send(f'set ::Xsource(Exposure) {exposure_ma}') + self.rc.send(f"set ::Xsource(Exposure) {exposure_ma}") @property def filter_material(self) -> str: @@ -68,14 +68,14 @@ def filter_material(self) -> str: Returns: str: Filter material of the XRay source. """ - return_value = self.rc.send('array get Xsource FilterMaterial') - return_value = return_value.split(' ')[1] + return_value = self.rc.send("array get Xsource FilterMaterial") + return_value = return_value.split(" ")[1] return str(return_value) - + @filter_material.setter def filter_material(self, filter_material: float) -> None: - self.rc.send(f'set ::Xsource(FilterMaterial) {filter_material}') - self.rc.send('::XSource::ComputeSpectrum') + self.rc.send(f"set ::Xsource(FilterMaterial) {filter_material}") + self.rc.send("::XSource::ComputeSpectrum") @property def filter_thickness_mm(self) -> float: @@ -84,14 +84,14 @@ def filter_thickness_mm(self) -> float: Returns: float: Filter thickness in [mm]. """ - return_value = self.rc.send('array get Xsource FilterThickness') - return_value = return_value.split(' ')[1] + return_value = self.rc.send("array get Xsource FilterThickness") + return_value = return_value.split(" ")[1] return float(return_value) - + @filter_thickness_mm.setter def filter_thickness_mm(self, filter_thickness_mm: float) -> None: - self.rc.send(f'set ::Xsource(FilterThickness) {filter_thickness_mm}') - self.rc.send('::XSource::ComputeSpectrum') + self.rc.send(f"set ::Xsource(FilterThickness) {filter_thickness_mm}") + self.rc.send("::XSource::ComputeSpectrum") @property def source_type(self) -> int: @@ -100,18 +100,18 @@ def source_type(self) -> int: Returns: int: Source type as integer. Use SOURCETYPES. """ - return_value = self.rc.send('array get Xsource Tube') - return_value = return_value.split(' ')[1] + return_value = self.rc.send("array get Xsource Tube") + return_value = return_value.split(" ")[1] - if str(return_value).startswith('Mono'): + if str(return_value).startswith("Mono"): return SOURCETYPES.MONOCHROMATIC - elif str(return_value).startswith('General'): + elif str(return_value).startswith("General"): return SOURCETYPES.GENERAL - + @source_type.setter def source_type(self, source_type: SOURCETYPES) -> None: if source_type == SOURCETYPES.MONOCHROMATIC: - self.rc.send('set ::Xsource(Tube) Mono') + self.rc.send("set ::Xsource(Tube) Mono") elif source_type == SOURCETYPES.GENERAL: - self.rc.send('set ::Xsource(Tube) General') - self.rc.send('::XSource::ComputeSpectrum') + self.rc.send("set ::Xsource(Tube) General") + self.rc.send("::XSource::ComputeSpectrum") diff --git a/src/artist_pythonlib/remote_connection.py b/src/artist_pythonlib/remote_connection.py index e1d2c50..a5163a8 100644 --- a/src/artist_pythonlib/remote_connection.py +++ b/src/artist_pythonlib/remote_connection.py @@ -1,11 +1,11 @@ # Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -20,8 +20,8 @@ class Junction: - """Remote control of aRTist simulator (this is a test) - """ + """Remote control of aRTist simulator (this is a test)""" + def __init__(self, host="localhost", port=3658, bufferSize=1024, timeout=10): self.host = host self.port = port @@ -35,77 +35,83 @@ def __init__(self, host="localhost", port=3658, bufferSize=1024, timeout=10): def connect(self): try: - self.S = socket.socket() # Create socket (for TCP) - self.S.connect((self.host, self.port)) # Connect to aRTist + self.S = socket.socket() # Create socket (for TCP) + self.S.connect((self.host, self.port)) # Connect to aRTist self.S.settimeout(self.timeout) self.S.setblocking(True) self.listen(0) except ConnectionRefusedError: - print('The Connection to aRTist was refused. Is aRTist running and the remote connection enabled?') + print( + "The Connection to aRTist was refused. Is aRTist running and the remote connection enabled?" + ) except Exception as e: raise e return self def send(self, command, msgType="RESULT"): - c = command + '\n' + c = command + "\n" self.S.send(c.encode()) return self.listen(msgType=msgType) def listen(self, command_no=1, msgType="RESULT"): answer = "" stop = False - if (command_no == 0): + if command_no == 0: self.S.settimeout(0.2) - while (not stop):# and ("SUCCESS" not in total) and ("ERROR" not in total): # Solange server antwortet und nicht "SUCCESS" enthält + while not stop: # and ("SUCCESS" not in total) and ("ERROR" not in total): # Solange server antwortet und nicht "SUCCESS" enthält try: msg = self.S.recv(self.bufferSize).decode() except BaseException as e: err = e.args[0] if err == "timed out": - #print("Timeout\n") + # print("Timeout\n") answer += "RESULT Timeout\n" - #print(answer) + # print(answer) stop = True continue else: - if ("SUCCESS" in msg): + if "SUCCESS" in msg: answer += msg stop = True continue - elif ("ERROR" in msg): + elif "ERROR" in msg: answer += msg stop = True - #global error - self.error = self.error + 1 + # global error + self.error = self.error + 1 continue - elif ("PROGRESS" in msg): + elif "PROGRESS" in msg: try: - self.progress = float(msg.strip('PROGRESS ')) + self.progress = float(msg.strip("PROGRESS ")) except ValueError: self.progress = 0 continue else: - if (command_no == 0): + if command_no == 0: print(msg) answer += msg self.S.settimeout(self.timeout) - self.answer.update({"SUCCESS":self.pick(answer, "SUCCESS"), - "RESULT":self.pick(answer, "RESULT"), - "SDTOUT":self.pick(answer, "STDOUT"), - "BASE64":self.pick(answer, "BASE64"), - "IMAGE":self.pick(answer, "IMAGE"), - "FILE":self.pick(answer, "FILE")}) - if (msgType != "*"): + self.answer.update( + { + "SUCCESS": self.pick(answer, "SUCCESS"), + "RESULT": self.pick(answer, "RESULT"), + "SDTOUT": self.pick(answer, "STDOUT"), + "BASE64": self.pick(answer, "BASE64"), + "IMAGE": self.pick(answer, "IMAGE"), + "FILE": self.pick(answer, "FILE"), + } + ) + if msgType != "*": answer = self.pick(answer, msgType) return answer - def pick(self, answer, res='RESULT'): - picked = '' - for a in answer.split('\n'): + def pick(self, answer, res="RESULT"): + picked = "" + for a in answer.split("\n"): if a.find(res) == 0: - picked += a[1 + len(res):].strip('\r') + '\n' + picked += a[1 + len(res) :].strip("\r") + "\n" if len(picked) == 0: - return res + ' not found.' + return res + " not found." return picked def get_answer(self, key): @@ -115,7 +121,9 @@ def save_image(self, imageName: str): imageData = self.answer["BASE64"] decodedData = base64.b64decode((imageData)) imageHeader = self.answer["IMAGE"].split() - im = np.frombuffer(decodedData, np.double).reshape((int(imageHeader[1]),int(imageHeader[2]))) + im = np.frombuffer(decodedData, np.double).reshape( + (int(imageHeader[1]), int(imageHeader[2])) + ) Image.fromarray(im).save(imageName) def receive_file(self, fileName): @@ -141,6 +149,9 @@ def get_image(self) -> np.ndarray: decodedData = base64.b64decode((imageData)) imageHeader = self.answer["IMAGE"].split() dtype = np.double - return np.frombuffer(decodedData, dtype).reshape((int(imageHeader[1]),int(imageHeader[2]))) - -_rc = Junction() \ No newline at end of file + return np.frombuffer(decodedData, dtype).reshape( + (int(imageHeader[1]), int(imageHeader[2])) + ) + + +_rc = Junction() diff --git a/src/artist_pythonlib/trajectory/__init__.py b/src/artist_pythonlib/trajectory/__init__.py index dc88815..2d2d766 100644 --- a/src/artist_pythonlib/trajectory/__init__.py +++ b/src/artist_pythonlib/trajectory/__init__.py @@ -1,22 +1,27 @@ # Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. -from .ct_trajectories import circular_trajectory, look_at_orientation, sphere_trajectory, arbitary_circular_trajectory +from .ct_trajectories import ( + circular_trajectory, + look_at_orientation, + sphere_trajectory, + arbitary_circular_trajectory, +) __all__ = [ - 'circular_trajectory', - 'look_at_orientation', - 'sphere_trajectory', - 'arbitary_circular_trajectory' + "circular_trajectory", + "look_at_orientation", + "sphere_trajectory", + "arbitary_circular_trajectory", ] diff --git a/src/artist_pythonlib/trajectory/ct_trajectories.py b/src/artist_pythonlib/trajectory/ct_trajectories.py index 26a8a8a..3b2d464 100644 --- a/src/artist_pythonlib/trajectory/ct_trajectories.py +++ b/src/artist_pythonlib/trajectory/ct_trajectories.py @@ -1,11 +1,11 @@ # Copyright 2023 Simon Wittl (Deggendorf Institute of Technology) -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -17,22 +17,29 @@ from scipy.spatial.transform import Rotation -def circular_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int, opening_angle: float = 0.2) -> tuple[np.ndarray, np.ndarray, np.ndarray]: +def circular_trajectory( + fod_mm: float, fdd_mm: float, number_of_projections: int, opening_angle: float = 0.2 +) -> tuple[np.ndarray, np.ndarray, np.ndarray]: if fod_mm > fdd_mm: - raise ValueError('fod > fdd.') + raise ValueError("fod > fdd.") - rotation_angles = np.linspace(0., np.pi * (1. + opening_angle), number_of_projections, endpoint=False) - rotation_object = Rotation.from_euler('Y', rotation_angles, degrees=False) + rotation_angles = np.linspace( + 0.0, np.pi * (1.0 + opening_angle), number_of_projections, endpoint=False + ) + rotation_object = Rotation.from_euler("Y", rotation_angles, degrees=False) - source_initial_position = np.array([0., 0., fod_mm]) - detector_initial_position = np.array([0., 0., fod_mm - fdd_mm]) + source_initial_position = np.array([0.0, 0.0, fod_mm]) + detector_initial_position = np.array([0.0, 0.0, fod_mm - fdd_mm]) source_positions = rotation_object.apply(source_initial_position) detector_positions = rotation_object.apply(detector_initial_position) - + return source_positions, detector_positions, rotation_object.as_matrix() -def look_at_orientation(source, detector, up_vector: np.ndarray = np.array([0., 0., 1.])): + +def look_at_orientation( + source, detector, up_vector: np.ndarray = np.array([0.0, 0.0, 1.0]) +): normal = source - detector normal = normal / np.linalg.norm(normal) @@ -40,9 +47,9 @@ def look_at_orientation(source, detector, up_vector: np.ndarray = np.array([0., line = np.cross(normal, up_vector) col = np.cross(line, normal) - + if np.sign(col[up_axis]) != np.sign(up_vector[up_axis]): - col *= -1. + col *= -1.0 line = np.cross(normal, col) @@ -52,37 +59,53 @@ def look_at_orientation(source, detector, up_vector: np.ndarray = np.array([0., rotation_matrix[:, 2] = normal if np.linalg.det(rotation_matrix) < 0.0: - rotation_matrix[:, np.argmax(up_vector)] *= -1. - + rotation_matrix[:, np.argmax(up_vector)] *= -1.0 + return rotation_matrix -def sphere_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int) -> tuple[np.ndarray, np.ndarray, np.ndarray]: + +def sphere_trajectory( + fod_mm: float, fdd_mm: float, number_of_projections: int +) -> tuple[np.ndarray, np.ndarray, np.ndarray]: phi = (1.0 + np.sqrt(5.0)) / 2.0 - start = -(number_of_projections - 1.) - end = number_of_projections - 1. + start = -(number_of_projections - 1.0) + end = number_of_projections - 1.0 i = np.linspace(start, end, number_of_projections) - theta = np.divide(2. * i * np.pi, phi) + theta = np.divide(2.0 * i * np.pi, phi) sphi = i / number_of_projections - cphi = np.sqrt((number_of_projections + i) * (number_of_projections - i)) / number_of_projections + cphi = ( + np.sqrt((number_of_projections + i) * (number_of_projections - i)) + / number_of_projections + ) point_array = np.zeros((number_of_projections, 3)) - + point_array[:, 0] = cphi * np.cos(theta) point_array[:, 1] = cphi * np.sin(theta) point_array[:, 2] = sphi source_positions = point_array * fod_mm detector_positions = point_array * (fod_mm - fdd_mm) - orientation = np.array(list(map(look_at_orientation, source_positions, detector_positions))) + orientation = np.array( + list(map(look_at_orientation, source_positions, detector_positions)) + ) return source_positions, detector_positions, orientation -def arbitary_circular_trajectory(fod_mm: float, fdd_mm: float, number_of_projections: int, transformation: np.ndarray = np.eye(4), opening_angle: float = 0.2): - source_positions, detector_positions, orientation = circular_trajectory(fod_mm, fdd_mm, number_of_projections, opening_angle) +def arbitary_circular_trajectory( + fod_mm: float, + fdd_mm: float, + number_of_projections: int, + transformation: np.ndarray = np.eye(4), + opening_angle: float = 0.2, +): + source_positions, detector_positions, orientation = circular_trajectory( + fod_mm, fdd_mm, number_of_projections, opening_angle + ) source_transformation_matrix = np.zeros((number_of_projections, 4, 4)) - source_transformation_matrix[:, 3, 3] = 1. + source_transformation_matrix[:, 3, 3] = 1.0 detector_transformation_matrix = source_transformation_matrix.copy() source_transformation_matrix[:, :3, 3] = source_positions @@ -93,9 +116,12 @@ def arbitary_circular_trajectory(fod_mm: float, fdd_mm: float, number_of_project transformation = np.expand_dims(transformation, 0) source_transformation_matrix = transformation @ source_transformation_matrix - detector_transformation_matrix = transformation @ detector_transformation_matrix - - return source_transformation_matrix[:, :3, 3].reshape((number_of_projections, 3)), detector_transformation_matrix[:, :3, 3].reshape((number_of_projections, 3)), detector_transformation_matrix[:, :3, :3].reshape((number_of_projections, 3, 3)) - - - + detector_transformation_matrix = transformation @ detector_transformation_matrix + + return ( + source_transformation_matrix[:, :3, 3].reshape((number_of_projections, 3)), + detector_transformation_matrix[:, :3, 3].reshape((number_of_projections, 3)), + detector_transformation_matrix[:, :3, :3].reshape( + (number_of_projections, 3, 3) + ), + ) diff --git a/src/artist_pythonlib/utility/__init__.py b/src/artist_pythonlib/utility/__init__.py index 65000c5..d4b84c8 100644 --- a/src/artist_pythonlib/utility/__init__.py +++ b/src/artist_pythonlib/utility/__init__.py @@ -1,6 +1,3 @@ from .load_projection import load_projection, load_header -__all__ = [ - 'load_projection', - 'load_header' -] \ No newline at end of file +__all__ = ["load_projection", "load_header"] diff --git a/src/artist_pythonlib/utility/load_projection.py b/src/artist_pythonlib/utility/load_projection.py index 4957056..0a46195 100644 --- a/src/artist_pythonlib/utility/load_projection.py +++ b/src/artist_pythonlib/utility/load_projection.py @@ -5,7 +5,9 @@ import time -def load_projection(projection_path: Path, load_projection_geometry: bool = True) -> tuple[np.ndarray, dict]: +def load_projection( + projection_path: Path, load_projection_geometry: bool = True +) -> tuple[np.ndarray, dict]: try: projection_array = np.array(Image.open(projection_path)) except FileNotFoundError: @@ -16,9 +18,10 @@ def load_projection(projection_path: Path, load_projection_geometry: bool = True return projection_array, None else: return projection_array, load_header(projection_path) - + + def load_header(projection_path) -> dict: - with open(str(projection_path.parent / f'{projection_path.stem}.json'), 'r') as f: + with open(str(projection_path.parent / f"{projection_path.stem}.json"), "r") as f: projection_geometry = json.load(f) - + return projection_geometry From f418f0cd007ecadd6c3a5c8d3626aeaad2252fa7 Mon Sep 17 00:00:00 2001 From: swittl Date: Wed, 20 Nov 2024 08:04:31 +0100 Subject: [PATCH 20/21] updated example --- examples/02_circular_trajectory.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/02_circular_trajectory.py b/examples/02_circular_trajectory.py index 70b114f..6e196ff 100644 --- a/examples/02_circular_trajectory.py +++ b/examples/02_circular_trajectory.py @@ -13,13 +13,15 @@ # limitations under the License. from __future__ import annotations -from matplotlib import pyplot as plt +from pathlib import Path -from artist_pythonlib import API +from artist_pythonlib import API, PROJECTIONGEOMETRIES from artist_pythonlib.trajectory import circular_trajectory NUMBER_OF_PROJECTIONS = 20 +SAVEFOLDER = Path('./workspace') / 'example_02' +SAVEFOLDER.mkdir(exist_ok=True) def main(): @@ -27,16 +29,14 @@ def main(): api = API() for i in range(NUMBER_OF_PROJECTIONS): - source, detector, beta_angles = trajectory[0][i], trajectory[1][i], trajectory[2][i] + source, detector, rotation_matrix = trajectory[0][i], trajectory[1][i], trajectory[2][i] api.translate('S', *source) api.translate('D', *detector) - api.rotate('S', beta=beta_angles) - api.rotate('D', beta=beta_angles) + api.rotate_from_rotation_matrix('S', rotation_matrix) + api.rotate_from_rotation_matrix('D', rotation_matrix) - image = api.get_image() - plt.imshow(image) - plt.show() + api.save_image(SAVEFOLDER / f'{i:03}.tif', save_projection_geometry=PROJECTIONGEOMETRIES.THD) if __name__ == '__main__': From 74d874e8b7989cd8383796fe9f08b5b3aa56c1a0 Mon Sep 17 00:00:00 2001 From: swittl Date: Wed, 20 Nov 2024 08:06:10 +0100 Subject: [PATCH 21/21] added xraydb for example --- examples/03_get_spectrum.py | 5 +- pyproject.toml | 1 + uv.lock | 132 ++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 4 deletions(-) diff --git a/examples/03_get_spectrum.py b/examples/03_get_spectrum.py index a1c722d..00ffdcb 100644 --- a/examples/03_get_spectrum.py +++ b/examples/03_get_spectrum.py @@ -1,10 +1,8 @@ -from artistlib import API +from artist_pythonlib import API import numpy as np from matplotlib import pyplot as plt from xraydb import mu_elam -import re -# Install xraydb: pip install xraydb def scrap_spectrum(artist_spectrum: str): try: @@ -19,7 +17,6 @@ def scrap_spectrum(artist_spectrum: str): raise ValueError('Ploychromatic Source must be set in aRTist!') - def get_current_artist_spcectrum(api: API) -> np.ndarray: return scrap_spectrum(api.rc.send('[Engine::GetSpectrum]')) diff --git a/pyproject.toml b/pyproject.toml index c76afce..82a88c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,6 +13,7 @@ dependencies = [ "pillow>=11.0.0", "scipy>=1.14.1", "thd-json>=0.1.0", + "xraydb>=4.5.4", ] [project.optional-dependencies] diff --git a/uv.lock b/uv.lock index 8debb34..f166e0a 100644 --- a/uv.lock +++ b/uv.lock @@ -11,6 +11,7 @@ dependencies = [ { name = "pillow" }, { name = "scipy" }, { name = "thd-json" }, + { name = "xraydb" }, ] [package.optional-dependencies] @@ -26,6 +27,7 @@ requires-dist = [ { name = "scipy", specifier = ">=1.14.1" }, { name = "thd-json", git = "https://mygit.th-deg.de/roboct/definitions/json_schemas" }, { name = "thd-json", marker = "extra == 'thd'", git = "https://mygit.th-deg.de/roboct/definitions/json_schemas" }, + { name = "xraydb", specifier = ">=4.5.4" }, ] [[package]] @@ -160,6 +162,57 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/b4/4a/786589606d4989cb34d8bc766cd687d955aaf3039c367fe7104bcf82dc98/fonttools-4.55.0-py3-none-any.whl", hash = "sha256:12db5888cd4dd3fcc9f0ee60c6edd3c7e1fd44b7dd0f31381ea03df68f8a153f", size = 1100249 }, ] +[[package]] +name = "greenlet" +version = "3.1.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2f/ff/df5fede753cc10f6a5be0931204ea30c35fa2f2ea7a35b25bdaf4fe40e46/greenlet-3.1.1.tar.gz", hash = "sha256:4ce3ac6cdb6adf7946475d7ef31777c26d94bccc377e070a7986bd2d5c515467", size = 186022 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/25/90/5234a78dc0ef6496a6eb97b67a42a8e96742a56f7dc808cb954a85390448/greenlet-3.1.1-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:0bbae94a29c9e5c7e4a2b7f0aae5c17e8e90acbfd3bf6270eeba60c39fce3563", size = 271235 }, + { url = "https://files.pythonhosted.org/packages/7c/16/cd631fa0ab7d06ef06387135b7549fdcc77d8d859ed770a0d28e47b20972/greenlet-3.1.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0fde093fb93f35ca72a556cf72c92ea3ebfda3d79fc35bb19fbe685853869a83", size = 637168 }, + { url = "https://files.pythonhosted.org/packages/2f/b1/aed39043a6fec33c284a2c9abd63ce191f4f1a07319340ffc04d2ed3256f/greenlet-3.1.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:36b89d13c49216cadb828db8dfa6ce86bbbc476a82d3a6c397f0efae0525bdd0", size = 648826 }, + { url = "https://files.pythonhosted.org/packages/76/25/40e0112f7f3ebe54e8e8ed91b2b9f970805143efef16d043dfc15e70f44b/greenlet-3.1.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94b6150a85e1b33b40b1464a3f9988dcc5251d6ed06842abff82e42632fac120", size = 644443 }, + { url = "https://files.pythonhosted.org/packages/fb/2f/3850b867a9af519794784a7eeed1dd5bc68ffbcc5b28cef703711025fd0a/greenlet-3.1.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:93147c513fac16385d1036b7e5b102c7fbbdb163d556b791f0f11eada7ba65dc", size = 643295 }, + { url = "https://files.pythonhosted.org/packages/cf/69/79e4d63b9387b48939096e25115b8af7cd8a90397a304f92436bcb21f5b2/greenlet-3.1.1-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:da7a9bff22ce038e19bf62c4dd1ec8391062878710ded0a845bcf47cc0200617", size = 599544 }, + { url = "https://files.pythonhosted.org/packages/46/1d/44dbcb0e6c323bd6f71b8c2f4233766a5faf4b8948873225d34a0b7efa71/greenlet-3.1.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b2795058c23988728eec1f36a4e5e4ebad22f8320c85f3587b539b9ac84128d7", size = 1125456 }, + { url = "https://files.pythonhosted.org/packages/e0/1d/a305dce121838d0278cee39d5bb268c657f10a5363ae4b726848f833f1bb/greenlet-3.1.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ed10eac5830befbdd0c32f83e8aa6288361597550ba669b04c48f0f9a2c843c6", size = 1149111 }, + { url = "https://files.pythonhosted.org/packages/96/28/d62835fb33fb5652f2e98d34c44ad1a0feacc8b1d3f1aecab035f51f267d/greenlet-3.1.1-cp310-cp310-win_amd64.whl", hash = "sha256:77c386de38a60d1dfb8e55b8c1101d68c79dfdd25c7095d51fec2dd800892b80", size = 298392 }, + { url = "https://files.pythonhosted.org/packages/28/62/1c2665558618553c42922ed47a4e6d6527e2fa3516a8256c2f431c5d0441/greenlet-3.1.1-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e4d333e558953648ca09d64f13e6d8f0523fa705f51cae3f03b5983489958c70", size = 272479 }, + { url = "https://files.pythonhosted.org/packages/76/9d/421e2d5f07285b6e4e3a676b016ca781f63cfe4a0cd8eaecf3fd6f7a71ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09fc016b73c94e98e29af67ab7b9a879c307c6731a2c9da0db5a7d9b7edd1159", size = 640404 }, + { url = "https://files.pythonhosted.org/packages/e5/de/6e05f5c59262a584e502dd3d261bbdd2c97ab5416cc9c0b91ea38932a901/greenlet-3.1.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d5e975ca70269d66d17dd995dafc06f1b06e8cb1ec1e9ed54c1d1e4a7c4cf26e", size = 652813 }, + { url = "https://files.pythonhosted.org/packages/49/93/d5f93c84241acdea15a8fd329362c2c71c79e1a507c3f142a5d67ea435ae/greenlet-3.1.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3b2813dc3de8c1ee3f924e4d4227999285fd335d1bcc0d2be6dc3f1f6a318ec1", size = 648517 }, + { url = "https://files.pythonhosted.org/packages/15/85/72f77fc02d00470c86a5c982b8daafdf65d38aefbbe441cebff3bf7037fc/greenlet-3.1.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e347b3bfcf985a05e8c0b7d462ba6f15b1ee1c909e2dcad795e49e91b152c383", size = 647831 }, + { url = "https://files.pythonhosted.org/packages/f7/4b/1c9695aa24f808e156c8f4813f685d975ca73c000c2a5056c514c64980f6/greenlet-3.1.1-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e8f8c9cb53cdac7ba9793c276acd90168f416b9ce36799b9b885790f8ad6c0a", size = 602413 }, + { url = "https://files.pythonhosted.org/packages/76/70/ad6e5b31ef330f03b12559d19fda2606a522d3849cde46b24f223d6d1619/greenlet-3.1.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:62ee94988d6b4722ce0028644418d93a52429e977d742ca2ccbe1c4f4a792511", size = 1129619 }, + { url = "https://files.pythonhosted.org/packages/f4/fb/201e1b932e584066e0f0658b538e73c459b34d44b4bd4034f682423bc801/greenlet-3.1.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1776fd7f989fc6b8d8c8cb8da1f6b82c5814957264d1f6cf818d475ec2bf6395", size = 1155198 }, + { url = "https://files.pythonhosted.org/packages/12/da/b9ed5e310bb8b89661b80cbcd4db5a067903bbcd7fc854923f5ebb4144f0/greenlet-3.1.1-cp311-cp311-win_amd64.whl", hash = "sha256:48ca08c771c268a768087b408658e216133aecd835c0ded47ce955381105ba39", size = 298930 }, + { url = "https://files.pythonhosted.org/packages/7d/ec/bad1ac26764d26aa1353216fcbfa4670050f66d445448aafa227f8b16e80/greenlet-3.1.1-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:4afe7ea89de619adc868e087b4d2359282058479d7cfb94970adf4b55284574d", size = 274260 }, + { url = "https://files.pythonhosted.org/packages/66/d4/c8c04958870f482459ab5956c2942c4ec35cac7fe245527f1039837c17a9/greenlet-3.1.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f406b22b7c9a9b4f8aa9d2ab13d6ae0ac3e85c9a809bd590ad53fed2bf70dc79", size = 649064 }, + { url = "https://files.pythonhosted.org/packages/51/41/467b12a8c7c1303d20abcca145db2be4e6cd50a951fa30af48b6ec607581/greenlet-3.1.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c3a701fe5a9695b238503ce5bbe8218e03c3bcccf7e204e455e7462d770268aa", size = 663420 }, + { url = "https://files.pythonhosted.org/packages/27/8f/2a93cd9b1e7107d5c7b3b7816eeadcac2ebcaf6d6513df9abaf0334777f6/greenlet-3.1.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2846930c65b47d70b9d178e89c7e1a69c95c1f68ea5aa0a58646b7a96df12441", size = 658035 }, + { url = "https://files.pythonhosted.org/packages/57/5c/7c6f50cb12be092e1dccb2599be5a942c3416dbcfb76efcf54b3f8be4d8d/greenlet-3.1.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99cfaa2110534e2cf3ba31a7abcac9d328d1d9f1b95beede58294a60348fba36", size = 660105 }, + { url = "https://files.pythonhosted.org/packages/f1/66/033e58a50fd9ec9df00a8671c74f1f3a320564c6415a4ed82a1c651654ba/greenlet-3.1.1-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1443279c19fca463fc33e65ef2a935a5b09bb90f978beab37729e1c3c6c25fe9", size = 613077 }, + { url = "https://files.pythonhosted.org/packages/19/c5/36384a06f748044d06bdd8776e231fadf92fc896bd12cb1c9f5a1bda9578/greenlet-3.1.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:b7cede291382a78f7bb5f04a529cb18e068dd29e0fb27376074b6d0317bf4dd0", size = 1135975 }, + { url = "https://files.pythonhosted.org/packages/38/f9/c0a0eb61bdf808d23266ecf1d63309f0e1471f284300ce6dac0ae1231881/greenlet-3.1.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:23f20bb60ae298d7d8656c6ec6db134bca379ecefadb0b19ce6f19d1f232a942", size = 1163955 }, + { url = "https://files.pythonhosted.org/packages/43/21/a5d9df1d21514883333fc86584c07c2b49ba7c602e670b174bd73cfc9c7f/greenlet-3.1.1-cp312-cp312-win_amd64.whl", hash = "sha256:7124e16b4c55d417577c2077be379514321916d5790fa287c9ed6f23bd2ffd01", size = 299655 }, + { url = "https://files.pythonhosted.org/packages/f3/57/0db4940cd7bb461365ca8d6fd53e68254c9dbbcc2b452e69d0d41f10a85e/greenlet-3.1.1-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:05175c27cb459dcfc05d026c4232f9de8913ed006d42713cb8a5137bd49375f1", size = 272990 }, + { url = "https://files.pythonhosted.org/packages/1c/ec/423d113c9f74e5e402e175b157203e9102feeb7088cee844d735b28ef963/greenlet-3.1.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:935e943ec47c4afab8965954bf49bfa639c05d4ccf9ef6e924188f762145c0ff", size = 649175 }, + { url = "https://files.pythonhosted.org/packages/a9/46/ddbd2db9ff209186b7b7c621d1432e2f21714adc988703dbdd0e65155c77/greenlet-3.1.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:667a9706c970cb552ede35aee17339a18e8f2a87a51fba2ed39ceeeb1004798a", size = 663425 }, + { url = "https://files.pythonhosted.org/packages/bc/f9/9c82d6b2b04aa37e38e74f0c429aece5eeb02bab6e3b98e7db89b23d94c6/greenlet-3.1.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b8a678974d1f3aa55f6cc34dc480169d58f2e6d8958895d68845fa4ab566509e", size = 657736 }, + { url = "https://files.pythonhosted.org/packages/d9/42/b87bc2a81e3a62c3de2b0d550bf91a86939442b7ff85abb94eec3fc0e6aa/greenlet-3.1.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:efc0f674aa41b92da8c49e0346318c6075d734994c3c4e4430b1c3f853e498e4", size = 660347 }, + { url = "https://files.pythonhosted.org/packages/37/fa/71599c3fd06336cdc3eac52e6871cfebab4d9d70674a9a9e7a482c318e99/greenlet-3.1.1-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0153404a4bb921f0ff1abeb5ce8a5131da56b953eda6e14b88dc6bbc04d2049e", size = 615583 }, + { url = "https://files.pythonhosted.org/packages/4e/96/e9ef85de031703ee7a4483489b40cf307f93c1824a02e903106f2ea315fe/greenlet-3.1.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:275f72decf9932639c1c6dd1013a1bc266438eb32710016a1c742df5da6e60a1", size = 1133039 }, + { url = "https://files.pythonhosted.org/packages/87/76/b2b6362accd69f2d1889db61a18c94bc743e961e3cab344c2effaa4b4a25/greenlet-3.1.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c4aab7f6381f38a4b42f269057aee279ab0fc7bf2e929e3d4abfae97b682a12c", size = 1160716 }, + { url = "https://files.pythonhosted.org/packages/1f/1b/54336d876186920e185066d8c3024ad55f21d7cc3683c856127ddb7b13ce/greenlet-3.1.1-cp313-cp313-win_amd64.whl", hash = "sha256:b42703b1cf69f2aa1df7d1030b9d77d3e584a70755674d60e710f0af570f3761", size = 299490 }, + { url = "https://files.pythonhosted.org/packages/5f/17/bea55bf36990e1638a2af5ba10c1640273ef20f627962cf97107f1e5d637/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1695e76146579f8c06c1509c7ce4dfe0706f49c6831a817ac04eebb2fd02011", size = 643731 }, + { url = "https://files.pythonhosted.org/packages/78/d2/aa3d2157f9ab742a08e0fd8f77d4699f37c22adfbfeb0c610a186b5f75e0/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7876452af029456b3f3549b696bb36a06db7c90747740c5302f74a9e9fa14b13", size = 649304 }, + { url = "https://files.pythonhosted.org/packages/f1/8e/d0aeffe69e53ccff5a28fa86f07ad1d2d2d6537a9506229431a2a02e2f15/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4ead44c85f8ab905852d3de8d86f6f8baf77109f9da589cb4fa142bd3b57b475", size = 646537 }, + { url = "https://files.pythonhosted.org/packages/05/79/e15408220bbb989469c8871062c97c6c9136770657ba779711b90870d867/greenlet-3.1.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8320f64b777d00dd7ccdade271eaf0cad6636343293a25074cc5566160e4de7b", size = 642506 }, + { url = "https://files.pythonhosted.org/packages/18/87/470e01a940307796f1d25f8167b551a968540fbe0551c0ebb853cb527dd6/greenlet-3.1.1-cp313-cp313t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6510bf84a6b643dabba74d3049ead221257603a253d0a9873f55f6a59a65f822", size = 602753 }, + { url = "https://files.pythonhosted.org/packages/e2/72/576815ba674eddc3c25028238f74d7b8068902b3968cbe456771b166455e/greenlet-3.1.1-cp313-cp313t-musllinux_1_1_aarch64.whl", hash = "sha256:04b013dc07c96f83134b1e99888e7a79979f1a247e2a9f59697fa14b5862ed01", size = 1122731 }, + { url = "https://files.pythonhosted.org/packages/ac/38/08cc303ddddc4b3d7c628c3039a61a3aae36c241ed01393d00c2fd663473/greenlet-3.1.1-cp313-cp313t-musllinux_1_1_x86_64.whl", hash = "sha256:411f015496fec93c1c8cd4e5238da364e1da7a124bcb293f085bf2860c32c6f6", size = 1142112 }, +] + [[package]] name = "hypothesis" version = "6.119.3" @@ -484,6 +537,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ec/3d/c32a51d848401bd94cabb8767a39621496491ee7cd5199856b77da9b18ad/pillow-11.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:224aaa38177597bb179f3ec87eeefcce8e4f85e608025e9cfac60de237ba6316", size = 2567508 }, ] +[[package]] +name = "platformdirs" +version = "4.3.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439 }, +] + [[package]] name = "pyparsing" version = "3.2.0" @@ -651,6 +713,51 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/32/46/9cb0e58b2deb7f82b84065f37f3bffeb12413f947f9388e4cac22c4621ce/sortedcontainers-2.4.0-py2.py3-none-any.whl", hash = "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0", size = 29575 }, ] +[[package]] +name = "sqlalchemy" +version = "2.0.36" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "greenlet", marker = "(python_full_version < '3.13' and platform_machine == 'AMD64') or (python_full_version < '3.13' and platform_machine == 'WIN32') or (python_full_version < '3.13' and platform_machine == 'aarch64') or (python_full_version < '3.13' and platform_machine == 'amd64') or (python_full_version < '3.13' and platform_machine == 'ppc64le') or (python_full_version < '3.13' and platform_machine == 'win32') or (python_full_version < '3.13' and platform_machine == 'x86_64')" }, + { name = "typing-extensions" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/50/65/9cbc9c4c3287bed2499e05033e207473504dc4df999ce49385fb1f8b058a/sqlalchemy-2.0.36.tar.gz", hash = "sha256:7f2767680b6d2398aea7082e45a774b2b0767b5c8d8ffb9c8b683088ea9b29c5", size = 9574485 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/db/72/14ab694b8b3f0e35ef5beb74a8fea2811aa791ba1611c44dc90cdf46af17/SQLAlchemy-2.0.36-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:59b8f3adb3971929a3e660337f5dacc5942c2cdb760afcabb2614ffbda9f9f72", size = 2092604 }, + { url = "https://files.pythonhosted.org/packages/1e/59/333fcbca58b79f5b8b61853d6137530198823392151fa8fd9425f367519e/SQLAlchemy-2.0.36-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37350015056a553e442ff672c2d20e6f4b6d0b2495691fa239d8aa18bb3bc908", size = 2083796 }, + { url = "https://files.pythonhosted.org/packages/6c/a0/ec3c188d2b0c1bc742262e76408d44104598d7247c23f5b06bb97ee21bfa/SQLAlchemy-2.0.36-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8318f4776c85abc3f40ab185e388bee7a6ea99e7fa3a30686580b209eaa35c08", size = 3066165 }, + { url = "https://files.pythonhosted.org/packages/07/15/68ef91de5b8b7f80fb2d2b3b31ed42180c6227fe0a701aed9d01d34f98ec/SQLAlchemy-2.0.36-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c245b1fbade9c35e5bd3b64270ab49ce990369018289ecfde3f9c318411aaa07", size = 3074428 }, + { url = "https://files.pythonhosted.org/packages/e2/4c/9dfea5e63b87325eef6d9cdaac913459aa6a157a05a05ea6ff20004aee8e/SQLAlchemy-2.0.36-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:69f93723edbca7342624d09f6704e7126b152eaed3cdbb634cb657a54332a3c5", size = 3030477 }, + { url = "https://files.pythonhosted.org/packages/16/a5/fcfde8e74ea5f683b24add22463bfc21e431d4a5531c8a5b55bc6fbea164/SQLAlchemy-2.0.36-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f9511d8dd4a6e9271d07d150fb2f81874a3c8c95e11ff9af3a2dfc35fe42ee44", size = 3055942 }, + { url = "https://files.pythonhosted.org/packages/3c/ee/c22c415a771d791ae99146d72ffdb20e43625acd24835ea7fc157436d59f/SQLAlchemy-2.0.36-cp310-cp310-win32.whl", hash = "sha256:c3f3631693003d8e585d4200730616b78fafd5a01ef8b698f6967da5c605b3fa", size = 2064960 }, + { url = "https://files.pythonhosted.org/packages/aa/af/ad9c25cadc79bd851bdb9d82b68af9bdb91ff05f56d0da2f8a654825974f/SQLAlchemy-2.0.36-cp310-cp310-win_amd64.whl", hash = "sha256:a86bfab2ef46d63300c0f06936bd6e6c0105faa11d509083ba8f2f9d237fb5b5", size = 2089078 }, + { url = "https://files.pythonhosted.org/packages/00/4e/5a67963fd7cbc1beb8bd2152e907419f4c940ef04600b10151a751fe9e06/SQLAlchemy-2.0.36-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fd3a55deef00f689ce931d4d1b23fa9f04c880a48ee97af488fd215cf24e2a6c", size = 2093782 }, + { url = "https://files.pythonhosted.org/packages/b3/24/30e33b6389ebb5a17df2a4243b091bc709fb3dfc9a48c8d72f8e037c943d/SQLAlchemy-2.0.36-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4f5e9cd989b45b73bd359f693b935364f7e1f79486e29015813c338450aa5a71", size = 2084180 }, + { url = "https://files.pythonhosted.org/packages/10/1e/70e9ed2143a27065246be40f78637ad5160ea0f5fd32f8cab819a31ff54d/SQLAlchemy-2.0.36-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ddd9db6e59c44875211bc4c7953a9f6638b937b0a88ae6d09eb46cced54eff", size = 3202469 }, + { url = "https://files.pythonhosted.org/packages/b4/5f/95e0ed74093ac3c0db6acfa944d4d8ac6284ef5e1136b878a327ea1f975a/SQLAlchemy-2.0.36-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2519f3a5d0517fc159afab1015e54bb81b4406c278749779be57a569d8d1bb0d", size = 3202464 }, + { url = "https://files.pythonhosted.org/packages/91/95/2cf9b85a6bc2ee660e40594dffe04e777e7b8617fd0c6d77a0f782ea96c9/SQLAlchemy-2.0.36-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:59b1ee96617135f6e1d6f275bbe988f419c5178016f3d41d3c0abb0c819f75bb", size = 3139508 }, + { url = "https://files.pythonhosted.org/packages/92/ea/f0c01bc646456e4345c0fb5a3ddef457326285c2dc60435b0eb96b61bf31/SQLAlchemy-2.0.36-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:39769a115f730d683b0eb7b694db9789267bcd027326cccc3125e862eb03bfd8", size = 3159837 }, + { url = "https://files.pythonhosted.org/packages/a6/93/c8edbf153ee38fe529773240877bf1332ed95328aceef6254288f446994e/SQLAlchemy-2.0.36-cp311-cp311-win32.whl", hash = "sha256:66bffbad8d6271bb1cc2f9a4ea4f86f80fe5e2e3e501a5ae2a3dc6a76e604e6f", size = 2064529 }, + { url = "https://files.pythonhosted.org/packages/b1/03/d12b7c1d36fd80150c1d52e121614cf9377dac99e5497af8d8f5b2a8db64/SQLAlchemy-2.0.36-cp311-cp311-win_amd64.whl", hash = "sha256:23623166bfefe1487d81b698c423f8678e80df8b54614c2bf4b4cfcd7c711959", size = 2089874 }, + { url = "https://files.pythonhosted.org/packages/b8/bf/005dc47f0e57556e14512d5542f3f183b94fde46e15ff1588ec58ca89555/SQLAlchemy-2.0.36-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f7b64e6ec3f02c35647be6b4851008b26cff592a95ecb13b6788a54ef80bbdd4", size = 2092378 }, + { url = "https://files.pythonhosted.org/packages/94/65/f109d5720779a08e6e324ec89a744f5f92c48bd8005edc814bf72fbb24e5/SQLAlchemy-2.0.36-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:46331b00096a6db1fdc052d55b101dbbfc99155a548e20a0e4a8e5e4d1362855", size = 2082778 }, + { url = "https://files.pythonhosted.org/packages/60/f6/d9aa8c49c44f9b8c9b9dada1f12fa78df3d4c42aa2de437164b83ee1123c/SQLAlchemy-2.0.36-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fdf3386a801ea5aba17c6410dd1dc8d39cf454ca2565541b5ac42a84e1e28f53", size = 3232191 }, + { url = "https://files.pythonhosted.org/packages/8a/ab/81d4514527c068670cb1d7ab62a81a185df53a7c379bd2a5636e83d09ede/SQLAlchemy-2.0.36-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ac9dfa18ff2a67b09b372d5db8743c27966abf0e5344c555d86cc7199f7ad83a", size = 3243044 }, + { url = "https://files.pythonhosted.org/packages/35/b4/f87c014ecf5167dc669199cafdb20a7358ff4b1d49ce3622cc48571f811c/SQLAlchemy-2.0.36-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:90812a8933df713fdf748b355527e3af257a11e415b613dd794512461eb8a686", size = 3178511 }, + { url = "https://files.pythonhosted.org/packages/ea/09/badfc9293bc3ccba6ede05e5f2b44a760aa47d84da1fc5a326e963e3d4d9/SQLAlchemy-2.0.36-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1bc330d9d29c7f06f003ab10e1eaced295e87940405afe1b110f2eb93a233588", size = 3205147 }, + { url = "https://files.pythonhosted.org/packages/c8/60/70e681de02a13c4b27979b7b78da3058c49bacc9858c89ba672e030f03f2/SQLAlchemy-2.0.36-cp312-cp312-win32.whl", hash = "sha256:79d2e78abc26d871875b419e1fd3c0bca31a1cb0043277d0d850014599626c2e", size = 2062709 }, + { url = "https://files.pythonhosted.org/packages/b7/ed/f6cd9395e41bfe47dd253d74d2dfc3cab34980d4e20c8878cb1117306085/SQLAlchemy-2.0.36-cp312-cp312-win_amd64.whl", hash = "sha256:b544ad1935a8541d177cb402948b94e871067656b3a0b9e91dbec136b06a2ff5", size = 2088433 }, + { url = "https://files.pythonhosted.org/packages/78/5c/236398ae3678b3237726819b484f15f5c038a9549da01703a771f05a00d6/SQLAlchemy-2.0.36-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b5cc79df7f4bc3d11e4b542596c03826063092611e481fcf1c9dfee3c94355ef", size = 2087651 }, + { url = "https://files.pythonhosted.org/packages/a8/14/55c47420c0d23fb67a35af8be4719199b81c59f3084c28d131a7767b0b0b/SQLAlchemy-2.0.36-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:3c01117dd36800f2ecaa238c65365b7b16497adc1522bf84906e5710ee9ba0e8", size = 2078132 }, + { url = "https://files.pythonhosted.org/packages/3d/97/1e843b36abff8c4a7aa2e37f9bea364f90d021754c2de94d792c2d91405b/SQLAlchemy-2.0.36-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9bc633f4ee4b4c46e7adcb3a9b5ec083bf1d9a97c1d3854b92749d935de40b9b", size = 3164559 }, + { url = "https://files.pythonhosted.org/packages/7b/c5/07f18a897b997f6d6b234fab2bf31dccf66d5d16a79fe329aefc95cd7461/SQLAlchemy-2.0.36-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9e46ed38affdfc95d2c958de328d037d87801cfcbea6d421000859e9789e61c2", size = 3177897 }, + { url = "https://files.pythonhosted.org/packages/b3/cd/e16f3cbefd82b5c40b33732da634ec67a5f33b587744c7ab41699789d492/SQLAlchemy-2.0.36-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b2985c0b06e989c043f1dc09d4fe89e1616aadd35392aea2844f0458a989eacf", size = 3111289 }, + { url = "https://files.pythonhosted.org/packages/15/85/5b8a3b0bc29c9928aa62b5c91fcc8335f57c1de0a6343873b5f372e3672b/SQLAlchemy-2.0.36-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4a121d62ebe7d26fec9155f83f8be5189ef1405f5973ea4874a26fab9f1e262c", size = 3139491 }, + { url = "https://files.pythonhosted.org/packages/a1/95/81babb6089938680dfe2cd3f88cd3fd39cccd1543b7cb603b21ad881bff1/SQLAlchemy-2.0.36-cp313-cp313-win32.whl", hash = "sha256:0572f4bd6f94752167adfd7c1bed84f4b240ee6203a95e05d1e208d488d0d436", size = 2060439 }, + { url = "https://files.pythonhosted.org/packages/c1/ce/5f7428df55660d6879d0522adc73a3364970b5ef33ec17fa125c5dbcac1d/SQLAlchemy-2.0.36-cp313-cp313-win_amd64.whl", hash = "sha256:8c78ac40bde930c60e0f78b3cd184c580f89456dd87fc08f9e3ee3ce8765ce88", size = 2084574 }, + { url = "https://files.pythonhosted.org/packages/b8/49/21633706dd6feb14cd3f7935fc00b60870ea057686035e1a99ae6d9d9d53/SQLAlchemy-2.0.36-py3-none-any.whl", hash = "sha256:fddbe92b4760c6f5d48162aef14824add991aeda8ddadb3c31d56eb15ca69f8e", size = 1883787 }, +] + [[package]] name = "thd-json" version = "0.1.0" @@ -661,3 +768,28 @@ dependencies = [ { name = "json-schema" }, { name = "jsonschema" }, ] + +[[package]] +name = "typing-extensions" +version = "4.12.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/df/db/f35a00659bc03fec321ba8bce9420de607a1d37f8342eee1863174c69557/typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8", size = 85321 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/26/9f/ad63fc0248c5379346306f8668cda6e2e2e9c95e01216d2b8ffd9ff037d0/typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d", size = 37438 }, +] + +[[package]] +name = "xraydb" +version = "4.5.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "numpy" }, + { name = "packaging" }, + { name = "platformdirs" }, + { name = "scipy" }, + { name = "sqlalchemy" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a5/a7/ae5ca3409a9f3cabfa3e83b55d050dd94e19a66c75ff4051d20e56000ea6/xraydb-4.5.4.tar.gz", hash = "sha256:05d646fe232c6772ace6ded330064b6cfbfedb041eede05a4e760c8a05fd5b60", size = 3846500 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/0d/9a2cca8917880dd8fc78dd42629e9c7299f91501e7c027149475ede0fc36/xraydb-4.5.4-py3-none-any.whl", hash = "sha256:cf46f57738d545e94be2394da65341a6ef4742ea3b168fffce2e9b5f56c35508", size = 3856329 }, +]