diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b8cd5060..d24d503be 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,8 +1,5 @@ -cmake_minimum_required(VERSION 2.8 FATAL_ERROR) +cmake_minimum_required(VERSION 3.21 FATAL_ERROR) -#if(POLICY CMP0048) -# cmake_policy(SET CMP0048 NEW) -#endif() project(Relion) # Use new policy for OS X @rpath @@ -72,13 +69,12 @@ endif() # ----------------------------------------------------------------SET CXX STANDARD-- set(CXX_STANDARD_REQUIRED ON) -if(SYCL) - set(CMAKE_CXX_STANDARD 17) -else() - set(CMAKE_CXX_STANDARD 14) -endif() +set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_EXTENSIONS OFF) +set(C_STANDARD_REQUIRED ON) +set(CMAKE_C_STANDARD 99) + # ------------------OPTIONS WHICH ARE NEEDED TO SET BUILD-TYPES (COMPILATION FLAGS)-- # -------------------------------------------------------------------FURTHER OPTIONS-- @@ -170,48 +166,47 @@ else(DoublePrec_ACC) endif(DoublePrec_ACC) if(MDT_TYPE_CHECK) - message("-- MetaDataTable type check is enabled.") + message(STATUS "MetaDataTable type check is enabled.") add_definitions(-DMETADATA_TABLE_TYPE_CHECK) endif() if(CUDA) # -----------------------------------------------------------------------------CUDA-- - # DOC: http://www.cmake.org/cmake/help/v3.0/module/FindCUDA.html - FIND_PACKAGE(CUDA) - - # "-arch=sm_XX" alone is equal to "-arch=compute_XX -code=compute_XX,sm_XX" - # compute_XX generates PTX; thus GPUs newer than XX can also use the binary. - # See https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/#gpu-architecture-arch. - set(CUDA_ARCH "" CACHE STRING "CUDA architecture to use") - if (CUDA_ARCH STREQUAL "") - if (${CUDA_VERSION} VERSION_LESS "13.0") # Pascal (e.g. 1080) - message(STATUS "Setting fallback CUDA_ARCH=50 (Pascal)") - set(CUDARCH "-arch=sm_50") - else() # CUDA >= 13.0 no longer supports Pascal. 75 = Turing (e.g. 2080) - message(STATUS "Setting fallback CUDA_ARCH=75 (Turing)") - set(CUDARCH "-arch=sm_75") - endif() - else () - message(STATUS "Using provided CUDA_ARCH=${CUDA_ARCH}") - set(CUDARCH "-arch=sm_${CUDA_ARCH}") - endif () - - if(CUDA_FOUND) - message(STATUS "Using cuda wrapper to compile....") - if( (NOT ${CUDA_VERSION} VERSION_LESS "7.5") AND (NOT DoublePrec_ACC) ) - message(STATUS "Cuda version is >= 7.5 and single-precision build, enable double usage warning.") - set(WARN_DBL "--ptxas-options=-warn-double-usage") # cuda>=7.5 - elseif( ${CUDA_VERSION} VERSION_LESS "7.0") - message(WARNING "Cuda version is less than 7.0, so relion will be compiled without GPU support.") - message(STATUS "Using non-cuda compilation....") - set(CUDA OFF) - endif() - if(CUDA) - add_definitions(-D_CUDA_ENABLED) - endif() - else(CUDA_FOUND) - message(FATAL_ERROR "CUDA enabled but unlable to locate packages...") - endif(CUDA_FOUND) + FIND_PACKAGE(CUDAToolkit) + + if((CUDAToolkit_FOUND) AND ("${CUDAToolkit_VERSION}" VERSION_GREATER_EQUAL "10.0")) + message(STATUS "CUDAToolkit discovered CUDA " ${CUDAToolkit_VERSION} " at " ${CUDAToolkit_BIN_DIR}) + set(CMAKE_CUDA_STANDARD 17) + + # Very puzzling but `CUDAToolkit` package and `enable_language(CUDA)` use + # different methods to find `nvcc`. The latter does NOT respect `PATH` (`which nvcc`) and + # can pick up /usr/bin/nvcc. We can override this by setting `CMAKE_CUDA_COMPILER`. + # Another useful variable is `CMAKE_CUDA_HOST_COMPILER`. + set(CMAKE_CUDA_COMPILER "${CUDAToolkit_BIN_DIR}/nvcc" CACHE FILEPATH "Path to the CUDA compiler (nvcc)") + enable_language(CUDA) + + # "-arch=sm_XX" alone is equal to "-arch=compute_XX -code=compute_XX,sm_XX" + # compute_XX generates PTX; thus GPUs newer than XX can also use the binary. + # See https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/#gpu-architecture-arch. + set(CUDA_ARCH "" CACHE STRING "CUDA architecture to use") + if (CUDA_ARCH STREQUAL "") + if (${CUDAToolkit_VERSION} VERSION_LESS "13.0") # Pascal (e.g. 1080) + message(STATUS "Setting fallback CUDA_ARCH=50 (Pascal)") + set(CMAKE_CUDA_ARCHITECTURES 50) + else() # CUDA >= 13.0 no longer supports Pascal. 75 = Turing (e.g. 2080) + message(STATUS "Setting fallback CUDA_ARCH=75 (Turing)") + set(CMAKE_CUDA_ARCHITECTURES 75) + endif() + else () + message(STATUS "Using provided CUDA_ARCH=${CUDA_ARCH}") + set(CMAKE_CUDA_ARCHITECTURES ${CUDA_ARCH}) + endif () + + add_definitions(-D_CUDA_ENABLED) + else() + message("!! CUDA was enabled but CUDA >= 10.0 cannot be located. CUDA is set to OFF.") + set(CUDA OFF) + endif() elseif(HIP) # ------------------------------------------------------------------------------HIP-- if (DEFINED ENV{ROCM_PATH}) @@ -257,6 +252,24 @@ elseif(ALTCPU) endif() endif() +# ----------------------------------------------------------------- OpenMP ---------- +# This must come before including BuildTypes.cmake to properly set OpenMP flags to NVCC. +# CUDA support by the OpenMP package came at CMake 3.31 (too new). + +if(SYCL) # Intel DPC++ specific; I don't know when the OpenMP package supports SYCL + set(OpenMP_C_FLAGS "-fiopenmp") + set(OpenMP_CXX_FLAGS "-fiopenmp") + set(OpenMP_EXE_LINKER_FLAGS "-fiopenmp") +else() + FIND_PACKAGE(OpenMP REQUIRED) +endif() + +set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") +set(CMAKE_CXX_FLAGS "-fPIC ${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") + +#message(STATUS "OpenMP_CXX_FLAGS: ${OpenMP_CXX_FLAGS}") + # ----------------------------------------------------------INCLUDE ALL BUILD TYPES--- # This has to be AFTER project() and find_package(HIP). # Up to RELION 5.0.0, this must come BEFORE find_package(CUDA) as discussed in issue #1032. @@ -372,29 +385,6 @@ set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) -# ----------------------------------------------------------------- OpenMP ---------- -# This MUST be set before all cuda_add_executable/library calls. -# Otherwise the -Xcompiler argument to NVCC does not contain -fopenmp -# and #pragma omp critical is SILENTLY ignored, giving a wrong binary!!! -# https://github.com/3dem/relion/issues/1016 - -if(SYCL) # Intel DPC++ specific - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fiopenmp") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fiopenmp") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fiopenmp") - - set(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}") - set(CMAKE_CXX_FLAGS "-fPIC -std=c++17 ${CMAKE_CXX_FLAGS}") -else() - FIND_PACKAGE(OpenMP REQUIRED) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${OpenMP_C_FLAGS}") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}") - set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_EXE_LINKER_FLAGS}") - - set(CMAKE_C_FLAGS "-std=c99 ${CMAKE_C_FLAGS}") - set(CMAKE_CXX_FLAGS "-fPIC -std=c++17 ${CMAKE_CXX_FLAGS}") -endif() - # ----------------------------------------------------------Intel Compiler support -- # ---------------------------------- and build flags including MKL and IPP --------- @@ -486,9 +476,9 @@ if(GUI) endif(NOT FLTK_FOUND) else(X11_FOUND) - message( STATUS "\n-- ------------------ YOU HAVE NO X11-LIBS ------------------") - message( STATUS "CCmake found no X11-libs on your system, which are required for the GUI.") - message( STATUS " You CAN add the flag -DGUI=OFF to avoid using X11" ) + message(STATUS "\n-- ------------------ YOU HAVE NO X11-LIBS ------------------") + message(STATUS "CCmake found no X11-libs on your system, which are required for the GUI.") + message(STATUS " You CAN add the flag -DGUI=OFF to avoid using X11" ) message(FATAL_ERROR "X11 is required for GUI.") endif(X11_FOUND) @@ -551,7 +541,7 @@ endif(JPEG_FOUND) # -----------------------------------------------------------------PYTHON DEPENDENCIES-- -set(CONDA_ENV_NAME "relion-5.0" CACHE STRING "The Conda environment name") +set(CONDA_ENV_NAME "relion-5.1" CACHE STRING "The Conda environment name") include(${CMAKE_SOURCE_DIR}/cmake/FindCondaPython.cmake) list(APPEND RELION_PYTHON_WRAPPERS @@ -569,6 +559,8 @@ list(APPEND RELION_PYTHON_WRAPPERS python_tomo_get_particle_poses python_tomo_denoise filament_selection + python_trace_amyloids + schemegui ) foreach (SCRIPT_FILE ${RELION_PYTHON_WRAPPERS}) @@ -587,6 +579,12 @@ if (FETCH_WEIGHTS) "NOTE: You can skip this step by setting -DFETCH_WEIGHTS=OFF" ) + # `relion_trace_amyloids.py` is necessary for weight download during `cmake`. + # The `copy_scripts` target below is executed only during `make`. + configure_file("${CMAKE_SOURCE_DIR}/scripts/trace_amyloids.py" + "${CMAKE_BINARY_DIR}/bin/relion_trace_amyloids.py" + COPYONLY) + execute_process( COMMAND bash ${CMAKE_BINARY_DIR}/bin/relion_python_fetch_weights WORKING_DIRECTORY ${CMAKE_BINARY_DIR} @@ -623,7 +621,7 @@ list(APPEND RELION_SCRIPT_FILES star_datablock_ctfdat qsub.csh it.py - schemegui.py + trace_amyloids.py ) add_custom_target(copy_scripts ALL) @@ -675,6 +673,11 @@ message(STATUS "CMAKE_CXX_FLAGS : ${CMAKE_CXX_FLAGS}") #message(STATUS "MPI_C_COMPILER : ${MPI_C_COMPILER}") #message(STATUS "MPI_CXX_COMPILER : ${MPI_CXX_COMPILER}") #message(STATUS "CMAKE_EXE_LINKER_FLAGS : ${CMAKE_EXE_LINKER_FLAGS}") +#message(STATUS "CUDAToolkit_FOUND: ${CUDAToolkit_FOUND}") +#get_target_property(CUDART_LIB CUDA::cudart IMPORTED_LOCATION) +#message(STATUS "CUDA::cudart location: ${CUDART_LIB}") +#get_target_property(CUDART_INC CUDA::cudart INTERFACE_INCLUDE_DIRECTORIES) +#message(STATUS "CUDA::cudart includes: ${CUDART_INC}") # -----------------------------------------------------------------------------TESTS-- # Include testing flag(s) as precomiler diff --git a/cmake/BuildTypes.cmake b/cmake/BuildTypes.cmake index c0f671b96..5e2f7a835 100644 --- a/cmake/BuildTypes.cmake +++ b/cmake/BuildTypes.cmake @@ -3,8 +3,7 @@ # Add -G to allow cuda-gdb to break inside kernels. if(CUDA) - set(EXTRA_NVCC_FLAGS " --default-stream per-thread --std=c++17") - set(RELION_NVCC_FLAGS "${CUDARCH} ${WARN_DBL} ${EXTRA_NVCC_FLAGS}" CACHE STRING "" FORCE) + set(RELION_NVCC_FLAGS "--default-stream per-thread -Xcompiler ${OpenMP_CXX_FLAGS} " CACHE STRING "" FORCE) elseif (HIP) if (${HIP_VERSION} VERSION_LESS "5.3" ) set(EXTRA_HIPCC_FLAGS "-fgpu-default-stream=legacy -fno-gpu-rdc -munsafe-fp-atomics") @@ -43,7 +42,7 @@ set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} ${RELION_FLAGS_DEBUG}") set(CMAKE_EXE_LINKER_FLAGS_DEBUG "${CMAKE_EXE_LINKER_FLAGS_DEBUG} ${RELION_LINKER_FLAGS_DEBUG}") if(CUDA) - set(CUDA_NVCC_FLAGS_DEBUG "${RELION_NVCC_FLAGS_DEBUG}" CACHE STRING "" FORCE) + set(CMAKE_CUDA_FLAGS_DEBUG "${RELION_NVCC_FLAGS_DEBUG}" CACHE STRING "" FORCE) elseif(HIP) set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${RELION_HIPCC_FLAGS_DEBUG}") endif() @@ -59,7 +58,7 @@ endif() # message(STATUS "Set the extra flags for Debug build type") # message(STATUS "RELION_NVCC_FLAGS_DEBUG : ${RELION_NVCC_FLAGS_DEBUG}") -# message(STATUS "CUDA_NVCC_FLAGS_DEBUG : ${CUDA_NVCC_FLAGS_DEBUG}") +# message(STATUS "CMAKE_CUDA_FLAGS_DEBUG : ${CMAKE_CUDA_FLAGS_DEBUG}") # message(STATUS "CMAKE_CXX_FLAGS_DEBUG : ${CMAKE_CXX_FLAGS_DEBUG}") #-------------------------------------------------------------------- @@ -82,7 +81,7 @@ set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${R set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS_RELWITHDEBINFO} ${RELION_FLAGS_RELWITHDEBINFO}") set(CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO "${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO} ${RELION_LINKER_FLAGS_RELWITHDEBINFO}") if(CUDA) - set(CUDA_NVCC_FLAGS_RELWITHDEBINFO "${RELION_NVCC_FLAGS_RELWITHDEBINFO}" CACHE STRING "" FORCE) + set(CMAKE_CUDA_FLAGS_RELWITHDEBINFO "${RELION_NVCC_FLAGS_RELWITHDEBINFO}" CACHE STRING "" FORCE) # -- Add preprocessor defintions ------------------------------------ set(RELION_DEFINITIONS_RELWITHDEBINFO "-DDEBUG_CUDA") set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO} ${RELION_DEFINITIONS_RELWITHDEBINFO}") @@ -95,7 +94,7 @@ endif() # message(STATUS "Set the extra flags for RELWITHDEBINFO build type") # message(STATUS "RELION_NVCC_FLAGS_RELWITHDEBINFO : ${RELION_NVCC_FLAGS_RELWITHDEBINFO}") -# message(STATUS "CUDA_NVCC_FLAGS_RELWITHDEBINFO : ${CUDA_NVCC_FLAGS_RELWITHDEBINFO}") +# message(STATUS "CMAKE_CUDA_FLAGS_RELWITHDEBINFO : ${CMAKE_CUDA_FLAGS_RELWITHDEBINFO}") # message(STATUS "CMAKE_CXX_FLAGS_RELWITHDEBINFO : ${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") #-------------------------------------------------------------------- @@ -130,7 +129,7 @@ set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${RELION_FLAGS_RE set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} ${RELION_FLAGS_RELEASE}") set(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${RELION_LINKER_FLAGS_RELEASE}") if(CUDA) - set(CUDA_NVCC_FLAGS_RELEASE "${RELION_NVCC_FLAGS_RELEASE}" CACHE STRING "" FORCE) + set(CMAKE_CUDA_FLAGS_RELEASE "${RELION_NVCC_FLAGS_RELEASE}" CACHE STRING "" FORCE) elseif(HIP) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${RELION_HIPCC_FLAGS_RELEASE}") endif() @@ -166,7 +165,7 @@ if(CUDA) set(CMAKE_CXX_FLAGS_PROFILING "${CMAKE_CXX_FLAGS_RELEASE} ${RELION_FLAGS_PROFILING}" CACHE STRING "") set(CMAKE_C_FLAGS_PROFILING "${CMAKE_C_FLAGS_RELEASE} ${RELION_FALAGS_PROFILING}" CACHE STRING "") set(CMAKE_EXE_LINKER_FLAGS_PROFILING "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${RELION_LINKER_FLAGS_PROFILING}" CACHE STRING "") - set(CUDA_NVCC_FLAGS_PROFILING "${RELION_NVCC_FLAGS_PROFILING}" CACHE STRING "" FORCE) + set(CMAKE_CUDA_FLAGS_PROFILING "${RELION_NVCC_FLAGS_PROFILING}" CACHE STRING "" FORCE) # -- Add preprocessor defintions ------------------------------------ set(RELION_DEFINITIONS_PROFILING "-DCUDA_PROFILING") @@ -223,7 +222,7 @@ set(CMAKE_CXX_FLAGS_BENCHMARKING "${CMAKE_CXX_FLAGS_RELEASE} ${RELION_FLA set(CMAKE_C_FLAGS_BENCHMARKING "${CMAKE_C_FLAGS_RELEASE} ${RELION_FLAGS_BENCHMARKING}" CACHE STRING "" FORCE) set(CMAKE_EXE_LINKER_FLAGS_BENCHMARKING "${CMAKE_EXE_LINKER_FLAGS_RELEASE} ${RELION_LINKER_FLAGS_BENCHMARKING}" CACHE STRING "" FORCE) if(CUDA) - set(CUDA_NVCC_FLAGS_BENCHMARKING "${RELION_NVCC_FLAGS_BENCHMARKING}" CACHE STRING "" FORCE) + set(CMAKE_CUDA_FLAGS_BENCHMARKING "${RELION_NVCC_FLAGS_BENCHMARKING}" CACHE STRING "" FORCE) elseif(HIP) set(CMAKE_CXX_FLAGS_BENCHMARKING "${CMAKE_CXX_FLAGS_RELEASE} ${RELION_HIPCC_FLAGS_BENCHMARKING}") endif() diff --git a/environment.yml b/environment.yml index bd58b151f..9fbbc3c52 100644 --- a/environment.yml +++ b/environment.yml @@ -1,4 +1,4 @@ -name: relion-5.0 +name: relion-5.1 channels: - conda-forge dependencies: @@ -6,8 +6,8 @@ dependencies: - python=3.10 - setuptools=59.5.0 - pip: - - torch==2.0.1 - - torchvision==0.15.2 + - --extra-index-url https://download.pytorch.org/whl/cu128 + - torch==2.7.1+cu128 - tqdm==4.65.0 - mrcfile==1.4.3 - starfile>=0.5.6 @@ -18,6 +18,8 @@ dependencies: - morphosamplers==0.0.13 - pydantic==1.10.18 - napari[all]==0.4.18 + - napari-threedee==0.0.28 + - psygnal==0.11.1 - tsnecuda==3.0.1 - PyQt5==5.15.9 - typer==0.9.0 @@ -28,6 +30,8 @@ dependencies: - dill==0.3.7 - numpy==1.26.1 - scipy==1.11.2 + - skan==0.12.2 + - opencv-python==4.10.0.84 - git+https://github.com/3dem/relion-classranker - git+https://github.com/3dem/relion-blush - git+https://github.com/3dem/DynaMight diff --git a/environment_blackwell.yml b/environment_pascal.yml similarity index 85% rename from environment_blackwell.yml rename to environment_pascal.yml index 31bca9018..c61f03684 100644 --- a/environment_blackwell.yml +++ b/environment_pascal.yml @@ -1,4 +1,4 @@ -name: relion-5.0 +name: relion-5.1 channels: - conda-forge dependencies: @@ -6,9 +6,7 @@ dependencies: - python=3.10 - setuptools=59.5.0 - pip: - - --extra-index-url https://download.pytorch.org/whl/cu128 - - torch==2.7.1+cu128 - - torchvision==0.22.1+cu128 + - torch==2.0.1 - tqdm==4.65.0 - mrcfile==1.4.3 - starfile>=0.5.6 @@ -29,6 +27,8 @@ dependencies: - dill==0.3.7 - numpy==1.26.1 - scipy==1.11.2 + - skan==0.12.2 + - opencv-python==4.10.0.84 - git+https://github.com/3dem/relion-classranker - git+https://github.com/3dem/relion-blush - git+https://github.com/3dem/DynaMight diff --git a/scripts/Schemes/amyprep/autopick_fom/job.star b/scripts/Schemes/amyprep/autopick_fom/job.star new file mode 100644 index 000000000..6f2da1f3c --- /dev/null +++ b/scripts/Schemes/amyprep/autopick_fom/job.star @@ -0,0 +1,83 @@ + +# version 50001 + +data_job + +_rlnJobTypeLabel relion.autopick.amypick +_rlnJobIsContinue 1 +_rlnJobIsTomo 0 + + +# version 50001 + +data_joboptions_values + +loop_ +_rlnJobOptionVariable #1 +_rlnJobOptionValue #2 +amyloid_threshold .25 + angpix -1 +angpix_ref -1 +continue_manual No +do_amyloid Yes +do_amyloid_fom Yes +do_amyloid_plot No +do_amyloid_tracing No +do_ctf_autopick Yes +do_ignore_first_ctfpeak_autopick No +do_invert_refs Yes + do_log No +do_pick_helical_segments Yes + do_queue No +do_read_fom_maps No + do_ref3d No + do_refs No + do_topaz No +do_topaz_filaments No +do_topaz_pick No +do_topaz_train No +do_topaz_train_parts No +do_write_fom_maps No +fn_input_autopick Schemes/amyprep/ctffind/micrographs_ctf.star +fn_ref3d_autopick "" +fn_refs_autopick "" +fn_topaz_exe relion_python_topaz + gpu_ids "" +helical_nr_asu 3 +helical_rise 4.75 +helical_tube_kappa_max 0.07 +helical_tube_length_min 500 +helical_tube_outer_diameter 200 + highpass -1 +log_adjust_thr 0 +log_diam_max 250 +log_diam_min 200 +log_invert No +log_maxres 20 +log_upper_thr 999 + lowpass 20 +maxstddevnoise_autopick 1.1 +min_dedicated 112 +minavgnoise_autopick -999 +mindist_autopick 100 + nr_mpi 6 +nr_threads 18 +other_args "" +psi_sampling_autopick 5 + qsub sbatch +qsubscript /public/EM/RELION/relion-slurm-cpu-devel.sh + queuename openmpi +ref3d_sampling "30 degrees" +ref3d_symmetry C1 + shrink 0 +threshold_autopick 0.05 +topaz_filament_threshold -5 +topaz_hough_length -1 +topaz_model "" +topaz_nr_particles -1 +topaz_other_args "" +topaz_particle_diameter -1 +topaz_train_parts "" +topaz_train_picks "" + use_gpu No + diff --git a/scripts/Schemes/amyprep/ctffind/job.star b/scripts/Schemes/amyprep/ctffind/job.star new file mode 100644 index 000000000..e8da13310 --- /dev/null +++ b/scripts/Schemes/amyprep/ctffind/job.star @@ -0,0 +1,41 @@ + +# version 50001 + +data_job + +_rlnJobTypeLabel relion.ctffind.ctffind4 +_rlnJobIsContinue 0 +_rlnJobIsTomo 0 + + +# version 50001 + +data_joboptions_values + +loop_ +_rlnJobOptionVariable #1 +_rlnJobOptionValue #2 + box 512 + ctf_win -1 + dast 100 + dfmax 50000 + dfmin 5000 + dfstep 500 +do_phaseshift No + do_queue No +fn_ctffind_exe /public/EM/ctffind/ctffind.exe +input_star_mics Schemes/amyprep/motioncorr/corrected_micrographs.star +min_dedicated 112 + nr_mpi 24 +other_args "" + phase_max 180 + phase_min 0 +phase_step 10 + qsub sbatch +qsubscript /public/EM/RELION/relion-slurm-cpu-devel.sh + queuename openmpi + resmax 5 + resmin 30 +slow_search No +use_given_ps Yes + use_noDW No diff --git a/scripts/Schemes/amyprep/import/job.star b/scripts/Schemes/amyprep/import/job.star new file mode 100644 index 000000000..afd6beba9 --- /dev/null +++ b/scripts/Schemes/amyprep/import/job.star @@ -0,0 +1,39 @@ + +# version 50001 + +data_job + +_rlnJobTypeLabel relion.import.movies +_rlnJobIsContinue 0 +_rlnJobIsTomo 0 + + +# version 50001 + +data_joboptions_values + +loop_ +_rlnJobOptionVariable #1 +_rlnJobOptionValue #2 + Cs 2.7 + Q0 0.1 + angpix 0.824 +beamtilt_x 0 +beamtilt_y 0 + do_other No + do_queue No + do_raw Yes +fn_in_other ref.mrc + fn_in_raw Tiff/*/*/*.tiff + fn_mtf "" +is_multiframe Yes + kV 300.0 +min_dedicated 24 + node_type "Particle coordinates (*.box, *_pick.star)" +optics_group_name opticsGroup1 +optics_group_particles "" +other_args " --do_at_most $$do_at_most" + qsub sbatch +qsubscript /public/EM/RELION/relion-slurm-cpu-devel.sh + queuename openmpi + diff --git a/scripts/Schemes/amyprep/motioncorr/job.star b/scripts/Schemes/amyprep/motioncorr/job.star new file mode 100644 index 000000000..3bf9b9743 --- /dev/null +++ b/scripts/Schemes/amyprep/motioncorr/job.star @@ -0,0 +1,50 @@ + +# version 50001 + +data_job + +_rlnJobTypeLabel relion.motioncorr +_rlnJobIsContinue 0 +_rlnJobIsTomo 0 + + +# version 50001 + +data_joboptions_values + +loop_ +_rlnJobOptionVariable #1 +_rlnJobOptionValue #2 + bfactor 150 +bin_factor 1 +do_dose_weighting Yes +do_float16 Yes +do_own_motioncor Yes + do_queue No +do_save_noDW No +do_save_ps Yes +dose_per_frame 1.0 +eer_grouping -1 +first_frame_sum 1 + fn_defect "" +fn_gain_ref gain.mrc +fn_motioncor2_exe /public/EM/MOTIONCOR2/MotionCor2 + gain_flip "No flipping (0)" + gain_rot "No rotation (0)" + gpu_ids 0 +group_for_ps 4 +group_frames 1 +input_star_mics Schemes/amyprep/import/movies.star +last_frame_sum -1 +min_dedicated 24 + nr_mpi 9 +nr_threads 12 +other_args "--do_at_most $$do_at_most" +other_motioncor2_args "" + patch_x 4 + patch_y 4 +pre_exposure 0 + qsub sbatch +qsubscript /public/EM/RELION/relion-slurm-cpu-devel.sh + queuename openmpi + diff --git a/scripts/Schemes/amyprep/scheme.star b/scripts/Schemes/amyprep/scheme.star new file mode 100644 index 000000000..aed8d12e4 --- /dev/null +++ b/scripts/Schemes/amyprep/scheme.star @@ -0,0 +1,106 @@ + +# version 50001 + +data_scheme_general + +_rlnSchemeName Schemes/amyprep/ +_rlnSchemeCurrentNodeName WAIT + + +# version 50001 + +data_scheme_floats + +loop_ +_rlnSchemeFloatVariableName #1 +_rlnSchemeFloatVariableValue #2 +_rlnSchemeFloatVariableResetValue #3 +current_nr_movies 0.000000 0.000000 +do_at_most 25000.000000 25000.000000 +maxtime_hr 48.000000 48.000000 +min_fom_skew 1.000000 1.000000 +prev_nr_movies 0.000000 0.000000 + wait_sec 300.000000 300.000000 + + +# version 50001 + +data_scheme_bools + +loop_ +_rlnSchemeBooleanVariableName #1 +_rlnSchemeBooleanVariableValue #2 +_rlnSchemeBooleanVariableResetValue #3 +has_increased 0 0 +has_larger_nr_mics 1 1 + has_mics 1 1 +has_movies 0 0 + + +# version 50001 + +data_scheme_strings + +loop_ +_rlnSchemeStringVariableName #1 +_rlnSchemeStringVariableValue #2 +_rlnSchemeStringVariableResetValue #3 +input_movies Schemes/amyprep/import/movies.star Schemes/amyprep/import/movies.star + movies movies movies + + +# version 50001 + +data_scheme_operators + +loop_ +_rlnSchemeOperatorName #1 +_rlnSchemeOperatorType #2 +_rlnSchemeOperatorOutput #3 +_rlnSchemeOperatorInput1 #4 +_rlnSchemeOperatorInput2 #5 +COUNT_movies float=count_images current_nr_movies input_movies movies +EXIT_maxtime exit_maxtime undefined maxtime_hr undefined +HAS_increased bool=gt has_increased current_nr_movies prev_nr_movies +SET_prev_nr_movies float=set prev_nr_movies current_nr_movies undefined + WAIT wait undefined wait_sec undefined + + +# version 50001 + +data_scheme_jobs + +loop_ +_rlnSchemeJobNameOriginal #1 +_rlnSchemeJobName #2 +_rlnSchemeJobMode #3 +_rlnSchemeJobHasStarted #4 +autopick_fom autopick_fom continue 0 + ctffind ctffind continue 0 + import import continue 0 +importmovies importmovies "" 0 +motioncorr motioncorr continue 0 +select_mics select_mics continue 0 + + +# version 50001 + +data_scheme_edges + +loop_ +_rlnSchemeEdgeInputNodeName #1 +_rlnSchemeEdgeOutputNodeName #2 +_rlnSchemeEdgeIsFork #3 +_rlnSchemeEdgeOutputNodeNameIfTrue #4 +_rlnSchemeEdgeBooleanVariable #5 + WAIT EXIT_maxtime 0 undefined undefined +EXIT_maxtime import 0 undefined undefined + import COUNT_movies 0 undefined undefined +COUNT_movies HAS_increased 0 undefined undefined +HAS_increased WAIT 1 SET_prev_nr_movies has_larger_nr_mics +SET_prev_nr_movies motioncorr 0 undefined undefined +motioncorr ctffind 0 undefined undefined + ctffind autopick_fom 0 undefined undefined +autopick_fom select_mics 0 undefined undefined +select_mics WAIT 0 undefined undefined + diff --git a/scripts/Schemes/amyprep/select_mics/job.star b/scripts/Schemes/amyprep/select_mics/job.star new file mode 100644 index 000000000..38ceddbfd --- /dev/null +++ b/scripts/Schemes/amyprep/select_mics/job.star @@ -0,0 +1,45 @@ + +# version 30001 + +data_job + +_rlnJobTypeLabel relion.select +_rlnJobIsContinue 0 + + +# version 30001 + +data_joboptions_values + +loop_ +_rlnJobOptionVariable #1 +_rlnJobOptionValue #2 +discard_label rlnImageName +discard_sigma 4 +do_class_ranker No +do_discard No + do_queue No + do_random No +do_recenter No +do_regroup No +do_remove_duplicates No +do_select_values Yes + do_split No +duplicate_threshold 30 + fn_data "" + fn_mic Schemes/amyprep/autopick_fom/micrographs_autopick.star + fn_model "" +image_angpix -1 +min_dedicated 24 + nr_groups 1 + nr_split -1 +other_args "" + qsub qsub +qsubscript /public/EM/RELION/relion/bin/relion_qsub.csh + queuename openmpi +rank_threshold 0.35 +select_label rlnMicrographScoreSkewness +select_maxval 9999. +select_minval 1. +split_size 100 + diff --git a/scripts/Schemes/amyproc/autopick_trace/job.star b/scripts/Schemes/amyproc/autopick_trace/job.star new file mode 100644 index 000000000..9be89c059 --- /dev/null +++ b/scripts/Schemes/amyproc/autopick_trace/job.star @@ -0,0 +1,88 @@ + +# version 50001 + +data_job + +_rlnJobTypeLabel relion.autopick.amypick +_rlnJobIsContinue 0 +_rlnJobIsTomo 0 + + +# version 50001 + +data_joboptions_values + +loop_ +_rlnJobOptionVariable #1 +_rlnJobOptionValue #2 +amyloid_carbon_threshold 0.9 +amyloid_gpu_ids 0:1:2:3 +amyloid_length 500 +amyloid_threshold 0.5 +amyloid_width 200 + angpix -1 +angpix_ref -1 +continue_manual No +do_amyloid Yes +do_amyloid_carbon Yes +do_amyloid_fom No +do_amyloid_plot No +do_amyloid_tracing Yes +do_ctf_autopick Yes +do_ignore_first_ctfpeak_autopick No +do_invert_refs Yes + do_log No +do_pick_helical_segments No + do_queue No +do_read_fom_maps No + do_ref3d No + do_refs No + do_topaz No +do_topaz_filaments No +do_topaz_pick No +do_topaz_train No +do_topaz_train_parts No +do_write_fom_maps No +fn_input_autopick $$input_mics +fn_ref3d_autopick "" +fn_refs_autopick "" +fn_topaz_exe relion_python_topaz + gpu_ids 0:1:2:3 +helical_nr_asu 3 +helical_rise 4.75 +helical_tube_kappa_max 0.07 +helical_tube_length_min 500 +helical_tube_outer_diameter 200 + highpass -1 +log_adjust_thr 0 +log_diam_max 250 +log_diam_min 200 +log_invert No +log_maxres 20 +log_upper_thr 999 + lowpass 20 +maxstddevnoise_autopick 1.1 +min_dedicated 112 +minavgnoise_autopick -999 +mindist_autopick 100 + nr_mpi 4 +nr_threads 1 +other_args "" +psi_sampling_autopick 5 + qsub sbatch +qsubscript /public/EM/RELION/relion-slurm-gpu-devel.csh + queuename openmpi +ref3d_sampling "30 degrees" +ref3d_symmetry C1 + shrink 0 +threshold_autopick 0.05 +topaz_filament_threshold -5 +topaz_hough_length -1 +topaz_model "" +topaz_nr_particles -1 +topaz_other_args "" +topaz_particle_diameter -1 +topaz_train_parts "" +topaz_train_picks "" + use_gpu Yes + diff --git a/scripts/Schemes/amyproc/class2d/job.star b/scripts/Schemes/amyproc/class2d/job.star new file mode 100644 index 000000000..28a1c638e --- /dev/null +++ b/scripts/Schemes/amyproc/class2d/job.star @@ -0,0 +1,58 @@ + +# version 50001 + +data_job + +_rlnJobTypeLabel relion.class2d.helical +_rlnJobIsContinue 0 +_rlnJobIsTomo 0 + + +# version 50001 + +data_joboptions_values + +loop_ +_rlnJobOptionVariable #1 +_rlnJobOptionValue #2 +allow_coarser No +ctf_intact_first_peak Yes +do_bimodal_psi Yes + do_center No +do_combine_thru_disc No +do_ctf_correction Yes + do_em Yes + do_grad No + do_helix Yes +do_parallel_discio Yes +do_preread_images No + do_queue No +do_restrict_xoff Yes +do_zero_mask Yes +dont_skip_align Yes + fn_cont "" + fn_img $$mybatch + gpu_ids 0:1:2:3 +helical_rise 4.75 +helical_tube_outer_diameter 200 +highres_limit -1 +min_dedicated 24 +nr_classes 100 +nr_iter_em 25 +nr_iter_grad 200 + nr_mpi 5 + nr_pool 30 +nr_threads 6 +offset_range 6 +offset_step 1 +other_args "" +particle_diameter 600 +psi_sampling 2 + qsub sbatch +qsubscript /public/EM/RELION/relion-slurm-gpu-4.0.csh + queuename openmpi + range_psi 6 +scratch_dir /ssd + tau_fudge 2 + use_gpu Yes + diff --git a/scripts/Schemes/amyproc/extract/job.star b/scripts/Schemes/amyproc/extract/job.star new file mode 100644 index 000000000..0e289cda6 --- /dev/null +++ b/scripts/Schemes/amyproc/extract/job.star @@ -0,0 +1,50 @@ + +# version 50001 + +data_job + +_rlnJobTypeLabel relion.extract.helical +_rlnJobIsContinue 0 +_rlnJobIsTomo 0 + + +# version 50001 + +data_joboptions_values + +loop_ +_rlnJobOptionVariable #1 +_rlnJobOptionValue #2 +bg_diameter -1 +black_dust -1 +coords_suffix Schemes/amyproc/autopick_trace/autopick.star +do_extract_helix Yes +do_float16 Yes +do_fom_threshold No + do_invert Yes + do_norm Yes + do_queue No +do_recenter No +do_reextract No +do_rescale Yes +do_reset_offsets No +extract_size 768 +fndata_reextract "" +helical_bimodal_angular_priors Yes +helical_nr_asu 3 +helical_rise 4.75 +helical_tube_outer_diameter 200 +min_dedicated 24 +minimum_pick_fom 0 + nr_mpi 12 +other_args "" + qsub sbatch +qsubscript /public/EM/RELION/relion-slurm-cpu-devel.sh + queuename openmpi +recenter_x 0 +recenter_y 0 +recenter_z 0 + rescale 128 + star_mics $$input_mics +white_dust -1 + diff --git a/scripts/Schemes/amyproc/scheme.star b/scripts/Schemes/amyproc/scheme.star new file mode 100644 index 000000000..49f7c3619 --- /dev/null +++ b/scripts/Schemes/amyproc/scheme.star @@ -0,0 +1,123 @@ + +# version 50001 + +data_scheme_general + +_rlnSchemeName Schemes/amyproc/ +_rlnSchemeCurrentNodeName WAIT + + +# version 50001 + +data_scheme_floats + +loop_ +_rlnSchemeFloatVariableName #1 +_rlnSchemeFloatVariableValue #2 +_rlnSchemeFloatVariableResetValue #3 + batchsize 100000.00000 100000.00000 +current_batch 1.000000 1.000000 +current_nr_mics 0.000000 0.000000 +maxtime_hr 48.000000 48.000000 +mybatchsize 0.000000 0.000000 +nr_batches 0.000000 0.000000 + one 1.000000 1.000000 +prev_nr_mics 0.000000 0.000000 + wait_sec 300.000000 300.000000 + + +# version 50001 + +data_scheme_bools + +loop_ +_rlnSchemeBooleanVariableName #1 +_rlnSchemeBooleanVariableValue #2 +_rlnSchemeBooleanVariableResetValue #3 + has_mics 0 0 +has_mics_increased 0 0 +is_batch_full 1 1 +is_full_batch 0 0 + + +# version 50001 + +data_scheme_strings + +loop_ +_rlnSchemeStringVariableName #1 +_rlnSchemeStringVariableValue #2 +_rlnSchemeStringVariableResetValue #3 +batchnames Schemes/amyproc/split/particles_split*.star Schemes/amyproc/split/particles_split*.star +input_mics Schemes/amyprep/select_mics/micrographs.star Schemes/amyprep/select_mics/micrographs.star +micrographs micrographs micrographs + mybatch "" "" + mybatches "" "" + particles particles particles + + +# version 50001 + +data_scheme_operators + +loop_ +_rlnSchemeOperatorName #1 +_rlnSchemeOperatorType #2 +_rlnSchemeOperatorOutput #3 +_rlnSchemeOperatorInput1 #4 +_rlnSchemeOperatorInput2 #5 +COUNT_mics float=count_images current_nr_mics input_mics micrographs +COUNT_mybatchsize float=count_images mybatchsize mybatch particles +EXIT_maxtime exit_maxtime undefined maxtime_hr undefined +GLOB_batchnames string=glob mybatches batchnames undefined + HAS_mics bool=file_exists has_mics input_mics undefined +HAS_mics_increased bool=gt has_mics_increased current_nr_mics prev_nr_mics +INCR_batch float=plus current_batch current_batch one +IS_batchfull bool=eq is_full_batch mybatchsize batchsize +SET_mybatch string=nth_word mybatch mybatches current_batch +SET_prev_nr_mics float=set prev_nr_mics current_nr_mics undefined + WAIT wait undefined wait_sec undefined + + +# version 50001 + +data_scheme_jobs + +loop_ +_rlnSchemeJobNameOriginal #1 +_rlnSchemeJobName #2 +_rlnSchemeJobMode #3 +_rlnSchemeJobHasStarted #4 +autopick_trace autopick_trace continue 0 + class2d class2d new 0 + extract extract continue 0 + split split continue 0 + + +# version 50001 + +data_scheme_edges + +loop_ +_rlnSchemeEdgeInputNodeName #1 +_rlnSchemeEdgeOutputNodeName #2 +_rlnSchemeEdgeIsFork #3 +_rlnSchemeEdgeOutputNodeNameIfTrue #4 +_rlnSchemeEdgeBooleanVariable #5 + WAIT EXIT_maxtime 0 undefined undefined +EXIT_maxtime HAS_mics 0 undefined undefined + HAS_mics WAIT 1 COUNT_mics has_mics +COUNT_mics HAS_mics_increased 0 undefined undefined +HAS_mics_increased WAIT 1 SET_prev_nr_mics has_mics_increased + WAIT EXIT_maxtime 0 undefined undefined +SET_prev_nr_mics autopick_trace 0 undefined undefined +autopick_trace extract 0 undefined undefined + extract split 0 undefined undefined + split GLOB_batchnames 0 undefined undefined +GLOB_batchnames SET_mybatch 0 undefined undefined +SET_mybatch COUNT_mybatchsize 0 undefined undefined +COUNT_mybatchsize IS_batchfull 0 undefined undefined +IS_batchfull WAIT 1 class2d is_full_batch + class2d INCR_batch 0 undefined undefined +INCR_batch WAIT 0 undefined undefined + diff --git a/scripts/Schemes/amyproc/split/job.star b/scripts/Schemes/amyproc/split/job.star new file mode 100644 index 000000000..d7f6a8716 --- /dev/null +++ b/scripts/Schemes/amyproc/split/job.star @@ -0,0 +1,51 @@ + +# version 50001 + +data_job + +_rlnJobTypeLabel relion.select.split +_rlnJobIsContinue 0 +_rlnJobIsTomo 0 + + +# version 50001 + +data_joboptions_values + +loop_ +_rlnJobOptionVariable #1 +_rlnJobOptionValue #2 +dendrogram_minclass 1000 +dendrogram_threshold 0.8 +discard_label rlnImageName +discard_sigma 4 +do_class_ranker No +do_discard No +do_filaments No + do_queue No + do_random No +do_recenter No +do_regroup No +do_remove_duplicates No +do_select_values No + do_split Yes +duplicate_threshold 30 + fn_data Schemes/amyproc/extract/particles.star + fn_mic "" + fn_model "" +image_angpix -1 +min_dedicated 24 + nr_groups 1 + nr_split -1 +other_args "" + qsub sbatch +qsubscript /public/EM/RELION/relion-slurm-gpu-4.0.csh + queuename openmpi +rank_threshold 0.5 +select_label rlnMicrographScoreSkewness +select_maxval 9999. +select_minval 1 +select_nr_classes -1 +select_nr_parts -1 +split_size $$batchsize + diff --git a/scripts/Schemes/proc/extract/job.star b/scripts/Schemes/proc/extract/job.star index 9764c54e4..08c9717ac 100644 --- a/scripts/Schemes/proc/extract/job.star +++ b/scripts/Schemes/proc/extract/job.star @@ -18,7 +18,8 @@ bg_diameter -1 black_dust -1 coords_suffix Schemes/proc/autopick/autopick.star do_cut_into_segments Yes -do_extract_helical_tubes Yes +do_extract_helical_tubes Yes +do_lines No do_extract_helix No do_fom_threshold Yes do_invert Yes diff --git a/scripts/python_fetch_weights.in b/scripts/python_fetch_weights.in index b0de26dc3..2ab67ce4d 100755 --- a/scripts/python_fetch_weights.in +++ b/scripts/python_fetch_weights.in @@ -39,6 +39,27 @@ if [ -x "$target_path" ]; then # Unsuccessful, trap the EXIT signal to call the custom exit function trap 'exit_with_error' EXIT fi + # Execute the target binary for amy-v1.0 + "$target_path" -m amy-v1.0 +else + echo "Error: $target_binary not found or not executable in $script_dir." + exit 1 +fi + +# Call amypicker weight download ##################################################### +echo "Attempting to download weights for amyloid filament picker..." + +target_path="$script_dir/relion_python_trace_amyloids" + +if [ -x "$target_path" ]; then + # Execute the target binary + "$target_path" + if [ $? -ne 0 ]; then + # Unsuccessful, trap the EXIT signal to call the custom exit function + trap 'exit_with_error' EXIT + fi + # Uncomment in case one also wanted to download the older amytracer-v1.0 weights.... + #"$target_path" -m amytracer-v1.0 else echo "Error: $target_binary not found or not executable in $script_dir." exit 1 diff --git a/scripts/python_trace_amyloids.in b/scripts/python_trace_amyloids.in new file mode 100755 index 000000000..5c37e5edc --- /dev/null +++ b/scripts/python_trace_amyloids.in @@ -0,0 +1,47 @@ +#!/usr/bin/env bash + +print_error() { +echo " +---------------------------------- PYTHON ERROR --------------------------------- + Has RELION been provided a Python interpreter with the correct environment? + The interpreter can be passed to RELION either during Cmake configuration by + using the Cmake flag -DPYTHON_EXE_PATH=. + NOTE: For some modules TORCH_HOME needs to be set to find pretrained models +--------------------------------------------------------------------------------- + + Using python executable: $1 +" +} + +# Set the Python executable path +python_executable="@PYTHON_EXE_PATH@" +torch_home="@TORCH_HOME_PATH@" +relion_home="@Relion_BINARY_DIR@" + +# Check if the python executable exists +if [ ! -x "$python_executable" ]; then + # Check for default python executable + python_executable=$(command -v python) + + if [ -z "$python_executable" ]; then + print_error "$python_executable" + exit 1 + fi +fi + +# Run the Python script with forwarded arguments +if [ -n "$torch_home" ]; then + TORCH_HOME="$torch_home" "$python_executable" "$relion_home"/bin/relion_trace_amyloids.py "$@" +else + "$python_executable" "$relion_home"/bin/relion_trace_amyloids.py "$@" +fi + +# Check the return status of the python command +if [ $? -ne 0 ]; then + print_error "$python_executable" + exit 2 +fi + +# Exit +exit 0 + diff --git a/scripts/schemegui.py b/scripts/schemegui.in similarity index 94% rename from scripts/schemegui.py rename to scripts/schemegui.in index 8a7f0c9dd..06e204332 100755 --- a/scripts/schemegui.py +++ b/scripts/schemegui.in @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!@PYTHON_EXE_PATH@ """ relion_it.py @@ -28,16 +28,15 @@ #from Tkinter import scrolledtext from tkinter import messagebox -OPTIONS_FILE = 'relion_it_options.py' IS_RUNNING = False # Colour definitions # Yellowish background for entries entry_bg = '#ffffe6' -# reddish colour for Browse buttons -button_bg = '#c8506e' -# Darker red for run buttons -runbutton_bg = '#a01e3c' +# relion-5.1: tealish colour for Browse buttons +button_bg = '#66b2b2' +# Darker teal for run buttons +runbutton_bg = '#008080' def load_star(filename): from collections import OrderedDict @@ -92,6 +91,17 @@ def load_star(filename): return datasets +def copy_scheme(schemename): + + ## Only copy the Scheme directory structure from the RELION installation directory if it doesn't exist yet + if not os.path.isdir('Schemes/'+schemename): + try: + mydir = os.environ['RELION_SCRIPT_DIRECTORY'] + except KeyError: + raise KeyError("Environment variable $RELION_SCRIPT_DIRECTORY has not been set. This is required to copy RELION-distributed schemes from.") + print(' Copying Schemes/' + schemename + ' from: ' + mydir) + copytree(mydir+'/Schemes/'+schemename, 'Schemes/'+schemename) + class SchemeGui(object): def __init__(self, main_window, schemename): @@ -271,17 +281,6 @@ def change_schemevar(self, *args): pass self.schemevar_value_var.set(myval) - def update_relion_it_options(self, myoption): - with open(OPTIONS_FILE) as file: - user_opts = collections.OrderedDict(ast.literal_eval(file.read())) - user_opts.update(myoption) - with open(OPTIONS_FILE, 'w') as file: - file.write("{\n") - for k,v in user_opts.items(): - file.write("'%s' : '%s', \n" % (k, v)) - file.write("}\n") - print(' RELION_IT: updated ', OPTIONS_FILE) - def set_joboption(self, *args_ignored, **kwargs_ignored): jobstar = 'Schemes/' + self.schemename + '/' + self.jobname_var.get() + '/job.star' command = 'relion_pipeliner --editJob ' + jobstar + ' --editOption ' + self.joboption_var.get() + ' --editValue \"' + str(self.joboption_value_entry.get()) + '\"' @@ -291,17 +290,11 @@ def set_joboption(self, *args_ignored, **kwargs_ignored): command2 = 'relion_schemer --scheme ' + self.schemename + ' --set_has_started ' + self.jobname_var.get() + ' --value False' print(' RELION_IT: excuting: ', command2) os.system(command2) - myoption = self.schemename + '__' + self.jobname_var.get() + '__' + self.joboption_var.get() - mydic = {myoption : self.joboption_value_entry.get()} - self.update_relion_it_options(mydic) def set_schemevar(self, *args_ignored, **kwargs_ignored): command = 'relion_schemer --scheme ' + self.schemename + ' --set_var ' + self.schemevar_var.get() + ' --value \"' + self.schemevar_value_var.get() + '\"' + ' --original_value \"' + self.schemevar_value_var.get() + '\"' print(' RELION_IT: excuting: ', command) os.system(command) - myoption = self.schemename + '__' + self.schemevar_var.get() - mydic = {myoption : self.schemevar_value_var.get()} - self.update_relion_it_options(mydic) def abort_scheme(self, *args_ignored, **kwargs_ignored): command = 'relion_schemer --scheme ' + self.schemename + ' --abort' @@ -407,7 +400,11 @@ def main(): else: schemename = sys.argv[1] - print(' RELION_IT: launching GUI...') + schemestar = 'Schemes/' + schemename + '/scheme.star' + if not path.exists(schemestar): + print(' Scheme does not yet exist, try copying from RELION scripts directory... ') + copy_scheme(schemename) + print(' Launching GUI...') tk_root = tk.Tk() titlegui = "Scheme: " + schemename tk_root.title(titlegui) diff --git a/scripts/trace_amyloids.py b/scripts/trace_amyloids.py new file mode 100755 index 000000000..9c976e159 --- /dev/null +++ b/scripts/trace_amyloids.py @@ -0,0 +1,823 @@ +#!/public/EM/anaconda3/envs/relion-5.0/bin/python + +import argparse +import math +import sys, os +from pathlib import Path + +import numpy as np +import pandas as pd +import starfile +import torch +import torch.nn as nn +import torch.nn.functional as F + +import mrcfile +import matplotlib +matplotlib.use("Agg") # non-GUI backend, no Qt/X11 needed +import matplotlib.pyplot as plt + +from skimage.morphology import remove_small_objects, skeletonize +from skimage.measure import regionprops, label as label_connected_component +from skan import Skeleton, summarize +from scipy.spatial.distance import cdist +import cv2 + +from tqdm import tqdm +import time + +############################################################################### +# U-Net Model +############################################################################### +class DownCarbon(nn.Module): + """Downscaling with maxpool then double conv""" + + def __init__(self, in_channels, out_channels): + super().__init__() + self.maxpool_conv = nn.Sequential( + nn.MaxPool2d(2), + DoubleConv(in_channels, out_channels) + ) + + def forward(self, x): + return self.maxpool_conv(x) + + +class UpCarbon(nn.Module): + """Upscaling then double conv""" + + def __init__(self, in_channels, out_channels): + super().__init__() + + # 1) spatial upsample + # 2) reduce channels + self.up = nn.Sequential( + nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True), + nn.Conv2d(in_channels, in_channels // 2, kernel_size=1), + ) + # after cat: (in_channels//2 + in_channels//2) == in_channels + self.conv = DoubleConv(in_channels, out_channels) + + def forward(self, x1, x2): + x1 = self.up(x1) + # input is CHW + diffY = x2.size()[2] - x1.size()[2] + diffX = x2.size()[3] - x1.size()[3] + + x1 = F.pad(x1, [diffX // 2, diffX - diffX // 2, + diffY // 2, diffY - diffY // 2]) + # if you have padding issues, see + # https://github.com/HaiyongJiang/U-Net-Pytorch-Unstructured-Buggy/commit/0e854509c2cea854e247a9c615f175f76fbb2e3a + # https://github.com/xiaopeng-liao/Pytorch-UNet/commit/8ebac70e633bac59fc22bb5195e513d5832fb3bd + x = torch.cat([x2, x1], dim=1) + return self.conv(x) + + +class DoubleConv(nn.Module): + """(convolution => [InstanceNorm] => GELU) * 2""" + def __init__(self, in_channels, out_channels, mid_channels=None): + super().__init__() + if not mid_channels: + mid_channels = out_channels + self.double_conv = nn.Sequential( + nn.Conv2d(in_channels, mid_channels, kernel_size=3, padding=1, bias=False), + nn.InstanceNorm2d(mid_channels), + nn.GELU(), + nn.Conv2d(mid_channels, out_channels, kernel_size=3, padding=1, bias=False), + nn.InstanceNorm2d(out_channels), + nn.GELU() + ) + + def forward(self, x): + return self.double_conv(x) + + +class Down(nn.Module): + def __init__(self, in_channels, out_channels): + super().__init__() + self.maxpool_conv = nn.Sequential( + nn.MaxPool2d(2), + DoubleConv(in_channels, out_channels) + ) + + def forward(self, x): + return self.maxpool_conv(x) + + +class Up(nn.Module): + def __init__(self, in_channels, out_channels, bilinear=True): + super().__init__() + if bilinear: + self.up = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) + self.conv = DoubleConv(in_channels, out_channels, in_channels // 2) + else: + self.up = nn.ConvTranspose2d(in_channels, in_channels // 2, kernel_size=2, stride=2) + self.conv = DoubleConv(in_channels, out_channels) + + def forward(self, x1, x2): + x1 = self.up(x1) + diffY = x2.size()[2] - x1.size()[2] + diffX = x2.size()[3] - x1.size()[3] + + x1 = F.pad( + x1, + [diffX // 2, diffX - diffX // 2, diffY // 2, diffY - diffY // 2] + ) + x = torch.cat([x2, x1], dim=1) + return self.conv(x) + + +class OutConv(nn.Module): + def __init__(self, in_channels, out_channels): + super().__init__() + self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1) + + def forward(self, x): + return self.conv(x) + + +class UNet(nn.Module): + def __init__(self, n_channels, n_classes, embedding_dim=32, bilinear=False): + super().__init__() + self.n_channels = n_channels + self.n_classes = n_classes + self.bilinear = bilinear + + self.base_channel_sz = 128 + + self.inc = DoubleConv(n_channels, self.base_channel_sz) + self.down1 = Down(self.base_channel_sz, 2 * self.base_channel_sz) + self.down2 = Down(2 * self.base_channel_sz, 4 * self.base_channel_sz) + self.down3 = Down(4 * self.base_channel_sz, 8 * self.base_channel_sz) + factor = 2 if bilinear else 1 + self.down4 = Down(8 * self.base_channel_sz, 16 * self.base_channel_sz // factor) + + self.up1 = Up(16 * self.base_channel_sz, 8 * self.base_channel_sz // factor, bilinear) + self.up2 = Up(8 * self.base_channel_sz, 4 * self.base_channel_sz // factor, bilinear) + self.up3 = Up(4 * self.base_channel_sz, 2 * self.base_channel_sz // factor, bilinear) + self.up4 = Up(2 * self.base_channel_sz, self.base_channel_sz, bilinear) + + self.outc = OutConv(self.base_channel_sz, n_classes) + self.embedding_head = nn.Sequential( + nn.Conv2d(self.base_channel_sz, embedding_dim, kernel_size=1), + nn.Sigmoid() + ) + + def forward(self, x): + x1 = self.inc(x) + x2 = self.down1(x1) + x3 = self.down2(x2) + x4 = self.down3(x3) + x5 = self.down4(x4) + + x = self.up1(x5, x4) + x = self.up2(x, x3) + x = self.up3(x, x2) + x = self.up4(x, x1) + + seg_logits = self.outc(x) + embedding = self.embedding_head(x) + return seg_logits, embedding + + @staticmethod + def load_from_checkpoint(model_path: str, n_channels: int, n_classes: int): + model = UNet(n_channels=n_channels, n_classes=n_classes) + lightning_dict = torch.load(model_path, map_location="cpu") + state_dict = lightning_dict['state_dict'] + try: + model.load_state_dict(state_dict, strict=False) + except: + model.load_state_dict(state_dict) + return model + + +class UNetCarbon(nn.Module): + def __init__(self, n_channels, n_classes, dropout=0.25): + super(UNetCarbon, self).__init__() + self.n_channels = n_channels + self.n_classes = n_classes + self.base_channel_sz = 64 + + self.inc = (DoubleConv(n_channels, self.base_channel_sz)) + self.down1 = (DownCarbon(self.base_channel_sz, 2 * self.base_channel_sz)) + self.down2 = (DownCarbon(2 * self.base_channel_sz, 4 * self.base_channel_sz)) + self.down3 = (DownCarbon(4 * self.base_channel_sz, 8 * self.base_channel_sz)) + self.down4 = (DownCarbon(8 * self.base_channel_sz, 16 * self.base_channel_sz )) + self.up1 = (UpCarbon(16 * self.base_channel_sz, 8 * self.base_channel_sz)) + self.up2 = (UpCarbon(8 * self.base_channel_sz, 4 * self.base_channel_sz)) + self.up3 = (UpCarbon(4 * self.base_channel_sz, 2 * self.base_channel_sz)) + self.up4 = (UpCarbon(2 * self.base_channel_sz, self.base_channel_sz)) + self.outc = (OutConv(self.base_channel_sz, n_classes)) + + + def forward(self, x): + x1 = self.inc(x) + x2 = self.down1(x1) + x3 = self.down2(x2) + x4 = self.down3(x3) + x5 = self.down4(x4) + + x = self.up1(x5, x4) + x = self.up2(x, x3) + x = self.up3(x, x2) + x = self.up4(x, x1) + logits = self.outc(x) + + return logits + + @staticmethod + def load_from_checkpoint(model_path: str, n_channels: int, n_classes: int): + model = UNetCarbon(n_channels=n_channels, n_classes=n_classes) + lightning_dict = torch.load(model_path, map_location="cpu") + state_dict = lightning_dict['state_dict'] + try: + model.load_state_dict(state_dict, strict=False) + except: + model.load_state_dict(state_dict) + return model + + + +############################################################################### +# MRC + instance segmentation +############################################################################### +def load_mrc(mrc_fn: str, multiply_global_origin: bool = True): + with mrcfile.open(mrc_fn, "r") as mrc_file_handle: + voxel_size = float(mrc_file_handle.voxel_size.x) + if voxel_size <= 0: + raise RuntimeError(f"MRC file {mrc_fn} does not have a valid header.") + + c = mrc_file_handle.header["mapc"] + r = mrc_file_handle.header["mapr"] + s = mrc_file_handle.header["maps"] + + global_origin = mrc_file_handle.header["origin"] + global_origin = np.array([global_origin.x, global_origin.y, global_origin.z]) + global_origin[0] += mrc_file_handle.header["nxstart"] + global_origin[1] += mrc_file_handle.header["nystart"] + global_origin[2] += mrc_file_handle.header["nzstart"] + + if multiply_global_origin: + global_origin *= mrc_file_handle.voxel_size.x + + raw_data = mrc_file_handle.data + if c == 1 and r == 2 and s == 3: + grid = raw_data + elif c == 3 and r == 2 and s == 1: + grid = np.moveaxis(raw_data, [0, 1, 2], [2, 1, 0]) + elif c == 2 and r == 1 and s == 3: + grid = np.moveaxis(raw_data, [1, 2, 0], [2, 1, 0]) + else: + raise RuntimeError("MRC file axis arrangement not supported!") + return grid, voxel_size, global_origin + + +############################################################################### +# Sample coordinates from the final pruned label, including IDs +############################################################################### +def sample_coordinates_with_ids(label_image, step=50): + + labels = np.unique(label_image) + labels = labels[labels != 0] + labels.sort() # ensure ascending + results = [] + + filament_counter = 1 + for lbl in labels: + bin_mask = (label_image == lbl) + sk = Skeleton(bin_mask) + if sk.n_paths == 0: + continue + + # For each path in this label, sample coordinates + for p_idx in range(sk.n_paths): + coords = sk.path_coordinates(p_idx).astype(int) + if len(coords) == 0: + continue + for i in range(0, len(coords), step): + r, c = coords[i] + results.append([c, r, filament_counter]) + # ensure final coordinate is included + if (len(coords) - 1) % step != 0: + r, c = coords[-1] + results.append([c, r, filament_counter]) + + filament_counter += 1 + + return np.array(results, dtype=int) + + +############################################################################### +# Visualization Helpers +############################################################################### +import matplotlib.colors as mcolors + +def color_nonrandom(label_image): + H, W = label_image.shape + colorized = np.full((H, W, 3), 127, dtype=np.uint8) + + labels = np.unique(label_image) + labels = labels[labels != 0] + i = 0 + for lbl in labels: + if i%6==0: + r= 255 + g= 0 + b =0 + elif i%6==1: + r= 0 + g= 255 + b =0 + elif i%6==2: + r= 0 + g= 0 + b =255 + elif i%6==3: + r= 255 + g= 255 + b =0 + elif i%6==4: + r= 0 + g= 255 + b =255 + elif i%6==5: + r= 255 + g= 0 + b =255 + mask = (label_image == lbl) + colorized[mask] = (r, g, b) + i=i+1 + return colorized + +def color_foreground(grey_image, threshold): + grey_image_uint8 = (grey_image * 255).astype(np.uint8) + colorized = np.stack([grey_image_uint8] * 3, axis=-1) + mask = (grey_image > threshold) + colorized[mask] = (255, 0, 0) + return colorized + + +############################################################################### +# Sjors go at pruning the raw skeleton image +############################################################################### + +def trim_end(branch_coords, trim_length=10, trim_start=False): + """Trims the start or end of a branch by `trim_length` pixels.""" + if len(branch_coords) > trim_length: + return branch_coords[trim_length:] if trim_start else branch_coords[:-trim_length] + return np.array([]) # Remove short branches completely + +def angular_diff(a, b, period=180): + """Minimal circular difference between angles a and b on [0, period).""" + raw = abs(a - b) + return min(raw, period - raw) + +def segment_orientation(p0, p1): + """ + Compute the orientation (in degrees) and fold it into [0, 180). + p0, p1 are (row, col) integer tuples or arrays. + """ + # Note: row = y, col = x + dy = p1[0] - p0[0] + dx = p1[1] - p0[1] + # conventions of y-axis is reversed in RELION, so use -dy! + ang = np.degrees(np.arctan2(-dy, dx)) # gives [-180, 180) + + # fold into [0, 180): + if ang < 0: + ang += 180 + elif ang >= 180: + ang -= 180 + + return ang + +def split_branch_on_psi_mismatch(branch_coords, psi_image, threshold=20): + + segments = [] + current_seg = [tuple(branch_coords[0])] + prev_pt = branch_coords[0] + prev_ang = psi_image[prev_pt[0], prev_pt[1]] + + # step through each next point + for i in range(1, len(branch_coords)): + pt = branch_coords[i] + psi_ang = psi_image[pt[0], pt[1]] + + # split if jump in neighbour psi image values > threshold + do_split = False + if angular_diff(prev_ang, psi_ang) > threshold: + do_split = True + # compute seg_ang between i-3 and i + elif i >= 3: + p0 = branch_coords[i - 3] + seg_ang = segment_orientation(p0, pt) + # split if mismatch > threshold + if angular_diff(seg_ang, psi_ang) > threshold: + do_split = True + + if do_split: + segments.append(np.array(current_seg)) + current_seg = [] + + current_seg.append(tuple(pt)) + prev_ang = psi_ang + + # append last segment + if current_seg: + segments.append(np.array(current_seg)) + + return segments + +def prune_skeleton(skeleton, psi_image, min_length=100, min_distance=25, step=50, psi_threshold=45): + """Prune skeleton branches that too short.""" + # Most of the compute goes into the Skeleton call; rest of function is cheap + skel = Skeleton(skeleton) + df = summarize(skel, separator='-') + + trim_length = int(min_distance / 2) + labeled_skeleton = np.zeros_like(skeleton, dtype=np.int32) + accepted_branches = [] # Stores (branch coordinates, start, end) + sampled_coords = [] + + # Pass 0: split branches with jumps in psi-angle values + all_splits = [] + for idx, row in df.iterrows(): + coords = skel.path_coordinates(idx) + pieces = split_branch_on_psi_mismatch(coords, psi_image, threshold=psi_threshold) + all_splits.extend(pieces) + + # Pass 1: Collect branches and compute pairwise distances + branch_data = [] # Store branch info for pass 2 + endpoints = [] # Store (start, end) tuples + for branch_coords in all_splits: + + # Compute Euclidean length of the branch + length = np.sum(np.sqrt(np.sum(np.diff(branch_coords, axis=0) ** 2, axis=1))) + if length < min_length: + continue # Skip short branches + + start, end = tuple(branch_coords[0]), tuple(branch_coords[-1]) + branch_data.append((branch_coords, start, end)) + endpoints.append(start) + endpoints.append(end) + + if not branch_data: + return labeled_skeleton, np.array(sampled_coords, dtype=int) # No valid branches + + # Compute all pairwise distances between endpoints + endpoints = np.array(endpoints) # Convert to numpy array + dists = cdist(endpoints, endpoints) + + # Mark close endpoint pairs for trimming + close_pairs = np.where((dists < min_distance) ) # Exclude self-distances + trim_flags = {} # Dictionary to store which endpoints need trimming + + for i in range(len(close_pairs[0])): + idx1, idx2 = close_pairs[0][i], close_pairs[1][i] + branch_idx1, endpoint_type1 = divmod(idx1, 2) # Get branch index & endpoint type + branch_idx2, endpoint_type2 = divmod(idx2, 2) + + if branch_idx1 == branch_idx2: + continue # Ignore self-pairs + + # Mark both endpoints for trimming + trim_flags.setdefault((branch_idx1, endpoint_type1), True) + trim_flags.setdefault((branch_idx2, endpoint_type2), True) + + # **Pass 2: Trim branches based on identified close endpoints** + final_branches = [] + + for i, (branch_coords, start, end) in enumerate(branch_data): + # Trim start or end if flagged + if (i, 0) in trim_flags: + branch_coords = trim_end(branch_coords, trim_length, trim_start=True) + if (i, 1) in trim_flags: + branch_coords = trim_end(branch_coords, trim_length, trim_start=False) + + # Ensure branch still exists after trimming + if len(branch_coords) > 0: + final_branches.append(branch_coords) + + # Assign unique labels to final pruned branches + for path_id, branch in enumerate(final_branches, start=1): + for x, y in branch: + labeled_skeleton[int(x), int(y)] = path_id + + for i in range(0, len(branch), step): + r, c = branch[i] + sampled_coords.append([c, r, path_id]) + # ensure final coordinate is included + if (len(branch) - 1) % step != 0: + r, c = branch[-1] + sampled_coords.append([c, r, path_id]) + + return labeled_skeleton, np.array(sampled_coords, dtype=int) + +def resize_and_norm(image, mysize, angpix, do_norm=True): + ys, xs = image.shape + if (xs > ys): + scale = ys/mysize + else: + scale = xs/mysize + + xsp = int(xs/scale) + ysp = int(ys/scale) + resized_angpix = angpix *scale + resized = cv2.resize(image.astype(np.float32), (xsp, ysp), interpolation=cv2.INTER_AREA) + if do_norm: + max = resized.max() + min = resized.min() + if (max > min): + resized = (resized - min) / (max - min) + + return resized, resized_angpix + + +def install_model( + name: str, + verbose: bool = False, +): + model_list = { + "amytracer-v1.0": [ + "https://zenodo.org/records/17949642/files/amytracer-v1.0.ckpt.gz", + "d83777816d899d64aef593c97888e88f56d49e2b652cdc460de554f59d6f94ed" + ], + "amytracer-v2.0": [ + "https://zenodo.org/records/17949642/files/amytracer-v2.0.ckpt.gz", + "57f0cd566ca1779641691f7daf4a6147ccdb4f509f01c7472861e32bb7dbe14c" + ], + "carbonpicker-v1.0": [ + "https://zenodo.org/records/17949642/files/carbonpicker-v1.0.ckpt.gz", + "e25702cc84850339b46ac5b7d8e19ebdd55ad420c15bda8c9f9a584f59e7fd6b" + ] + } + + if name in model_list.keys(): + dest_dir = os.path.join(torch.hub.get_dir(), "checkpoints", "relion_trace_amyloids") + model_path = os.path.join(dest_dir, f"{name}.ckpt") + model_path_gz = model_path + ".gz" + completed_check_path = os.path.join(dest_dir, f"{name}_installed.txt") + + # Download file and install it if not already done + if not os.path.isfile(completed_check_path): + if verbose: + print(f"Installing amyloid picker model ({name})...") + os.makedirs(dest_dir, exist_ok=True) + + source_url = model_list[name][0] + + if verbose: + print(f"Downloading model weights from:\n {source_url}") + + import gzip, shutil + torch.hub.download_url_to_file(source_url, model_path_gz, hash_prefix=model_list[name][1]) + with gzip.open(model_path_gz, 'rb') as f_in: + with open(model_path, 'wb') as f_out: + shutil.copyfileobj(f_in, f_out) + os.remove(model_path_gz) + + with open(completed_check_path, "w") as f: + f.write("Successfully downloaded model") + + if verbose: + print(f"Amyloid picker model ({name}) successfully installed in {dest_dir}") + + else: + model_path = name + + return model_path + + + + +############################################################################### +# MAIN +############################################################################### +def main(): + + parser = argparse.ArgumentParser("Skeleton-based filament picking with instance merging, branch pruning, and ID labeling") + parser.add_argument("-i", "--input", help="Input star file", default="None") + parser.add_argument("-o", "--output", help="Output star file with coordinates", default="out") + parser.add_argument("-r", "--radius", type=int, help="Minimum distance between ends of filaments (in A)", default=25) + parser.add_argument("-l", "--minimum_length", type=int, default=250, + help="Remove final segments smaller than this size in Angstroms (default=250)") + parser.add_argument("-p", "--psi_jump_threshold", default=45, type=float, help="Maximum difference in degrees of psi angles for consecutive points in skeletons (default=45)") + parser.add_argument("-t", "--threshold", default=0.5, type=float, help="Foreground threshold (default=0.5)") + parser.add_argument("-c", "--carbon", action='store_true', help="Ignore filaments on carbon") + parser.add_argument("-ct", "--carbon_threshold", default=0.9, type=float, help="Carbon detection threshold (default=0.9)") + parser.add_argument("-s", "--scale", type=float, default=1.0, + help="Multiply output coordinates by this factor (default=1.0)") + parser.add_argument("-d", "--device", default="cuda:0", help="Which GPU device to use") + parser.add_argument("-j", "--threads", type=int, default=1) + parser.add_argument("-m", "--model_path", help="Path to PyTorch model checkpoint", default="amytracer-v2.0") + parser.add_argument("-cm", "--carbon_model_path", help="Path to PyTorch model checkpoint for carbon detection", default="carbonpicker-v1.0") + parser.add_argument("-a", "--abort", help="Abort if this file exists") + parser.add_argument("-v", "--verb", type=int, help="Verbosity") + parser.add_argument("--sample_step", type=int, default=100, + help="Sample a coordinate every 'sample_step' Angstroms along each path (default=50)") + parser.add_argument("--plot", action='store_true', + help="If set, display/save a collage figure of the pipeline results.") + args = parser.parse_args() + + # number of CPU threads allowed + #torch.set_num_threads(args.threads) + + # ------------------- Load model ---------------------- + device = torch.device(args.device) + + # This is for when we call this program without any arguments upon installation of the relion package (in scripts/python_fetch_weights.in) + if (args.input == "None"): + my_model_path = install_model(args.model_path, verbose=True) + my_carbon_model_path = install_model(args.carbon_model_path, verbose=True) + sys.exit(0) + + # Load checkpoint file + my_model_path = install_model(args.model_path) + model = UNet.load_from_checkpoint(my_model_path, n_channels=3, n_classes=1) + model.eval().to(device) + if not args.carbon: + if args.verb > 0: + print(" + Not doing carbon detection") + do_carbon = False + else: + do_carbon = True + if args.verb > 0: + print(" + Doing carbon detection") + my_carbon_model_path = install_model(args.carbon_model_path) + carbon_model = UNetCarbon.load_from_checkpoint(my_carbon_model_path, n_channels=1, n_classes=1) + carbon_model.eval().to(device) + + if args.plot: + print(" + Writing PNG file with intermediate results for every micrograph") + input_star = starfile.read(args.input) + + @torch.compile + def run_compiled_carbon_model(data): + seg_logits = carbon_model(data) + carbon_prob = torch.sigmoid(seg_logits.squeeze()) + return carbon_prob + + @torch.compile + def run_compiled_model(data): + seg_logits, embedding = model(data) + seg_prob = torch.sigmoid(seg_logits.squeeze()) + return seg_prob + + # ------------------ Run Inference ---------------- + iterator = tqdm(input_star.iterrows(), total=len(input_star), file=sys.stdout) if args.verb > 0 else input_star.iterrows() + half_dtype = torch.bfloat16 if torch.cuda.is_bf16_supported() else torch.float16 + for i, row in iterator: + + if Path(args.abort).exists(): + print("Abort file exists. Aborting...") + sys.exit() + + # ------------------- Load MRCs ---------------------- + fom_image, pixel_size, origin = load_mrc(row["rlnMicrographFomImage"]) + psi_image, _, _ = load_mrc(row["rlnMicrographPsiImage"]) + + #--------------------- Carbon detection ----------------- + if do_carbon: + #in_tensor = np.stack(mic_image, axis=0) + #in_tensor = torch.from_numpy(in_tensor[None,None]).to(device=device, dtype=half_dtype) # shape (1,1,H,W) + mic_image, ori_pixel_size, _ = load_mrc(row["rlnMicrographName"]) + mic_image, resized_angpix = resize_and_norm(mic_image, 64, ori_pixel_size) + in_tensor = torch.from_numpy(mic_image[None,None]).to(device=device, dtype=half_dtype) # shape (1,1,H,W) + with torch.no_grad(): + if device.type == "cuda": + with torch.autocast(device_type=device.type, dtype=half_dtype): + carbon_prob = run_compiled_carbon_model(in_tensor) + else: + with torch.autocast(device_type="cpu", dtype=half_dtype): + carbon_prob = run_compiled_carbon_model(in_tensor) + carbon_prob = carbon_prob.to(dtype=torch.float32, device="cpu").numpy() + xsf, ysf= fom_image.shape + if carbon_prob.shape != fom_image.shape: + carbon_prob = cv2.resize(carbon_prob.astype(np.float32), (ysf, xsf), interpolation=cv2.INTER_AREA) + carbon_mask = (carbon_prob>args.carbon_threshold) + + #--------------------- Filament segmentation ----------------- + outfile = row["rlnMicrographCoordinates"] + directory = Path(outfile).parent + # Check if the directory exists, and create it if not + directory.mkdir(parents=True, exist_ok=True) + + H, W = fom_image.shape + + rad_psi = np.deg2rad(psi_image * 2) + in_tensor = np.stack((fom_image, np.sin(rad_psi), np.cos(rad_psi)), axis=0) # shape (3,H,W) + in_tensor = torch.from_numpy(in_tensor[None]).to(device=device, dtype=half_dtype) # shape (1,3,H,W) + + with torch.no_grad(): + if device.type == "cuda": + with torch.autocast(device_type=device.type, dtype=half_dtype): + seg_prob = run_compiled_model(in_tensor) + else: + with torch.autocast(device_type="cpu", dtype=half_dtype): + seg_prob = run_compiled_model(in_tensor) + foreground = seg_prob.to(dtype=torch.float32, device="cpu").numpy() + + # 2) Clean + threshold => remove small objects + bin_foreground = (foreground > args.threshold) + if do_carbon: + bin_foreground = bin_foreground & (~carbon_mask) + + min_size = 100 + clean_foreground = remove_small_objects(bin_foreground, min_size=min_size) + + # 3) Crop edges if radius is given + if args.radius is not None: + d = round(args.radius / pixel_size) + clean_foreground[:d, :] = False + clean_foreground[-d:, :] = False + clean_foreground[:, :d] = False + clean_foreground[:, -d:] = False + + # 4) Skeletonize + skeleton_img = skeletonize(clean_foreground) + + # if there is only a single non-zero pixel, Skeleton will give an error. Let's check for at least 10 non-zero pixels + if np.count_nonzero(skeleton_img) > 10: + + # 5) Prune skeleton based on Skan's branches: splits branches with jumps in psi-angles, remove any branch with length below args.final_min_size, and enforce minimal distance between end points + pruned_skeleton, sampled_points = prune_skeleton(skeleton_img, + psi_image, + min_length=args.minimum_length / pixel_size, + min_distance=2 * args.radius / pixel_size, + step=int(args.sample_step / pixel_size), + psi_threshold=args.psi_jump_threshold) + + # 6) Sample coordinates every 'sample_step' from pruned skeleton, **including filament ID**. + #sampled_points = sample_coordinates_with_ids(pruned_skeleton, step=int(args.sample_step / pixel_size)) + # sampled_points shape: (N, 3) => [x, y, filament_id] + if sampled_points.size > 0: + + # 7) Scale, round, write star + # scale only the x,y columns + sampled_points[:, 0:2] = np.round(sampled_points[:, 0:2] * args.scale).astype(int) + + df = pd.DataFrame({ + 'rlnCoordinateX': sampled_points[:, 0], + 'rlnCoordinateY': sampled_points[:, 1], + 'rlnParticleSelectionType': sampled_points[:, 2] + }) + starfile.write(df, outfile, overwrite=True) + else: + Path(outfile).touch() + else: + Path(outfile).touch() + + # --------------------------------------------------- + # If plotting is requested, create a collage figure + # --------------------------------------------------- + if args.plot: + + fig, ax = plt.subplots(2, 4, figsize=(20,15)) + ax = ax.ravel() + + ax[0].imshow(fom_image, cmap='gray') + ax[0].set_title("FOM Image") + ax[0].axis('off') + + ax[1].imshow(psi_image, cmap='gray') + ax[1].set_title("PSI Image") + ax[1].axis('off') + + ax[2].imshow(color_foreground(foreground, args.threshold)) + ax[2].set_title("Foreground") + ax[2].axis('off') + + ax[3].imshow(skeleton_img) + ax[3].set_title("Raw Skeleton") + ax[3].axis('off') + + if do_carbon: + ax[4].imshow(mic_image, cmap='gray') + ax[4].set_title("micrograph") + ax[4].axis('off') + + ax[5].imshow(color_foreground(carbon_prob, args.carbon_threshold)) + ax[5].set_title("carbon detection") + ax[5].axis('off') + + if skeleton_img.any() and np.count_nonzero(skeleton_img) > 10: + ax[6].imshow(color_nonrandom(pruned_skeleton)) + ax[6].set_title("Pruned Skeleton") + ax[6].axis('off') + + if sampled_points.size > 0: + ax[7].imshow(np.zeros_like(foreground), cmap='gray') # blank background + ax[7].scatter(sampled_points[:,0]/args.scale, sampled_points[:,1]/args.scale, s=2, c='red') + ax[7].set_xlim([0, foreground.shape[1]]) + ax[7].set_ylim([foreground.shape[0], 0]) + ax[7].set_title("Final Sampled Picks (ID shown in STAR)") + ax[7].axis('off') + + plt.tight_layout() + out_png = os.path.splitext(outfile)[0] + ".png" + plt.savefig(out_png, dpi=200, bbox_inches="tight") + plt.close() + + +if __name__ == "__main__": + main() diff --git a/src/acc/acc_ml_optimiser_impl.h b/src/acc/acc_ml_optimiser_impl.h index c29c2401b..fa3552d75 100644 --- a/src/acc/acc_ml_optimiser_impl.h +++ b/src/acc/acc_ml_optimiser_impl.h @@ -144,11 +144,11 @@ void getFourierTransformsAndCtfs(long int part_id, // If there were no defined priors (i.e. their values were 999.), then use the "normal" angles // Also do this for local angular searches when not doing helical refinement (e.g. for subtomograms picked on certain geometries) // Note that helical refinement deals with priors in a special manner... So leave that untouched... - if (prior_rot > 998.99 && prior_rot < 999.01 || (!baseMLO->do_helical_refine && do_local_angular_searches) ) + if (prior_rot > 998.99 && prior_rot < 999.01 || (!baseMLO->do_helical_refine && do_local_angular_searches && !baseMLO->keep_angular_priors_fixed ) ) prior_rot = DIRECT_A2D_ELEM(baseMLO->exp_metadata, op.metadata_offset, METADATA_ROT); - if (prior_tilt > 998.99 && prior_tilt < 999.01 || (!baseMLO->do_helical_refine && do_local_angular_searches) ) + if (prior_tilt > 998.99 && prior_tilt < 999.01 || (!baseMLO->do_helical_refine && do_local_angular_searches && !baseMLO->keep_angular_priors_fixed ) ) prior_tilt = DIRECT_A2D_ELEM(baseMLO->exp_metadata, op.metadata_offset, METADATA_TILT); - if (prior_psi > 998.99 && prior_psi < 999.01 || (!baseMLO->do_helical_refine && do_local_angular_searches) ) + if (prior_psi > 998.99 && prior_psi < 999.01 || (!baseMLO->do_helical_refine && do_local_angular_searches && !baseMLO->keep_angular_priors_fixed ) ) prior_psi = DIRECT_A2D_ELEM(baseMLO->exp_metadata, op.metadata_offset, METADATA_PSI); if (prior_psi_flip_ratio > 998.99 && prior_psi_flip_ratio < 999.01) prior_psi_flip_ratio = 0.5; diff --git a/src/align_tiltseries_runner.cpp b/src/align_tiltseries_runner.cpp index 4e7eb22a8..93b172bc9 100644 --- a/src/align_tiltseries_runner.cpp +++ b/src/align_tiltseries_runner.cpp @@ -46,11 +46,19 @@ void AlignTiltseriesRunner::read(int argc, char **argv, int rank) do_aretomo_tiltcorrect = parser.checkOption("--aretomo_tiltcorrect", "Specify to correct the tilt angle offset in the tomogram (AreTomo -TiltCor option; default=false)"); aretomo_tilcorrect_angle = textToFloat(parser.getOption("--aretomo_tiltcorrect_angle", "User-specified tilt angle correction (value > 180, means estimate automatically", "999.")); do_aretomo_ctf = parser.checkOption("--aretomo_ctf", "Perform CTF estimation in AreTomo? (default=false)"); - do_aretomo_phaseshift = parser.checkOption("--aretomo_phaseshift", "Perform CTF estimation in AreTomo? (default=false)"); + do_aretomo_phaseshift = parser.checkOption("--aretomo_phaseshift", "Perform CTF estimation in AreTomo?"); + do_aretomo_reconstruct = parser.checkOption("--aretomo_reconstruct", "Perform Tomogram reconstruction (WBP) in AreTomo?"); + do_only_aretomo_reconstruct = parser.checkOption("--aretomo_only_reconstruct", "Only perform Tomogram reconstruction in AreTomo, and skip alignment/CTF estimation?"); + if (do_only_aretomo_reconstruct) do_aretomo_reconstruct = true; + aretomo_OutBin = textToInteger(parser.getOption("--aretomo_OutBin", "Binning for the output reconstruction by AreTomo", "4")); + aretomo_VolZ = textToInteger(parser.getOption("--aretomo_VolZ", "Height of the output tomogram reconstruction (in unbinned voxels)", "0")); gpu_ids = parser.getOption("--gpu", "Device ids for each MPI-thread, e.g 0:1:2:3", ""); int exp_section = parser.addSection("Expert options"); other_wrapper_args = parser.getOption("--other_wrapper_args", "Additional command-line arguments that will be passed onto the wrapper.", ""); + do_aretomo_sart = parser.checkOption("--aretomo_sart", "Use SART instead of weighted backprojection for aretomo reconstructions."); + aretomo_sart_iter = textToInteger(parser.getOption("--aretomo_sart_iter", "Number of iterations for aretomo SART reconstruction", "20")); + aretomo_sart_proj = textToInteger(parser.getOption("--aretomo_sart_proj", "Number of projections per iterations for aretomo SART reconstruction", "5")); // Initialise verb for non-parallel execution verb = 1; @@ -260,15 +268,12 @@ bool AlignTiltseriesRunner::checkResults(long idx_tomo) // check that .aln (and _ctf.txt if do_aretomo_ctf) file(s) has been written out FileName fn_aln = fn_dir + tomoname + ".aln"; FileName fn_ctf = fn_dir + tomoname + "_ctf.txt"; + FileName fn_tomo = fn_out + "tomograms/rec_" + tomoname + ".mrc"; - if (do_aretomo_ctf) - { - return (exists(fn_ctf) && exists(fn_aln)); - } - else - { - return exists(fn_aln); - } + bool has_required = exists(fn_aln); + if (has_required && do_aretomo_ctf) has_required = exists(fn_ctf); + if (has_required && do_aretomo_reconstruct) has_required = exists(fn_tomo); + return has_required; } else @@ -284,44 +289,82 @@ bool AlignTiltseriesRunner::checkResults(long idx_tomo) return false; } -void AlignTiltseriesRunner::generateMRCStackAndRawTiltFile(long idx_tomo, bool is_aretomo) +void AlignTiltseriesRunner::generateMRCStackAndRawTiltFileOrAlnFile(long idx_tomo, bool is_aretomo) { FileName fn_dir = fn_out + "external/" + tomogramSet.getTomogramName(idx_tomo) + '/'; - FileName fn_tilt = fn_dir + tomogramSet.getTomogramName(idx_tomo) + ".rawtlt"; - FileName fn_series = fn_dir + tomogramSet.getTomogramName(idx_tomo) + ".mrc"; - std::ofstream fh; - fh.open((fn_tilt).c_str(), std::ios::out); + // Write out tilt series stack Image Imic, Iseries; - std::vector frame_dose_order = tomogramSet.getFrameDoseOrder(idx_tomo); - + RFLOAT angpix = tomogramSet.getTiltSeriesPixelSize(idx_tomo); int fc = tomogramSet.tomogramTables[idx_tomo].numberOfObjects(); for (int f = 0; f < fc; f++) { FileName fn_mic; - RFLOAT tiltangle; tomogramSet.tomogramTables[idx_tomo].getValue(EMDL_MICROGRAPH_NAME, fn_mic, f); - tomogramSet.tomogramTables[idx_tomo].getValue(EMDL_TOMO_NOMINAL_TILT_STAGE_ANGLE, tiltangle, f); - RFLOAT dose; - tomogramSet.tomogramTables[idx_tomo].getValue(EMDL_MICROGRAPH_PRE_EXPOSURE, dose, f); - // IMOD: 1-column and AreTomo2 2-column raw tilt angle file with tilt angles (and order of acquisition). - fh << tiltangle; - if (is_aretomo) fh << " " << frame_dose_order[f]; - fh << std::endl; Imic.read(fn_mic); if (f == 0) Iseries().resize(fc, YSIZE(Imic()), XSIZE(Imic())); Iseries().setSlice(f, Imic()); - } - RFLOAT angpix = tomogramSet.getTiltSeriesPixelSize(idx_tomo); tomogramSet.globalTable.getDouble(EMDL_TOMO_IMPORT_FRACT_DOSE, idx_tomo); if (is_aretomo) Iseries.setSamplingRateInHeader(angpix); + FileName fn_series = fn_dir + tomogramSet.getTomogramName(idx_tomo) + ".mrc"; Iseries.write(fn_series); - fh.close(); + // Write out text file with rawtilt or aln + std::ofstream fh; + if (do_only_aretomo_reconstruct) + { + // make aln file + FileName fn_aln = fn_dir + tomogramSet.getTomogramName(idx_tomo) + ".aln"; + fh.open((fn_aln).c_str(), std::ios::out); + + std::vector frame_tilt_order_index = tomogramSet.getFrameTiltOrderIndex(idx_tomo); + fh << "# AreTomo Alignment / Priims bprmMn \n"; + fh << "# RawSize = " << integerToString(XSIZE(Iseries())) << " " << integerToString(YSIZE(Iseries())) << " " << integerToString(ZSIZE(Iseries())) <<"\n"; + fh << "# NumPatches = 0\n"; + fh << "# SEC ROT GMAG TX TY SMEAN SFIT SCALE BASE TILT\n"; + for (int f = 0; f < fc; f++) + { + int fp = frame_tilt_order_index[f]; + RFLOAT xtilt=0., ytilt, zrot, xshift, yshift; + tomogramSet.tomogramTables[idx_tomo].getValue(EMDL_TOMO_YTILT, ytilt, fp); + tomogramSet.tomogramTables[idx_tomo].getValue(EMDL_TOMO_ZROT, zrot, fp); + tomogramSet.tomogramTables[idx_tomo].getValue(EMDL_TOMO_XSHIFT_ANGST, xshift, fp); + tomogramSet.tomogramTables[idx_tomo].getValue(EMDL_TOMO_YSHIFT_ANGST, yshift, fp); + //AreTomo shifts are in pixels, bnot Angstroms! + xshift /= angpix; + yshift /= angpix; + + char buffer[256]; + std::snprintf(buffer, sizeof(buffer), + "%5d %9.4f %9.5f %9.3f %9.3f %7.2f %7.2f %7.2f %7.2f %8.2f\n", + fp, zrot, 1., xshift, yshift, 1., 1., 1., 0., ytilt); + fh << buffer; + } + } + else + { + // make rawtlt file + FileName fn_tilt = fn_dir + tomogramSet.getTomogramName(idx_tomo) + ".rawtlt"; + fh.open((fn_tilt).c_str(), std::ios::out); + + std::vector frame_dose_order = tomogramSet.getFrameDoseOrder(idx_tomo); + for (int f = 0; f < fc; f++) + { + RFLOAT tiltangle; + tomogramSet.tomogramTables[idx_tomo].getValue(EMDL_TOMO_NOMINAL_TILT_STAGE_ANGLE, tiltangle, f); + RFLOAT dose; + tomogramSet.tomogramTables[idx_tomo].getValue(EMDL_MICROGRAPH_PRE_EXPOSURE, dose, f); + // IMOD: 1-column and AreTomo2 2-column raw tilt angle file with tilt angles (and order of acquisition). + fh << tiltangle; + if (is_aretomo) fh << " " << frame_dose_order[f]; + fh << std::endl; + } + } + fh.close(); } @@ -389,7 +432,7 @@ void AlignTiltseriesRunner::executeIMOD(long idx_tomo, int rank) // Make sure metadata table is sorted on rlnTomoNominalStageTiltAngle (it should be, but anyways...) tomogramSet.tomogramTables[idx_tomo].newSort(EMDL_TOMO_NOMINAL_TILT_STAGE_ANGLE); - generateMRCStackAndRawTiltFile(idx_tomo, false); + generateMRCStackAndRawTiltFileOrAlnFile(idx_tomo, false); // Now run the actual IMOD command std::string command = fn_batchtomo_exe; @@ -430,14 +473,12 @@ void AlignTiltseriesRunner::executeAreTomo(long idx_tomo, int rank) FileName fn_ali = fn_dir + tomoname + "_aligned.mrc"; FileName fn_log = fn_dir + tomoname + ".log"; FileName fn_com = fn_dir + tomoname + ".com"; + FileName fn_aln = fn_dir + tomoname + ".aln"; - std::ofstream fh; - fh.open((fn_tilt).c_str(), std::ios::out); - Image Imic, Iseries; - int fc = tomogramSet.tomogramTables[idx_tomo].numberOfObjects(); - std::vector frame_dose_order = tomogramSet.getFrameDoseOrder(idx_tomo); + // Make sure metadata table is sorted on rlnTomoNominalStageTiltAngle (it should be, but anyways...) + tomogramSet.tomogramTables[idx_tomo].newSort(EMDL_TOMO_NOMINAL_TILT_STAGE_ANGLE); - generateMRCStackAndRawTiltFile(idx_tomo, true); + generateMRCStackAndRawTiltFileOrAlnFile(idx_tomo, true); RFLOAT frac_dose = tomogramSet.globalTable.getDouble(EMDL_TOMO_IMPORT_FRACT_DOSE, idx_tomo); RFLOAT pixel_size = tomogramSet.getTiltSeriesPixelSize(idx_tomo); @@ -450,46 +491,74 @@ void AlignTiltseriesRunner::executeAreTomo(long idx_tomo, int rank) // Now run the actual AreTomo command std::string command = fn_aretomo_exe + " "; command += " -InMrc " + fn_series; - command += " -AngFile " + fn_tilt; command += " -OutMrc " + fn_ali; - command += " -ImgDose " + floatToString(frac_dose); - // Tomogram thickness should be in unbinned pixels - command += " -AlignZ " + floatToString(thickness_pix); - // Skip reconstruction of the tomogram in AreTomo... - command += " -volZ 0"; - if (tomogramSet.tomogramTables[idx_tomo].containsLabel(EMDL_TOMO_NOMINAL_TILT_AXIS_ANGLE)) + if (do_only_aretomo_reconstruct) { - RFLOAT tiltaxis_angle = tomogramSet.tomogramTables[idx_tomo].getDouble(EMDL_TOMO_NOMINAL_TILT_AXIS_ANGLE, 0); - command += " -TiltAxis " + floatToString(tiltaxis_angle); + command += " -Align 0 "; + command += " -AlnFile " + fn_aln; } - - if (do_aretomo_tiltcorrect) + else { - command += " -TiltCor 1 "; - if (aretomo_tilcorrect_angle < 180.) - command += floatToString(aretomo_tilcorrect_angle); + command += " -AngFile " + fn_tilt; + command += " -ImgDose " + floatToString(frac_dose); + // Tomogram thickness should be in unbinned pixels + command += " -AlignZ " + floatToString(thickness_pix); + } + if (do_aretomo_reconstruct) + { + command += " -FlipVol 1 -volZ " + integerToString(aretomo_VolZ); + command += " -OutBin " + integerToString(aretomo_OutBin); + if (do_aretomo_sart) + { + command += " -Sart " + integerToString(aretomo_sart_iter) + " " + integerToString(aretomo_sart_proj); + } + else + { + command += " -Wbp 1"; + } } else { - command += " -TiltCor -1 "; + command += " -volZ 0"; } - if (do_aretomo_ctf) + if (!do_only_aretomo_reconstruct) { - // Also estimate CTF parameters in AreTomo - RFLOAT kV, Cs, Q0; - RFLOAT angpix = tomogramSet.getTiltSeriesPixelSize(idx_tomo); - tomogramSet.globalTable.getValue(EMDL_CTF_VOLTAGE, kV, idx_tomo); - tomogramSet.globalTable.getValue(EMDL_CTF_CS, Cs, idx_tomo); - tomogramSet.globalTable.getValue(EMDL_CTF_Q0, Q0, idx_tomo); - command += " -Kv " + floatToString(kV); - command += " -Cs " + floatToString(Cs); - command += " -AmpContrast " + floatToString(Q0); - command += " -PixSize " + floatToString(angpix); - if (do_aretomo_phaseshift) - command += " -ExtPhase 90 180"; + if (tomogramSet.tomogramTables[idx_tomo].containsLabel(EMDL_TOMO_NOMINAL_TILT_AXIS_ANGLE)) + { + RFLOAT tiltaxis_angle = tomogramSet.tomogramTables[idx_tomo].getDouble(EMDL_TOMO_NOMINAL_TILT_AXIS_ANGLE, 0); + command += " -TiltAxis " + floatToString(tiltaxis_angle); + } + + if (do_aretomo_tiltcorrect) + { + command += " -TiltCor 1 "; + if (aretomo_tilcorrect_angle < 180.) + command += floatToString(aretomo_tilcorrect_angle); + } + else + { + command += " -TiltCor -1 "; + } + + + if (do_aretomo_ctf) + { + // Also estimate CTF parameters in AreTomo + RFLOAT kV, Cs, Q0; + RFLOAT angpix = tomogramSet.getTiltSeriesPixelSize(idx_tomo); + tomogramSet.globalTable.getValue(EMDL_CTF_VOLTAGE, kV, idx_tomo); + tomogramSet.globalTable.getValue(EMDL_CTF_CS, Cs, idx_tomo); + tomogramSet.globalTable.getValue(EMDL_CTF_Q0, Q0, idx_tomo); + command += " -Kv " + floatToString(kV); + command += " -Cs " + floatToString(Cs); + command += " -AmpContrast " + floatToString(Q0); + command += " -PixSize " + floatToString(angpix); + if (do_aretomo_phaseshift) + command += " -ExtPhase 90 180"; + } } if (gpu_ids.length() > 0) @@ -838,6 +907,31 @@ bool AlignTiltseriesRunner::readAreTomoResults(long idx_tomo, std::string &error } } + if (do_aretomo_reconstruct) + { + std::string tomoname = tomogramSet.getTomogramName(idx_tomo); + FileName fn_inmap = fn_out + "external/" + tomoname + "/" + tomoname + "_aligned.mrc"; + FileName fn_tomodir = fn_out + "tomograms/"; + if (!exists(fn_tomodir)) mktree(fn_tomodir); + FileName fn_outmap = fn_tomodir + "rec_" + tomoname + ".mrc"; + std::string command = "mv -f " + fn_inmap + " " + fn_outmap; + int res = system(command.c_str()); + + // Read image size from header (don't read data!) + Image Itomo; + Itomo.read(fn_outmap, false); + // Set information about the tomogram in the globalTable + float floatbin = aretomo_OutBin; + int xs = aretomo_OutBin*XSIZE(Itomo()); + int ys = aretomo_OutBin*YSIZE(Itomo()); + int zs = aretomo_OutBin*ZSIZE(Itomo()); + tomogramSet.globalTable.setValue(EMDL_TOMO_TOMOGRAM_BINNING, floatbin, idx_tomo); + tomogramSet.globalTable.setValue(EMDL_TOMO_SIZE_X, xs, idx_tomo); + tomogramSet.globalTable.setValue(EMDL_TOMO_SIZE_Y, ys, idx_tomo); + tomogramSet.globalTable.setValue(EMDL_TOMO_SIZE_Z, zs, idx_tomo); + tomogramSet.globalTable.setValue(EMDL_TOMO_RECONSTRUCTED_TOMOGRAM_FILE_NAME, fn_outmap, idx_tomo); + + } MetaDataTable MDnew; for (int i = 0; i < rot.size(); i++) @@ -946,7 +1040,8 @@ void AlignTiltseriesRunner::joinResults() } } - tomogramSet.write(fn_out+"aligned_tilt_series.star"); + FileName fnt = (do_aretomo && do_aretomo_reconstruct) ? fn_out+"tomograms.star" : fn_out+"aligned_tilt_series.star"; + tomogramSet.write(fnt); if (do_aretomo && do_aretomo_ctf) { diff --git a/src/align_tiltseries_runner.h b/src/align_tiltseries_runner.h index 346ff0be9..bc926e844 100644 --- a/src/align_tiltseries_runner.h +++ b/src/align_tiltseries_runner.h @@ -157,6 +157,24 @@ class AlignTiltseriesRunner // Do phase shift estimation in AreTomo? bool do_aretomo_phaseshift; + // Do AreTomo reconstruction? + bool do_aretomo_reconstruct; + + //Skip alignment and CTF-estimation: only reconstruct: generate .aln file from input STAR file, which must contain tiltseries alignments + bool do_only_aretomo_reconstruct; + + // By default use Wbp in Aretomo, but can also use SART + bool do_aretomo_sart; + + // Number of SART iterations and the number of projections per iteration + int aretomo_sart_iter, aretomo_sart_proj; + + // AreTomo reconstruction Z-height (in unbinned pixels) + int aretomo_VolZ; + + // Aretomo reconstruction binning + int aretomo_OutBin; + // estimated tomogram thickness (for -AlignZ) RFLOAT tomogram_thickness; @@ -191,7 +209,7 @@ class AlignTiltseriesRunner bool checkResults(long idx_tomo); // Generate MRC stack and raw tilt file - void generateMRCStackAndRawTiltFile(long idx_tomo, bool is_aretomo); + void generateMRCStackAndRawTiltFileOrAlnFile(long idx_tomo, bool is_aretomo); // Execute IMOD for a single tomogram void executeIMOD(long idx_tomo, int rank = 0); diff --git a/src/amyloid_finder.cpp b/src/amyloid_finder.cpp new file mode 100644 index 000000000..1f1b238ba --- /dev/null +++ b/src/amyloid_finder.cpp @@ -0,0 +1,1006 @@ +/*************************************************************************** + * + * Author: "Sjors H.W. Scheres" + * MRC Laboratory of Molecular Biology + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This complete copyright notice must be included in any revised version of the + * source code. Additional authorship citations may be added, but existing + * author citations must be preserved. + ***************************************************************************/ +#include "src/amyloid_finder.h" +//#define DEBUG_BOUNDS + +void AmyloidFinder::read(int argc, char **argv, int rank) +{ + parser.setCommandLine(argc, argv); + + + int general_section = parser.addSection("General options"); + fn_in = parser.getOption("--i", "Input image (.mrc) or STAR file with micrographs"); + fn_out = parser.getOption("--pickname", "Rootname for coordinate STAR files", "autopick"); + fn_odir = parser.getOption("--odir", "Output directory for coordinate files (default is to store next to micrographs)", "AutoPick/"); + do_only_unfinished = parser.checkOption("--only_do_unfinished", "Only estimate CTFs for those tomograms for which there is not yet a logfile with Final values."); + nr_threads = textToInteger(parser.getOption("--j", "Number of threads to us in parallel", "1")); + + int search_section = parser.addSection("Filament searching options "); + psi_step = textToFloat(parser.getOption("--psi_step", "Angular sampling rate (in degrees)", "5.")); + shift_step = textToInteger(parser.getOption("--shift_step", "Step in shifts to search (in downscaled pixels)", "5")); + search_filament_width = textToFloat(parser.getOption("--search_filament_width", "Width of searching image (in A)", "50")); + search_filament_length = textToFloat(parser.getOption("--search_filament_length", "Length of searching image (in A)", "250")); + do_skip_fom = parser.checkOption("--skip_fom", "Skip FOM calculation."); + + int pick_section = parser.addSection("Filament tracing options "); + threshold = textToFloat(parser.getOption("--threshold", "Threshold in Z-scores for coordinate picking", "0.5")); + trace_filament_width = textToFloat(parser.getOption("--trace_filament_width", "Minimum width occupied by a traced filaments (in A)", "100")); + trace_filament_length = textToFloat(parser.getOption("--trace_filament_length", "Minimum length of traced filaments (in A)", "300")); + psi_jump_threshold = textToFloat(parser.getOption("--psi_jump_threshold", "Maximum difference in PSI values between consecutive elements of a skeletonised branch (in degrees)", "45")); + do_plot = parser.checkOption("--plot", "Display images with intermediate tracing results for each micrograph"); + fn_exe = parser.getOption("--exe", "Name of python script for filament tracing", "relion_python_trace_amyloids"); + fn_other_args = parser.getOption("--other_args", "Other arguments for the python script", ""); + fn_model_path = parser.getOption("--model_path", "Name of the model to execute for filament tracing","amytracer-v2.0"); + do_carbon = parser.checkOption("--detect_carbon", "Detect carbon and ignore filaments on there."); + fn_carbon_model_path = parser.getOption("--carbon_model_path", "Name of the model to execute for carbon detection","carbonpicker-v1.0"); + carbon_threshold = textToFloat(parser.getOption("--carbon_threshold", "Threshold for carbon detection", "0.9")); + do_skip_tracing = parser.checkOption("--skip_tracing", "Skip tracing."); + do_gpu = parser.checkOption("--gpu", "Use GPU acceleration when availiable"); + gpu_ids = parser.getOption("--gpu", "Device ids for each MPI-thread","default"); + + int expert_section = parser.addSection("Expert options (typically no need to change)"); + signal_minres = textToFloat(parser.getOption("--signal_minres", "Minimum resolution value for signal (in A)", "4.85")); + signal_maxres = textToFloat(parser.getOption("--signal_maxres", "Maximum resolution value for signal (in A)", "4.65")); + nonsignal_minres = textToFloat(parser.getOption("--nonsignal_minres", "Minimum resolution value for non-signal (in A)", "4.4")); + nonsignal_maxres = textToFloat(parser.getOption("--nonsignal_maxres", "Maximum resolution value for non-signal (in A)", "4.2")); + down_angpix = textToFloat(parser.getOption("--down_angpix", "Pixel size for downscaled images (needs to include signal frequency!)", "2.1")); + angpix = textToFloat(parser.getOption("--force_angpix", "Force this pixel size, regardless of what is in the image header", "-1")); + verb =textToInteger(parser.getOption("--verb", "Verbosity", "1")); + + // Check for errors in the command-line option + if (parser.checkForErrors()) + REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); +} + +void AmyloidFinder::usage() +{ + parser.writeUsage(std::cout); +} + +void AmyloidFinder::initialise(bool is_leader) +{ + // Make sure fn_odir ends with a slash + if (fn_odir[fn_odir.length()-1] != '/') + fn_odir += "/"; + + fn_ori_micrographs.clear(); + fn_ori_micrographs_fom.clear(); + fn_ori_micrographs_psi.clear(); + + todo_micrographs_fom.clear(); + todo_micrographs_tracing.clear(); + if (fn_in.isStarFile()) + { + MetaDataTable MDin; + MDin.read(fn_in, "micrographs"); + + if (do_skip_fom && !(MDin.containsLabel(EMDL_MICROGRAPH_AUTOPICK_FOM) && MDin.containsLabel(EMDL_MICROGRAPH_AUTOPICK_PSI))) + { + REPORT_ERROR("ERROR: You are skipping FOM calculation, but the input STAR file does not contain the FOM/PSI images."); + } + FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDin) + { + FileName fn_mic; + MDin.getValue(EMDL_MICROGRAPH_NAME, fn_mic); + fn_ori_micrographs.push_back(fn_mic); + if (MDin.containsLabel(EMDL_MICROGRAPH_AUTOPICK_FOM) && MDin.containsLabel(EMDL_MICROGRAPH_AUTOPICK_PSI)) + { + MDin.getValue(EMDL_MICROGRAPH_AUTOPICK_FOM, fn_mic); + fn_ori_micrographs_fom.push_back(fn_mic); + MDin.getValue(EMDL_MICROGRAPH_AUTOPICK_PSI, fn_mic); + fn_ori_micrographs_psi.push_back(fn_mic); + } + } + } + else + { + // Read a single micrograph + fn_ori_micrographs.push_back(fn_in); + } + + if (!do_only_unfinished) + { + if (!do_skip_fom) todo_micrographs_fom = fn_ori_micrographs; + if (!do_skip_tracing) + { + todo_micrographs_tracing = fn_ori_micrographs; + idx_todo_micrographs_tracing.resize(todo_micrographs_tracing.size()); + std::iota(idx_todo_micrographs_tracing.begin(), idx_todo_micrographs_tracing.end(), 0); + } + } + else + { + // If we're continuing an old run, see which micrographs have not been finished yet... + // A. for FOM/PSI calculation + if (!do_skip_fom) + { + if (verb > 0) + { + std::cout << " + Skipping those micrographs for which FOM and PSI images already exist" << std::endl; + } + todo_micrographs_fom.clear(); + for (long int imic = 0; imic < fn_ori_micrographs.size(); imic++) + { + FileName fn_fom = getOutputRootName(fn_ori_micrographs[imic]) + "_" + fn_out + "_fom.mrc"; + FileName fn_psi = getOutputRootName(fn_ori_micrographs[imic]) + "_" + fn_out + "_psi.mrc"; + if (!exists(fn_fom) || !exists(fn_psi)) + todo_micrographs_fom.push_back(fn_ori_micrographs[imic]); + } + } + // B. For tracing + if (!do_skip_tracing) + { + if (do_skip_fom && (fn_ori_micrographs_fom.size() == 0 || fn_ori_micrographs_psi.size() == 0)) + { + REPORT_ERROR("ERROR: you cannot skip FOM calculation without providing autopick FOM and PSI images in the input STAR file!"); + } + + if (verb > 0) + { + std::cout << " + Skipping those micrographs for which coordinate file already exists" << std::endl; + } + for (long int imic = 0; imic < fn_ori_micrographs.size(); imic++) + { + FileName fn_tmp = getOutputRootName(fn_ori_micrographs[imic]) + "_" + fn_out + ".star"; + if (!exists(fn_tmp)) + { + todo_micrographs_tracing.push_back(fn_ori_micrographs[imic]); + idx_todo_micrographs_tracing.push_back(imic); + } + } + + } + } + + if (verb > 0) + { + std::cout << " + Calculating FOM images for " << todo_micrographs_fom.size() << " micrographs... " << std::endl; + std::cout << " + Tracing filaments for " << todo_micrographs_tracing.size() << " micrographs... " << std::endl; + } + + // Read in header of first image + Image Iin; + Iin.read(fn_ori_micrographs[0], false); + ori_xsize = XSIZE(Iin()); + ori_ysize = YSIZE(Iin()); + Iin().setXmippOrigin(); + if (angpix < 0.) + { + angpix = Iin.samplingRateX(); + if (verb > 0) std::cout << " - Using pixel size from the header of : " << fn_in << " = " << angpix << std::endl; + } + if (nonsignal_maxres < 2*down_angpix) REPORT_ERROR("ERROR: the down_angpix is not enough to support the maximum resolution of the signal!"); + if (angpix > down_angpix) REPORT_ERROR("ERROR: this program requires input images with a pixel size of at least down_angpix (" + floatToString(down_angpix) + ")!"); + + if (todo_micrographs_fom.size() > 0) + { + + + // Width and length in the downscaled pixels + iwidthmax = ROUND(search_filament_width / down_angpix ); + ilengthmax = CEIL(search_filament_length / down_angpix ); + + down_xsize = FLOOR( (ori_xsize * angpix) / down_angpix ); + down_ysize = FLOOR( (ori_ysize * angpix) / down_angpix ); + if (ilengthmax %2 != 0) ilengthmax++; + nr_psi = ROUND(180./psi_step); + psi_step = 180./nr_psi; + + // Calculate Fourier shells for amyloid signal + imin_signal = FLOOR(ilengthmax*down_angpix/signal_minres); + imax_signal = CEIL(ilengthmax*down_angpix/signal_maxres); + imin_nonsignal = FLOOR(ilengthmax*down_angpix/nonsignal_minres); + imax_nonsignal = CEIL(ilengthmax*down_angpix/nonsignal_maxres); + + // Box size, orginal and cropped: set size of rectangular image to largest dimension + large_box = sqrt(2.)*XMIPP_MAX(ori_xsize, ori_ysize); + large_box += ROUND(XMIPP_MAX(search_filament_width, search_filament_length) / angpix); + if (large_box%2 != 0) large_box++; + // Also calculate size of cropped box: + crop_box = large_box * angpix/down_angpix; + if (crop_box%2 != 0) crop_box++; + + // Output some information to the user + if (verb > 0) + { + std::cout << " + Number of 1D rows for filament width (in downscaled pixels): " << iwidthmax << std::endl; + std::cout << " + Length of 1D rows for filament (in downscaled pixels): " << ilengthmax << std::endl; + std::cout << " + Number of in-plane rotations to sample: " << nr_psi << " with step of " << psi_step << " degrees" << std::endl; + std::cout << " + Original size of the input micrographs: " << ori_xsize << " x " << ori_ysize << " pixels" << std::endl; + std::cout << " + Size of image to sample (in downscaled pixels): " << down_xsize << " x " << down_ysize << std::endl; + std::cout << " + Fourier shells for the amyloid signal (in downscaled pixels): " << imin_signal << " - " << imax_signal << std::endl; + std::cout << " + Fourier shells for the non-signal control (in downscaled pixels): " << imin_nonsignal << " - " << imax_nonsignal << std::endl; + std::cout << " ========================== " << std::endl; + } + } + +} + + +#if defined _CUDA_ENABLED +void AmyloidFinder::deviceInitialise() +{ + int devCount; + accGPUGetDeviceCount(&devCount); + + std::vector < std::vector < std::string > > allThreadIDs; + untangleDeviceIDs(gpu_ids, allThreadIDs); + + // Sequential initialisation of GPUs on all ranks + if (!std::isdigit(*gpu_ids.begin())) + device_id = 0; + else + device_id = textToInteger((allThreadIDs[0][0]).c_str()); + + if (verb>0) + { + std::cout << " + Using GPU device " << device_id << std::endl; + } +} +#endif + +FileName AmyloidFinder::getOutputRootName(FileName fn_mic) +{ + FileName fn_pre, fn_jobnr, fn_post; + decomposePipelineFileName(fn_mic, fn_pre, fn_jobnr, fn_post); + return fn_odir + fn_post.withoutExtension(); +} + +RFLOAT AmyloidFinder::getPsiAngle(int ipsi) +{ + return 2.3 + ipsi * psi_step; +} + +MultidimArray AmyloidFinder::growNonSignalMask(MultidimArray &inmask, int extend_size) +{ + + MultidimArray Mresult = inmask; + RFLOAT extend_ini_mask2 = extend_size * extend_size; + +#pragma omp parallel for num_threads(nr_threads) + for (long int i=STARTINGY(inmask)+extend_size; i<=FINISHINGY(inmask)-extend_size; i++) + { + for (long int j=STARTINGX(inmask)+extend_size; j<=FINISHINGX(inmask)-extend_size; j++) + { + // only extend from 1 values + if (A2D_ELEM(inmask, i, j) > 0.99) + { + for (long int ip = i - extend_size; ip <= i + extend_size; ip++) + { + for (long int jp = j - extend_size; jp <= j + extend_size; jp++) + { + // only check distance if neighbouring pixel is zero + if (A2D_ELEM(inmask, ip, jp) < 0.01) + { + RFLOAT r2 = (RFLOAT)( (ip-i)*(ip-i)+ (jp-j)*(jp-j) ); + // Set original voxel to 1 if a neghouring with Im()=1 is within distance extend_ini_mask + if (r2 < extend_ini_mask2) + { + A2D_ELEM(Mresult, ip, jp) = 1.; + } + } + } + } + } + } + } + + return Mresult; + +} +void AmyloidFinder::getScoreForOneMicrograph(MultidimArray &image, MultidimArray &Mscore, + MultidimArray &Mangle, RFLOAT &skew, RFLOAT &kurt, bool myverb) +{ + + MultidimArray Mbig(large_box, large_box); + Mbig.setXmippOrigin(); + for (long int i=STARTINGY(Mbig); i<=FINISHINGY(Mbig); i++) + { + long int ip = i; + //if (i < STARTINGY(image)) ip += YSIZE(image); + //else if (i > FINISHINGY(image)) ip -= YSIZE(image); + if (i < STARTINGY(image)) ip = 2*STARTINGY(image) - i; + else if (i > FINISHINGY(image)) ip = 2*FINISHINGY(image) - i; + + for (long int j=STARTINGX(Mbig); j<=FINISHINGX(Mbig); j++) + { + long int jp = j; + if (j < STARTINGX(image)) jp = 2*STARTINGX(image) - j; + else if (j > FINISHINGX(image)) jp = 2*FINISHINGX(image) - j; + + A2D_ELEM(Mbig, i, j) = A2D_ELEM(image, ip, jp); + } + } + + // Rotate the large image, and store downscaled images by cropping their Fourier Transform + std::vector > rotated_imgs(nr_psi), rotated_scores_perline(nr_psi), rotated_scores(nr_psi); + std::vector > rotated_nonscores_perline(nr_psi), rotated_nonscores(nr_psi); + std::vector transformer(nr_threads); + // TODO: in principle, only need to rotate to 90 degrees, as I can use both the X and the Y direction for the 1D FFTs! + if (myverb) + { + std::cout << " - Rotating the input image ..." << std::endl; + init_progress_bar(nr_psi); + } + +#pragma omp parallel for num_threads(nr_threads) + for (int ipsi = 0; ipsi < nr_psi/2; ipsi++) + { + const int tid = omp_get_thread_num(); + RFLOAT psi = getPsiAngle(ipsi); + + // Rotate the images in their original size to prevent interpolation artefacts near the signal frequencies + MultidimArray Mrot; + Mrot.setXmippOrigin(); + Mrot.initZeros(large_box, large_box); + rotate(Mbig, Mrot, psi, 'Z', true); + + //Image Ir; + //Ir()=Mrot; + //Ir.write("Ir_psi"+ integerToString(ipsi)+".spi"); + //std::cerr << " written: " << "Ir_psi"<< integerToString(ipsi)<<".spi" << std::endl; + + // Re-scale image so that Nyquist is at down_angpix + MultidimArray FT, FT2; + transformer[tid].FourierTransform(Mrot, FT, false); + windowFourierTransform(FT, FT2, crop_box); + Mrot.resize(crop_box, crop_box); + transformer[tid].inverseFourierTransform(FT2, Mrot); + Mrot.setXmippOrigin(); + rotated_imgs[ipsi] = Mrot; + + } + MultidimArray Mzero(crop_box, crop_box); + Mzero.setXmippOrigin(); + for (int ipsi = nr_psi/2; ipsi < nr_psi; ipsi++) + { + rotated_imgs[ipsi] = Mzero; + // stay away from boundary to prevent many if-statements below. Images are cropped in larger box anyway, so boundaries should be zero + for (long int i=STARTINGY(Mzero)+1; i<=FINISHINGY(Mzero)-1; i++) + { + for (long int j=STARTINGX(Mzero)+1; j<=FINISHINGX(Mzero)-1; j++) + { + A2D_ELEM(rotated_imgs[ipsi], i, j) = A2D_ELEM(rotated_imgs[ipsi-nr_psi/2], -j, i); + } + } + } + + if (myverb) progress_bar(nr_psi); + + // Just prepare the rotated_scores vector too + for (int ipsi = 0; ipsi < nr_psi; ipsi++) + { + rotated_scores_perline[ipsi].initZeros(crop_box, crop_box); + rotated_scores_perline[ipsi].setXmippOrigin(); + rotated_nonscores_perline[ipsi].initZeros(crop_box, crop_box); + rotated_nonscores_perline[ipsi].setXmippOrigin(); + rotated_scores[ipsi].initZeros(crop_box/shift_step, crop_box/shift_step); + rotated_scores[ipsi].setXmippOrigin(); + rotated_nonscores[ipsi].initZeros(crop_box/shift_step, crop_box/shift_step); + rotated_nonscores[ipsi].setXmippOrigin(); + } + + // Prepare all the transformers for the 1D lines + MultidimArray oneline_tmp(ilengthmax); + for (int i = 0; i < nr_threads; i++) + transformer[i].setReal(oneline_tmp); + + // Now loop over all positions to calculate 1D FFTs + if (myverb) + { + std::cout << " - Searching over all coordinates ..." << std::endl; + init_progress_bar(nr_psi); + } + + int my_skip_side_length = ilengthmax/2; + for (int ipsi = 0; ipsi < nr_psi; ipsi++) + { +#pragma omp parallel for num_threads(nr_threads) + for (int ypos = my_skip_side_length; ypos < YSIZE(rotated_imgs[ipsi]) - my_skip_side_length; ypos += 1) + { + int cen_ypos = ypos - YSIZE(rotated_imgs[ipsi])/2; + const int tid = omp_get_thread_num(); + MultidimArray oneline(ilengthmax); + MultidimArray FTline(ilengthmax/2 + 1); + + for (int xpos = my_skip_side_length; xpos < XSIZE(rotated_imgs[ipsi]) - my_skip_side_length; xpos += 1) + { + int cen_xpos = xpos - XSIZE(rotated_imgs[ipsi])/2; + + // Grab the line from the rotated image, in X and in Y directions + for (int iline = 0; iline < ilengthmax; iline++) + DIRECT_A1D_ELEM(oneline, iline) = A2D_ELEM(rotated_imgs[ipsi], cen_ypos, cen_xpos+iline-ilengthmax/2); + + transformer[tid].FourierTransform(oneline, FTline, false); + + for (int isig = imin_signal; isig <= imax_signal; isig++) + { + A2D_ELEM(rotated_scores_perline[ipsi], cen_ypos, cen_xpos) += norm(DIRECT_A1D_ELEM(FTline, isig)); + } + for (int isig = imin_nonsignal; isig <= imax_nonsignal; isig++) + { + A2D_ELEM(rotated_nonscores_perline[ipsi], cen_ypos, cen_xpos) += norm(DIRECT_A1D_ELEM(FTline, isig)); + } + + } // end loop ypos + } // end for xpos + + /* + Image It0; + It0()= rotated_scores_perline[ipsi]; + FileName fnt0="It0_scores_psi"+ integerToString(ipsi)+".spi"; + It0.write(fnt0); + std::cerr <<" written: "< It; + It()= rotated_scores[ipsi]; + FileName fnt="It_scores_psi"+ integerToString(ipsi)+".spi"; + It.write(fnt); + std::cerr <<" written: "< Msum, Mnonsum, Mnonscore, Mneighbour, Mneighbour2; + Msum.resize(Mangle); + Mnonsum.resize(Mangle); + Mnonscore.resize(Mangle); + Mneighbour.resize(Mangle); + Mneighbour2.resize(Mangle); + + // This can't be parallelised efficiently because need to protect Msums, Mscore and Mangle from simultaneous writing... + // Calculate Z-scores over psi: (max_psi - avg_psi) /stddev_psi + int xsize = XSIZE(Mscore); + int ysize = YSIZE(Mscore); + for (int ipsi = 0; ipsi < nr_psi; ipsi++) + { + RFLOAT mypsi = getPsiAngle(ipsi); + for (int ypos = 0; ypos < ysize; ypos ++) + { + int cen_ypos = ypos - ysize/2; + for (int xpos = 0; xpos < xsize; xpos ++) + { + int cen_xpos = xpos - xsize/2; + + RFLOAT myscore = A2D_ELEM(rotated_scores[ipsi], cen_ypos, cen_xpos); + RFLOAT mynonscore = A2D_ELEM(rotated_nonscores[ipsi], cen_ypos, cen_xpos); + A2D_ELEM(Msum, cen_ypos, cen_xpos) += myscore; + A2D_ELEM(Mnonsum, cen_ypos, cen_xpos) += mynonscore; + + if (myscore > A2D_ELEM(Mscore, cen_ypos, cen_xpos)) + { + A2D_ELEM(Mscore, cen_ypos, cen_xpos) = myscore; + A2D_ELEM(Mangle, cen_ypos, cen_xpos) = mypsi; + int ipsi_nb = (ipsi == 0) ? nr_psi - 1 : ipsi - 1; + A2D_ELEM(Mneighbour, cen_ypos, cen_xpos) = A2D_ELEM(rotated_scores[ipsi_nb], cen_ypos, cen_xpos); + ipsi_nb = (ipsi == nr_psi - 1) ? 0 : ipsi + 1; + A2D_ELEM(Mneighbour, cen_ypos, cen_xpos) += A2D_ELEM(rotated_scores[ipsi_nb], cen_ypos, cen_xpos); + } + + if (mynonscore > A2D_ELEM(Mnonscore, cen_ypos, cen_xpos)) + { + A2D_ELEM(Mnonscore, cen_ypos, cen_xpos) = mynonscore; + int ipsi_nb = (ipsi == 0) ? nr_psi - 1 : ipsi - 1; + A2D_ELEM(Mneighbour2, cen_ypos, cen_xpos) = A2D_ELEM(rotated_nonscores[ipsi_nb], cen_ypos, cen_xpos); + ipsi_nb = (ipsi == nr_psi - 1) ? 0 : ipsi + 1; + A2D_ELEM(Mneighbour2, cen_ypos, cen_xpos) += A2D_ELEM(rotated_nonscores[ipsi_nb], cen_ypos, cen_xpos); + } + + } + } + } + +//#define DEBUG_FOM +#ifdef DEBUG_FOM + Image It, It2; + It()= Mscore; + FileName fnt="Mscore.spi"; + It.write(fnt); + std::cerr <<" written: "< 0.) + Zscore_signal = (DIRECT_MULTIDIM_ELEM(Mscore, n) - DIRECT_MULTIDIM_ELEM(Msum, n)) / DIRECT_MULTIDIM_ELEM(Msum, n); + DIRECT_MULTIDIM_ELEM(Mscore, n) = Zscore_signal; + +#ifdef DEBUG_FOM + DIRECT_MULTIDIM_ELEM(It(), n) = Zscore_signal; +#endif + + // Also for non-signal + DIRECT_MULTIDIM_ELEM(Mnonsum, n) -= DIRECT_MULTIDIM_ELEM(Mnonscore, n) + DIRECT_MULTIDIM_ELEM(Mneighbour2, n); + DIRECT_MULTIDIM_ELEM(Mnonsum, n) /= (RFLOAT)(nr_psi-3); + RFLOAT Zscore_nonsignal = 0.; + if (DIRECT_MULTIDIM_ELEM(Mnonsum, n) > 0.) + { + Zscore_nonsignal = (DIRECT_MULTIDIM_ELEM(Mnonscore, n) - DIRECT_MULTIDIM_ELEM(Mnonsum, n)) / DIRECT_MULTIDIM_ELEM(Mnonsum, n); + +#ifdef DEBUG_FOM + DIRECT_MULTIDIM_ELEM(It2(), n) = Zscore_nonsignal; +#endif + // binarize to generate a non-signal mask + Zscore_nonsignal = (Zscore_nonsignal < 0.7) ? 0 : 1; + } + DIRECT_MULTIDIM_ELEM(Mnonscore, n) = Zscore_nonsignal; + + } + + // Grow the nonsignal mask a bit, as ice crystals give artefacts near their borders + Mnonscore = growNonSignalMask(Mnonscore, iwidthmax); + +#ifdef DEBUG_FOM + fnt="Zscore_signal.spi"; + It.write(fnt); + fnt="Zscore_nonsignal.spi"; + It2.write(fnt); + It()=Mnonscore; + It.write("grownmask.spi"); +#endif + + // Apply inverse non-signal mask to the Mscore to calculate final FOM image + RFLOAT sum=0., sum2=0.; + FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(Mscore) + { + DIRECT_MULTIDIM_ELEM(Mscore, n) *= (1. - DIRECT_MULTIDIM_ELEM(Mnonscore, n)); + // Also calculate mean and stddev of final combined score over the whole micrograph, to later calculate skewness and kurtosis for signal detection + sum += DIRECT_MULTIDIM_ELEM(Mscore, n); + sum2 += DIRECT_MULTIDIM_ELEM(Mscore, n) * DIRECT_MULTIDIM_ELEM(Mscore, n); + + } + +#ifdef DEBUG_FOM + It()=Mscore; + fnt="fom.spi"; + It.write(fnt); +#endif + + // Output skewness and kurtosis of Mscore distribution to detect which micrographs have filaments + RFLOAT n = NZYXSIZE(Msum); + sum /= n; + sum2 /= n; + sum2 = sqrt(sum2-sum*sum); + skew = 0.; + kurt = 0.; + FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(Msum) + { + RFLOAT aux = (DIRECT_MULTIDIM_ELEM(Mscore, n) - sum)/sum2; + skew += aux*aux*aux; + kurt += aux*aux*aux*aux; + } + kurt *= n*(n+1)/((n-1)*(n-2)*(n-3)); + skew *= n/((n-1)*(n-2)); + + if (myverb) progress_bar(nr_psi); + +} + + +void AmyloidFinder::calculateFOMOneMicrograph(FileName fn_mic, bool myverb) +{ + + FileName fn_root = getOutputRootName(fn_mic); + FileName fn_fom = fn_root + "_" + fn_out + "_fom.mrc"; + FileName fn_psi = fn_root + "_" + fn_out + "_psi.mrc"; + FileName fn_skew = fn_root + "_" + fn_out + "_skew.txt"; + MultidimArray Mscore, Mangle; + + if (!exists(fn_fom) || !exists(fn_psi)) + { + + Image Iin; + Iin.read(fn_mic); + Iin().setXmippOrigin(); + if (XSIZE(Iin()) != ori_xsize || YSIZE(Iin()) != ori_ysize || fabs(angpix - Iin.samplingRateX()) > 0.001) + REPORT_ERROR("ERROR: incorrect size or pixel size for image " + fn_mic); + + RFLOAT skew, kurt; + getScoreForOneMicrograph(Iin(), Mscore, Mangle, skew, kurt, myverb); + + Image Ipsi, Izscore; + Ipsi.setSamplingRateInHeader(down_angpix*shift_step); + Izscore.setSamplingRateInHeader(down_angpix*shift_step); + Ipsi()=Mangle; + Izscore()=Mscore; + // Set the skewness and kurtosis in the header of the FOM image + Izscore.MDMainHeader.setValue(EMDL_IMAGE_STATS_AVG, skew); + Izscore.MDMainHeader.setValue(EMDL_IMAGE_STATS_STDDEV, kurt); + Ipsi.write(fn_psi); + Izscore.write(fn_fom); + } + + if (myverb) std::cout << "done!" << std::endl; + + + +} + + +void AmyloidFinder::runFOMBatch(long int my_first, long int my_last) +{ + + long int my_nr = my_last - my_first + 1; + if (my_nr <= 0) return; + + int barstep; + if (verb > 0) + { + std::cout << " Calculating FOMs ..." << std::endl; + init_progress_bar(my_nr); + barstep = XMIPP_MAX(1, my_nr / 60); + } + + FileName fn_olddir=""; + for (long int imic = my_first; imic <= my_last; imic++) + { + + // Abort through the pipeline_control system + if (pipeline_control_check_abort_job()) + exit(RELION_EXIT_ABORTED); + + // Check new-style outputdirectory exists and make it if not! + FileName fn_oroot = getOutputRootName(todo_micrographs_fom[imic]); + FileName fn_dir = fn_oroot.beforeLastOf("/"); + if (fn_dir != fn_olddir) + { + // Make a Particles directory + mktree(fn_dir); + fn_olddir = fn_dir; + } +#ifdef TIMING + timer.tic(TIMING_A5); +#endif + calculateFOMOneMicrograph(todo_micrographs_fom[imic], todo_micrographs_fom.size() == 1); + if (verb > 0 && (imic-my_first+1)%barstep == 0) progress_bar(imic - my_first + 1); +#ifdef TIMING + timer.toc(TIMING_A5); +#endif + } + + if (verb > 0) progress_bar(my_nr); + +} + +void AmyloidFinder::runTracingBatch(long int my_first, long int my_last, int my_rank) +{ + long int my_nr = my_last - my_first + 1; + if (my_nr <= 0) return; + + if (verb > 0) std::cout << " - Tracing filaments ..." << std::endl; + + // TODO!!! Make a temp STAR file with mic, fom and psi names to pass to Jenny's program!!!! + // takes from my_first to my_last! + FileName fn_tracing_star = fn_odir + "input_trace_rank" + integerToString(my_rank) + ".star"; + MetaDataTable MDtrace; + FileName fn_fom, fn_psi; + for (long int imic = my_first; imic <= my_last; imic++) + { + MDtrace.addObject(); + FileName fn_root = getOutputRootName(todo_micrographs_tracing[imic]); + if (do_skip_fom) + { + long int imic_ori = idx_todo_micrographs_tracing[imic]; + fn_fom = fn_ori_micrographs_fom[imic_ori]; + fn_psi = fn_ori_micrographs_psi[imic_ori]; + } + else + { + fn_fom = fn_root + "_" + fn_out + "_fom.mrc"; + fn_psi = fn_root + "_" + fn_out + "_psi.mrc"; + } + // remove leading job number from fn_mic filename + FileName fn_pick = fn_root + "_" + fn_out + ".star"; + MDtrace.setValue(EMDL_MICROGRAPH_NAME, todo_micrographs_tracing[imic]); + MDtrace.setValue(EMDL_MICROGRAPH_AUTOPICK_FOM, fn_fom); + MDtrace.setValue(EMDL_MICROGRAPH_AUTOPICK_PSI, fn_psi); + MDtrace.setValue(EMDL_MICROGRAPH_COORDINATES, fn_pick); + } + MDtrace.write(fn_tracing_star); + + Image It; + It.read(fn_fom, false); + down_angpix = It.samplingRateX(); + + // hardcoded python script for now... + FileName command = fn_exe; + + command += " -i " + fn_tracing_star; + command += " -m " + fn_model_path; + if (do_gpu) + { + command += " -d cuda:" + integerToString(device_id); + } + else + { + command += " -d cpu"; + command += " -j " + integerToString(nr_threads); + } + command += " -t " + floatToString(threshold); + command += " -r " + floatToString(trace_filament_width/2); + command += " -l " + floatToString(trace_filament_length); + command += " -p " + floatToString(psi_jump_threshold); + command += " -s " + floatToString(down_angpix/angpix); + command += " -a " + pipeline_control_outputname+RELION_JOB_ABORT_NOW; + command += " -v " + integerToString(verb); + if (do_carbon) + { + command += " -c "; + command += " -cm " + fn_carbon_model_path; + command += " --carbon_threshold " + floatToString(carbon_threshold); + } + if (do_plot) + command += " --plot "; + + command += " " + fn_other_args; + + std::cerr << command << std::endl; + int res = system(command.c_str()); + + if (pipeline_control_check_abort_job()) + exit(RELION_EXIT_ABORTED); + else if (res != 0) exit(RELION_EXIT_FAILURE); + +} + + +void AmyloidFinder::run() +{ + + runFOMBatch(0, todo_micrographs_fom.size() - 1); + runTracingBatch(0, todo_micrographs_tracing.size() - 1); + +} + + +void AmyloidFinder::finalise() +{ + + long int barstep = XMIPP_MAX(1, fn_ori_micrographs.size() / 60); + if (verb > 0) + { + std::cout << " Generating output list of coordinate files ... " << std::endl; + init_progress_bar(fn_ori_micrographs.size()); + } + + MetaDataTable MDin; + ObservationModel obsModel; + ObservationModel::loadSafely(fn_in, obsModel, MDin, "micrographs", verb); + + MetaDataTable MDcoords; + MDcoords.setName("coordinate_files"); + long total_nr_picked = 0; + int nr_coord_files = 0; + for (long int imic = 0; imic < fn_ori_micrographs.size(); imic++) + { + + FileName fn_root = getOutputRootName(fn_ori_micrographs[imic]); + FileName fn_fom = (do_skip_fom) ? fn_ori_micrographs_fom[imic] : fn_root + "_" + fn_out + "_fom.mrc"; + + if (!do_skip_fom) + { + FileName fn_psi = fn_root + "_" + fn_out + "_psi.mrc"; + + Image Ifom; + Ifom.read(fn_fom, false); + RFLOAT kurt = 0., skew = 0.; + Ifom.MDMainHeader.getValue(EMDL_IMAGE_STATS_AVG, skew); + Ifom.MDMainHeader.getValue(EMDL_IMAGE_STATS_STDDEV, kurt); + if (isnan(skew)) skew = 0.; + if (isnan(kurt)) kurt = 0.; + + MDin.setValue(EMDL_MICROGRAPH_SCORE_KURTOSIS, kurt, imic); + MDin.setValue(EMDL_MICROGRAPH_SCORE_SKEWNESS, skew, imic); + MDin.setValue(EMDL_MICROGRAPH_AUTOPICK_FOM, fn_fom, imic); + MDin.setValue(EMDL_MICROGRAPH_AUTOPICK_PSI, fn_psi, imic); + } + + if (!do_skip_tracing) + { + + FileName fn_pick = fn_root + "_" + fn_out + ".star"; + + MetaDataTable MD; + MD.read(fn_pick); + long nr_pick = MD.numberOfObjects(); + total_nr_picked += nr_pick; + MDin.setValue(EMDL_MLMODEL_GROUP_NR_PARTICLES, nr_pick, imic); + + MDcoords.addObject(); + MDcoords.setValue(EMDL_MICROGRAPH_NAME, fn_ori_micrographs[imic]); + MDcoords.setValue(EMDL_MICROGRAPH_COORDINATES, fn_pick); + MDcoords.setValue(EMDL_MICROGRAPH_AUTOPICK_FOM, fn_fom); + nr_coord_files++; + + } + + if (verb > 0 && imic % 60 == 0) progress_bar(imic); + + } + + if (verb > 0) progress_bar(fn_ori_micrographs.size()); + + // Make histograms of skewness and kurtosis of FOM values for all micrographs + FileName fn_eps; + std::vector all_fn_eps; + std::vector histX, histY; + + if (!do_skip_fom) + { + + FileName fn_mics = fn_odir + "micrographs_" + fn_out + ".star"; + obsModel.save(MDin, fn_mics, "micrographs"); + if (verb > 0) std::cout << " Saved output micrograph STAR file with FOM images in: " << fn_mics << std::endl; + + CPlot2D *plot2De=new CPlot2D("Skewness of FOM for all micrographs"); + MDin.addToCPlot2D(plot2De, EMDL_UNDEFINED, EMDL_MICROGRAPH_SCORE_SKEWNESS, 1.); + plot2De->SetDrawLegend(false); + fn_eps = fn_odir + "all_FOM_skew.eps"; + plot2De->OutputPostScriptPlot(fn_eps); + all_fn_eps.push_back(fn_eps); + delete plot2De; + if (MDin.numberOfObjects() > 3) + { + CPlot2D *plot2Df=new CPlot2D(""); + MDin.columnHistogram(EMDL_MICROGRAPH_SCORE_SKEWNESS,histX,histY,0, plot2Df); + fn_eps = fn_odir + "histogram_FOM_skew.eps"; + plot2Df->SetTitle("Histogram of FOM skewness per micrograph"); + plot2Df->OutputPostScriptPlot(fn_eps); + all_fn_eps.push_back(fn_eps); + delete plot2Df; + } + + CPlot2D *plot2Dg=new CPlot2D("Kurtosis of FOM for all micrographs"); + MDin.addToCPlot2D(plot2Dg, EMDL_UNDEFINED, EMDL_MICROGRAPH_SCORE_KURTOSIS, 1.); + plot2Dg->SetDrawLegend(false); + fn_eps = fn_odir + "all_FOM_kurt.eps"; + plot2Dg->OutputPostScriptPlot(fn_eps); + all_fn_eps.push_back(fn_eps); + delete plot2Dg; + if (MDin.numberOfObjects() > 3) + { + CPlot2D *plot2Dh=new CPlot2D(""); + MDin.columnHistogram(EMDL_MICROGRAPH_SCORE_KURTOSIS,histX,histY,0, plot2Dh); + fn_eps = fn_odir + "histogram_FOM_kurt.eps"; + plot2Dh->SetTitle("Histogram of FOM kurtosis per micrograph"); + plot2Dh->OutputPostScriptPlot(fn_eps); + all_fn_eps.push_back(fn_eps); + delete plot2Dh; + } + + } + + if (!do_skip_tracing) + { + + CPlot2D *plot2De=new CPlot2D("Nr of picked particles for all micrographs"); + MDin.addToCPlot2D(plot2De, EMDL_UNDEFINED, EMDL_MLMODEL_GROUP_NR_PARTICLES, 1.); + plot2De->SetDrawLegend(false); + fn_eps = fn_odir + "all_nrparts.eps"; + plot2De->OutputPostScriptPlot(fn_eps); + all_fn_eps.push_back(fn_eps); + delete plot2De; + if (MDin.numberOfObjects() > 3) + { + CPlot2D *plot2Df=new CPlot2D(""); + MDin.columnHistogram(EMDL_MLMODEL_GROUP_NR_PARTICLES,histX,histY,0, plot2Df); + fn_eps = fn_odir + "histogram_nrparts.eps"; + plot2Df->SetTitle("Histogram of nr of picked particles per micrograph"); + plot2Df->OutputPostScriptPlot(fn_eps); + all_fn_eps.push_back(fn_eps); + delete plot2Df; + } + + FileName fn_coords = fn_odir + fn_out + ".star"; + + MetaDataTable MDhead; + MDhead.setIsList(true); + MDhead.setName("general"); + MDhead.addObject(); + std::string picktype = "lines"; + MDhead.setValue(EMDL_MICROGRAPH_PICKTYPE, picktype); + + std::vector MDins; + MDins.push_back(MDhead); + MDins.push_back(MDcoords); + writeMultipleTablesToStar(MDins, fn_coords); + + } + + joinMultipleEPSIntoSinglePDF(fn_odir + "logfile.pdf", all_fn_eps); + +} \ No newline at end of file diff --git a/src/amyloid_finder.h b/src/amyloid_finder.h new file mode 100644 index 000000000..8b55cd2ec --- /dev/null +++ b/src/amyloid_finder.h @@ -0,0 +1,170 @@ +/*************************************************************************** + * + * Author: "Sjors H.W. Scheres" + * MRC Laboratory of Molecular Biology + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This complete copyright notice must be included in any revised version of the + * source code. Additional authorship citations may be added, but existing + * author citations must be preserved. + ***************************************************************************/ +#ifndef RELION_AMYLOID_FINDER_H +#define RELION_AMYLOID_FINDER_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // for std::iota + +struct AmyloidCoordinate +{ + RFLOAT x, y, psi, fom, order; +}; + +class AmyloidFinder +{ +public: + + // I/O Parser + IOParser parser; + + // Verbosity + int verb; + + // Output rootname + FileName fn_in, fn_odir, fn_out, fn_other_args; + + // Psi sampling step + RFLOAT psi_step; + + // Original pixel size, and the downscaled one + RFLOAT angpix, down_angpix; + + // Fourier shells for amyloid signal and non-signal + RFLOAT signal_minres, signal_maxres, nonsignal_minres, nonsignal_maxres; + + // Threshold for selecting peaks in Zscore map + RFLOAT threshold; + + // Plot filament tracing results? + bool do_plot; + + // Skip FOM calculation or tracing call + bool do_skip_fom, do_skip_tracing; + + // width and length of filaments (in A) for searching of 4.7A signal + RFLOAT search_filament_length, search_filament_width; + + // Minimum length for tracing filaments + RFLOAT trace_filament_length, trace_filament_width; + + // Redo existing tracings? + bool do_redo_tracing; + + // Detect carbon in filament tracing to ignore filaments on carbon + bool do_carbon; + + // threshold for carbon detection + RFLOAT carbon_threshold; + + // threshold for psi-jumps in tracing skeletons + RFLOAT psi_jump_threshold; + + // FileName for carbon detection model + FileName fn_carbon_model_path; + + // FileName for Jenny's model + FileName fn_model_path; + + // Use GPU to execute the model? + bool do_gpu; + + // Which GPU devices to use? + std::string gpu_ids; + + // GPU Device ID + int device_id = -1; + + // Python executable name + FileName fn_exe; + + // Sampling of positions + int shift_step, ori_xsize, ori_ysize, down_xsize, down_ysize; + + // Number of psi samplings + int nr_psi; + + //Number of openMP trhreads + int nr_threads; + + // Some public parameters + int iwidthmax, ilengthmax, imin_signal, imax_signal, imin_nonsignal, imax_nonsignal, large_box, crop_box; + std::vector circle; + + // All and selected micrographs to autopick from + std::vector fn_ori_micrographs, fn_ori_micrographs_fom, fn_ori_micrographs_psi, todo_micrographs_fom, todo_micrographs_tracing; + std::vector idx_todo_micrographs_tracing; + + // Continue an old run: only estimate CTF if logfile WITH Final Values line does not yet exist, otherwise skip the tomogram + bool do_only_unfinished; + +public: + // Read command line arguments + void read(int argc, char **argv, int rank = 0); + + // Print usage instructions + void usage(); + + // Initialise some stuff after reading + void initialise(bool is_leader = true); + + // Which device to use? + void deviceInitialise(); + + // Get the output coordinate filename given the micrograph filename + FileName getOutputRootName(FileName fn_mic); + + // Make sure all pieces of code use same psi angles from ipsi + RFLOAT getPsiAngle(int ipsi); + + // grow nonsignal mask + MultidimArray growNonSignalMask(MultidimArray &inmask, int dist); + + // Loop over all psi-angles and coordinates to get accumulated score and angle image for a given micrograph + void getScoreForOneMicrograph(MultidimArray &image, MultidimArray &Mscore, + MultidimArray &Mangle, RFLOAT &skew, RFLOAT &kurt, bool myverb = false); + + // Run on one micrograph + void calculateFOMOneMicrograph(FileName fn_mic, bool myverb = false); + + // Calculate FOM for all micrographs in the indicated batch + void runFOMBatch(long int my_first, long int my_last); + + // Trace filaments for all micrographs in the indicated batch + void runTracingBatch(long int my_first, long int my_last, int my_rank = 0); + + void run(); + + // Write out combined star files, etc + void finalise(); + + +}; + + +#endif //RELION_AMYLOID_FINDER_H diff --git a/src/amyloid_finder_mpi.cpp b/src/amyloid_finder_mpi.cpp new file mode 100644 index 000000000..18bb14a54 --- /dev/null +++ b/src/amyloid_finder_mpi.cpp @@ -0,0 +1,90 @@ +/*************************************************************************** + * + * Author: "Sjors H.W. Scheres" + * MRC Laboratory of Molecular Biology + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This complete copyright notice must be included in any revised version of the + * source code. Additional authorship citations may be added, but existing + * author citations must be preserved. + ***************************************************************************/ + +#include "src/amyloid_finder_mpi.h" + +void AmyloidFinderMpi::read(int argc, char **argv) +{ + // Define a new MpiNode + node = new MpiNode(argc, argv); + + if (node->isLeader()) + PRINT_VERSION_INFO(); + + // First read in non-parallelisation-dependent variables + AmyloidFinder::read(argc, argv); + + // Don't put any output to screen for mpi followers + if (!node->isLeader()) + verb = 0; + + // Possibly also read parallelisation-dependent variables here + + if (do_plot) REPORT_ERROR("ERROR: cannot use --plot in parallel execution!"); + + // Print out MPI info + printMpiNodesMachineNames(*node); +} + +#if defined _CUDA_ENABLED +void AmyloidFinderMpi::deviceInitialise() +{ + int devCount; + accGPUGetDeviceCount(&devCount); + + std::vector < std::vector < std::string > > allThreadIDs; + untangleDeviceIDs(gpu_ids, allThreadIDs); + + // Sequential initialisation of GPUs on all ranks + if (!std::isdigit(*gpu_ids.begin())) + device_id = node->rank%devCount; + else + device_id = textToInteger((allThreadIDs[node->rank][0]).c_str()); + + for (int follower = 0; follower < node->size; follower++) + { + if (follower == node->rank) + { + std::cout << " + Using GPU device: " << device_id << " on MPI node: " << node->rank << std::endl; + std::cout.flush(); + } + node->barrierWait(); + } +} +#endif + +void AmyloidFinderMpi::run() +{ + // Each node does part of the work + if (todo_micrographs_fom.size() > 0) + { + long int my_first_fom, my_last_fom; + divide_equally(todo_micrographs_fom.size(), node->size, node->rank, my_first_fom, my_last_fom); + runFOMBatch(my_first_fom, my_last_fom); + } + + if (todo_micrographs_tracing.size() > 0) + { + long int my_first_tracing, my_last_tracing; + divide_equally(todo_micrographs_tracing.size(), node->size, node->rank, my_first_tracing, my_last_tracing); + runTracingBatch(my_first_tracing, my_last_tracing, node->rank); + } + +} diff --git a/src/amyloid_finder_mpi.h b/src/amyloid_finder_mpi.h new file mode 100644 index 000000000..025a57df3 --- /dev/null +++ b/src/amyloid_finder_mpi.h @@ -0,0 +1,49 @@ +/* + * autopicker_mpi.h + * + * Created on: Sep 18, 2013 + * Author: "Sjors H.W. Scheres" + */ + +#ifndef AMYLOID_FINDER_MPI_H_ +#define AMYLOID_FINDER_MPI_H_ + +#include "src/mpi.h" +#include "src/amyloid_finder.h" +#include "src/parallel.h" + +class AmyloidFinderMpi: public AmyloidFinder +{ +private: + MpiNode *node; + +public: + /** Destructor, calls MPI_Finalize */ + ~AmyloidFinderMpi() + { + delete node; + } + + /** Read + * This could take care of mpi-parallelisation-dependent variables + */ + void read(int argc, char **argv); + + // Set device-affinity + void deviceInitialise(); + + // Parallelized run function + void run(); + + int getRank() + { + return(node->rank); + } + + MpiNode * getNode() + { + return(node); + } +}; + +#endif /* AMYLOID_FINDER_MPI_H_ */ diff --git a/src/apps/CMakeLists.txt b/src/apps/CMakeLists.txt index 24f2c3e75..488aedf6c 100644 --- a/src/apps/CMakeLists.txt +++ b/src/apps/CMakeLists.txt @@ -115,10 +115,6 @@ file(GLOB RELION_JAZ_TOMO_TARGETS "${CMAKE_SOURCE_DIR}/src/jaz/tomography/apps/* file(GLOB RELION_MPI_TARGETS RELATIVE "${CMAKE_SOURCE_DIR}/src/apps" "${CMAKE_SOURCE_DIR}/src/apps/*_mpi.cpp") list(APPEND RELION_MPI_TARGETS "postprocess.cpp;flex_analyse.cpp;autopick.cpp") -if(RELION_TEST) - file(GLOB RELION_JAZ_EXPERIMENTAL_TARGETS "${CMAKE_SOURCE_DIR}/src/jaz/scripts/*.cpp") -endif(RELION_TEST) - set(GUI_TARGETS maingui display manualpick) #--Remove apps using X11 if no GUI-- @@ -223,7 +219,7 @@ endif() # FFTW_LIBRARIES is used even with MKLFFT. # This is empty for ICC. # See https://github.com/3dem/relion/issues/958#issuecomment-1498521352. -target_link_libraries(relion_lib ${FFTW_LIBRARIES}) +target_link_libraries(relion_lib PUBLIC ${FFTW_LIBRARIES}) if(NOT MKLFFT) if(BUILD_OWN_FFTW) add_dependencies(relion_lib own_fftw_lib) @@ -235,20 +231,20 @@ endif(NOT MKLFFT) if(GUI) include_directories("${FLTK_INCLUDE_DIR}") - target_link_libraries(relion_gui_lib relion_lib ${FLTK_LIBRARIES}) + target_link_libraries(relion_gui_lib PUBLIC relion_lib ${FLTK_LIBRARIES}) if(BUILD_OWN_FLTK) add_dependencies(relion_gui_lib OWN_FLTK) endif() endif(GUI) -if (CUDA_FOUND) +if (CUDAToolkit_FOUND) file(GLOB REL_CUDA_SRC "${CMAKE_SOURCE_DIR}/src/acc/cuda/*.cu" "${CMAKE_SOURCE_DIR}/src/acc/cuda/cuda_kernels/*.cu" ) - cuda_add_library(relion_gpu_util ${REL_CUDA_SRC}) + add_library(relion_gpu_util ${REL_CUDA_SRC}) if (${CMAKE_BUILD_TYPE_LOWER} STREQUAL "profiling") - find_library(NV_TOOLS_LIBRARIES NAMES nvToolsExt PATHS ${CUDA_TOOLKIT_ROOT_DIR}/lib ${CUDA_TOOLKIT_ROOT_DIR}/lib64) + find_library(NV_TOOLS_LIBRARIES NAMES nvToolsExt PATHS ${CUDA_TOOLKIT_ROOT_DIR}/lib ${CUDA_TOOLKIT_ROOT_DIR}/lib64) list(APPEND EXTRA_LIBS "${NV_TOOLS_LIBRARIES}") - target_link_libraries(relion_gpu_util ${NV_TOOLS_LIBRARIES}) + target_link_libraries(relion_gpu_util PUBLIC ${NV_TOOLS_LIBRARIES}) message(STATUS "Adding extra library for NVIDIA profiling: ${NV_TOOLS_LIBRARIES}") endif() @@ -264,32 +260,23 @@ if (CUDA_FOUND) set_target_properties(relion_gpu_util PROPERTIES LINK_FLAGS "${new_link_flags}") endif() - list(APPEND EXTRA_LIBS "${CUDA_CUFFT_LIBRARIES}") if(BUILD_SHARED_LIBS) install (TARGETS relion_gpu_util LIBRARY DESTINATION lib) else() - target_link_libraries(relion_gpu_util relion_lib) - target_link_libraries(relion_gpu_util ${CUDA_CUFFT_LIBRARIES}) + target_link_libraries(relion_gpu_util PUBLIC relion_lib) endif() - target_link_libraries(relion_lib relion_gpu_util ${CUDA_CUFFT_LIBRARIES}) - target_link_libraries(relion_lib relion_gpu_util ${CUDA_CUFFT_LIBRARIES} ${CUDA_curand_LIBRARY}) - - - file(GLOB REL_JAZ_CUDA_SRC "${CMAKE_SOURCE_DIR}/src/jaz/cuda/*.cu") - cuda_add_library(relion_jaz_gpu_util ${REL_JAZ_CUDA_SRC}) + add_library(relion_jaz_gpu_util ${REL_JAZ_CUDA_SRC}) - list(APPEND EXTRA_LIBS "${CUDA_CUFFT_LIBRARIES}") if(BUILD_SHARED_LIBS) install (TARGETS relion_jaz_gpu_util LIBRARY DESTINATION lib) else() - target_link_libraries(relion_jaz_gpu_util relion_lib) - target_link_libraries(relion_jaz_gpu_util ${CUDA_CUFFT_LIBRARIES}) + target_link_libraries(relion_jaz_gpu_util PUBLIC relion_lib) endif() - target_link_libraries(relion_lib relion_jaz_gpu_util ${CUDA_CUFFT_LIBRARIES}) - target_link_libraries(relion_lib relion_jaz_gpu_util ${CUDA_CUFFT_LIBRARIES} ${CUDA_curand_LIBRARY}) + target_link_libraries(relion_lib PUBLIC relion_gpu_util relion_jaz_gpu_util) + target_link_libraries(relion_lib PUBLIC CUDA::cudart CUDA::cufft CUDA::curand) elseif (HIP_FOUND) file(GLOB REL_HIP_SRC "${CMAKE_SOURCE_DIR}/src/acc/hip/*.cpp" "${CMAKE_SOURCE_DIR}/src/acc/hip/hip_kernels/*.cpp" ) @@ -298,7 +285,7 @@ elseif (HIP_FOUND) if (${CMAKE_BUILD_TYPE_LOWER} STREQUAL "profiling") find_library(ROCM_TRACER_LIB NAMES roctx64 PATHS ${HIP_ROOT_DIR}/lib ${HIP_ROOT_DIR}/../lib REQUIRED) list(APPEND EXTRA_LIBS "${ROCM_TRACER_LIB}") - target_link_libraries(relion_gpu_util ${ROCM_TRACER_LIB}) + target_link_libraries(relion_gpu_util PUBLIC ${ROCM_TRACER_LIB}) message(STATUS "Adding extra library for AMD profiling: ${ROCM_TRACER_LIB}") endif() @@ -318,28 +305,19 @@ elseif (HIP_FOUND) if(BUILD_SHARED_LIBS) install (TARGETS relion_gpu_util LIBRARY DESTINATION lib) else() - target_link_libraries(relion_gpu_util relion_lib) - target_link_libraries(relion_gpu_util ${HIPFFT_LIBRARIES}) + target_link_libraries(relion_gpu_util PUBLIC relion_lib) endif() - target_link_libraries(relion_lib relion_gpu_util ${HIPFFT_LIBRARIES}) - target_link_libraries(relion_lib relion_gpu_util ${HIPFFT_LIBRARIES} ${HIPRAND_LIBRARIES}) - target_link_libraries(relion_lib relion_gpu_util ${HIPCUB_LIBRARIES}) + target_link_libraries(relion_lib PUBLIC relion_gpu_util ${HIPFFT_LIBRARIES}) + target_link_libraries(relion_lib PUBLIC relion_gpu_util ${HIPFFT_LIBRARIES} ${HIPRAND_LIBRARIES}) + target_link_libraries(relion_lib PUBLIC relion_gpu_util ${HIPCUB_LIBRARIES}) file(GLOB REL_JAZ_HIP_SRC "${CMAKE_SOURCE_DIR}/src/jaz/hip/*.cpp" "${CMAKE_SOURCE_DIR}/src/jaz/hip/kernels/*.cpp" ) hip_add_library(relion_jaz_gpu_util ${REL_JAZ_HIP_SRC}) - #list(APPEND EXTRA_LIBS "${HIPFFT_LIBRARIES}") - #if(BUILD_SHARED_LIBS) - # install (TARGETS relion_jaz_gpu_util LIBRARY DESTINATION lib) - #else() - # target_link_libraries(relion_jaz_gpu_util relion_lib) - # target_link_libraries(relion_jaz_gpu_util ${HIPFFT_LIBRARIES}) - #endif() - - target_link_libraries(relion_lib relion_jaz_gpu_util ${HIPFFT_LIBRARIES}) - target_link_libraries(relion_lib relion_jaz_gpu_util ${HIPFFT_LIBRARIES} ${HIPRAND_LIBRARIES}) - target_link_libraries(relion_lib relion_gpu_util ${HIPCUB_LIBRARIES}) + target_link_libraries(relion_lib PUBLIC relion_jaz_gpu_util ${HIPFFT_LIBRARIES}) + target_link_libraries(relion_lib PUBLIC relion_jaz_gpu_util ${HIPFFT_LIBRARIES} ${HIPRAND_LIBRARIES}) + target_link_libraries(relion_lib PUBLIC relion_gpu_util ${HIPCUB_LIBRARIES}) elseif(SYCL) @@ -387,41 +365,28 @@ elseif(SYCL) set_source_files_properties(${_source} PROPERTIES COMPILE_FLAGS -qno-openmp) endif() endforeach() - target_link_libraries(relion_sycl_util sycl OpenCL relion_lib) + target_link_libraries(relion_sycl_util PUBLIC sycl OpenCL relion_lib) endif() if(TIFF_FOUND) include_directories(${TIFF_INCLUDE_DIRS}) - target_link_libraries(relion_lib ${TIFF_LIBRARIES}) + target_link_libraries(relion_lib PUBLIC ${TIFF_LIBRARIES}) endif() if(PNG_FOUND) include_directories(${PNG_INCLUDE_DIRS}) - target_link_libraries(relion_lib ${PNG_LIBRARY}) -else() - find_library(PNG_LIBRARY NAMES png PATHS /share/modules/libpng/1.6.37/lib/ /usr/local/lib) - if(PNG_LIBRARY) - message("Trying manual search for PNG") - add_definitions(-DHAVE_PNG) - message(STATUS "PNG_LIBRARY: ${PNG_LIBRARY}") - target_link_libraries(relion_lib ${PNG_LIBRARY}) - endif() + target_link_libraries(relion_lib PUBLIC ${PNG_LIBRARY}) endif() if(JPEG_FOUND) include_directories(${JPEG_INCLUDE_DIRS}) - target_link_libraries(relion_lib ${JPEG_LIBRARY}) -else() - find_library(JPEG_LIBRARY NAMES jpeg PATHS /share/modules/libjpeg/62.2.0/lib64/ /usr/local/lib) - if(JPEG_LIBRARY) - message("Trying manual search for JPEG") - add_definitions(-DHAVE_JPEG) - message(STATUS "JPEG_LIBRARY: ${JPEG_LIBRARY}") - target_link_libraries(relion_lib ${JPEG_LIBRARY}) - endif() + target_link_libraries(relion_lib PUBLIC ${JPEG_LIBRARY}) endif() +#get_target_property(RELION_LIB_LINKS relion_lib LINK_LIBRARIES) +#message(STATUS "relion_lib links to: ${RELION_LIB_LINKS}") + if(BUILD_OWN_TBB) add_dependencies(relion_lib OWN_TBB) endif() @@ -437,22 +402,16 @@ foreach (_target ${RELION_TARGETS}) set_target_properties(${_target} PROPERTIES PREFIX "relion_") endif() - set(LIB relion_lib) - add_dependencies(${_target} relion_lib) if(NOT MKLFFT) - target_link_libraries(${_target} ${LIB} ${EXTRA_LIBS} ${MPI_LIBRARIES} ${CMAKE_DL_LIBS}) + target_link_libraries(${_target} PUBLIC relion_lib ${EXTRA_LIBS} ${MPI_LIBRARIES} ${CMAKE_DL_LIBS}) else() - target_link_libraries(${_target} ${LIB} ${FFTW_LIBRARIES} ${EXTRA_LIBS} ${MPI_LIBRARIES} ${CMAKE_DL_LIBS}) + target_link_libraries(${_target} PUBLIC relion_lib ${FFTW_LIBRARIES} ${EXTRA_LIBS} ${MPI_LIBRARIES} ${CMAKE_DL_LIBS}) endif(NOT MKLFFT) - if(CUDA_FOUND OR HIP_FOUND) - target_link_libraries(${_target} relion_gpu_util) - endif() - if(SYCL) - target_link_libraries(${_target} relion_sycl_util sycl OpenCL relion_lib) + target_link_libraries(${_target} PUBLIC relion_sycl_util sycl OpenCL relion_lib) list(FIND SYCL_TARGETS ${_target} IS_SYCL_TARGET) if(NOT ${IS_SYCL_TARGET} LESS 0) if(DEFINED SYCL_CUDA_COMPILE OR DEFINED SYCL_HIP_COMPILE) @@ -470,7 +429,7 @@ foreach (_target ${RELION_TARGETS}) endif(SYCL) if (ALTCPU) - target_link_libraries(${_target} ${TBB_LIBRARIES}) + target_link_libraries(${_target} PUBLIC ${TBB_LIBRARIES}) endif(ALTCPU) set_target_properties(${_target} PROPERTIES @@ -480,87 +439,47 @@ foreach (_target ${RELION_TARGETS}) list(FIND GUI_TARGETS ${_target} IS_GUI_TARGET) if((NOT ${IS_GUI_TARGET} LESS 0) OR (${_target} STREQUAL "relion")) add_dependencies(${_target} relion_gui_lib) - target_link_libraries(${_target} relion_gui_lib ${FLTK_LIBRARIES} ${X11}) + target_link_libraries(${_target} PUBLIC relion_gui_lib ${FLTK_LIBRARIES} ${X11}) endif() - if(TIFF_FOUND) - target_link_libraries(${_target} ${TIFF_LIBRARIES}) - endif() + install(TARGETS ${_target} RUNTIME DESTINATION bin) - list(FIND RELION_MPI_TARGETS ${_target}.cpp IS_MPI_TARGET) - if(NOT ${IS_MPI_TARGET} LESS 0) - target_link_libraries(${_target} ${MPI_LIBRARIES}) - endif() - - install (TARGETS ${_target} RUNTIME DESTINATION bin) + #get_target_property(EXE_LINKS ${_target} LINK_LIBRARIES) + #message(STATUS "${_target} links to: ${EXE_LINKS}") endforeach() foreach (_target ${RELION_JAZ_SPA_TARGETS}) GET_FILENAME_COMPONENT(_target "relion_${_target}" NAME_WE) add_executable(${_target} ${CMAKE_SOURCE_DIR}/src/jaz/single_particle/apps/${_target}.cpp) - set(LIB relion_lib) add_dependencies(${_target} relion_lib) set_target_properties(${_target} PROPERTIES PREFIX "relion_") - target_link_libraries(${_target} ${LIB} ${FFTW_LIBRARIES} ${EXTRA_LIBS} ${MPI_LIBRARIES} ${CMAKE_DL_LIBS}) + target_link_libraries(${_target} PUBLIC relion_lib ${EXTRA_LIBS} ${MPI_LIBRARIES} ${CMAKE_DL_LIBS}) set_target_properties(${_target} PROPERTIES CXX_EXTENSIONS OFF ) - if(TIFF_FOUND) - target_link_libraries(${_target} ${TIFF_LIBRARIES}) - endif() - - if(SYCL) - target_link_libraries(${_target} sycl OpenCL relion_lib) - endif(SYCL) + if(SYCL) + target_link_libraries(${_target} PUBLIC sycl OpenCL relion_lib) + endif(SYCL) if (ALTCPU) - target_link_libraries(${_target} ${TBB_LIBRARIES}) + target_link_libraries(${_target} PUBLIC ${TBB_LIBRARIES}) endif(ALTCPU) - install (TARGETS ${_target} RUNTIME DESTINATION bin) + install(TARGETS ${_target} RUNTIME DESTINATION bin) endforeach() # former Dynamite programs: foreach (_target ${RELION_JAZ_TOMO_TARGETS}) GET_FILENAME_COMPONENT(_target "relion_tomo_${_target}" NAME_WE) add_executable(${_target} ${CMAKE_SOURCE_DIR}/src/jaz/tomography/apps/${_target}.cpp) - set(LIB relion_lib) add_dependencies(${_target} relion_lib) set_target_properties(${_target} PROPERTIES PREFIX "relion_tomo_") - target_link_libraries(${_target} ${LIB} ${FFTW_LIBRARIES} ${EXTRA_LIBS} ${MPI_LIBRARIES} ${CMAKE_DL_LIBS}) + target_link_libraries(${_target} PUBLIC relion_lib ${EXTRA_LIBS} ${MPI_LIBRARIES} ${CMAKE_DL_LIBS}) set_target_properties(${_target} PROPERTIES CXX_EXTENSIONS OFF ) - if(TIFF_FOUND) - target_link_libraries(${_target} ${TIFF_LIBRARIES}) - endif() - - if(SYCL) - target_link_libraries(${_target} sycl OpenCL relion_lib) - endif(SYCL) - - install (TARGETS ${_target} RUNTIME DESTINATION bin) -endforeach() - -foreach (_target ${RELION_JAZ_EXPERIMENTAL_TARGETS}) - GET_FILENAME_COMPONENT(_target "relion_exp_${_target}" NAME_WE) - add_executable(${_target} ${CMAKE_SOURCE_DIR}/src/jaz/scripts/${_target}.cpp) - set(LIB relion_lib) - add_dependencies(${_target} relion_lib) - set_target_properties(${_target} PROPERTIES PREFIX "relion_exp_") - target_link_libraries(${_target} ${LIB} ${FFTW_LIBRARIES} ${EXTRA_LIBS} ${MPI_LIBRARIES} ${CMAKE_DL_LIBS}) - set_target_properties(${_target} PROPERTIES CXX_EXTENSIONS OFF ) - - if(TIFF_FOUND) - target_link_libraries(${_target} ${TIFF_LIBRARIES}) - endif() - - if(SYCL) - target_link_libraries(${_target} sycl OpenCL relion_lib) - endif(SYCL) - - if (ALTCPU) - target_link_libraries(${_target} ${TBB_LIBRARIES}) - endif(ALTCPU) + if(SYCL) + target_link_libraries(${_target} PUBLIC sycl OpenCL relion_lib) + endif(SYCL) install (TARGETS ${_target} RUNTIME DESTINATION bin) endforeach() diff --git a/src/jaz/scripts/spa_backproject.cpp b/src/apps/find_amyloid.cpp similarity index 74% rename from src/jaz/scripts/spa_backproject.cpp rename to src/apps/find_amyloid.cpp index cc62eb30a..72f283e00 100644 --- a/src/jaz/scripts/spa_backproject.cpp +++ b/src/apps/find_amyloid.cpp @@ -1,6 +1,6 @@ /*************************************************************************** * - * Author: "Jasenko Zivanov" + * Author: "Sjors H.W. Scheres" * MRC Laboratory of Molecular Biology * * This program is free software; you can redistribute it and/or modify @@ -17,24 +17,39 @@ * source code. Additional authorship citations may be added, but existing * author citations must be preserved. ***************************************************************************/ - -#include +#include int main(int argc, char *argv[]) { - SpaBackproject program; + AmyloidFinder prm; try { - program.read(argc, argv); - program.run(); + prm.read(argc, argv); + + prm.initialise(); + +#if defined _CUDA_ENABLED + if (prm.do_gpu) prm.deviceInitialise(); +#endif + + prm.run(); + prm.finalise(); + +#ifdef TIMING + std::cout << "timings:" << std::endl; + prm.timer.printTimes(false); +#endif } catch (RelionError XE) { + //prm.usage(); std::cerr << XE; + return RELION_EXIT_FAILURE; } - + return RELION_EXIT_SUCCESS; } + diff --git a/src/apps/find_amyloid_mpi.cpp b/src/apps/find_amyloid_mpi.cpp new file mode 100644 index 000000000..892c7146c --- /dev/null +++ b/src/apps/find_amyloid_mpi.cpp @@ -0,0 +1,55 @@ +/*************************************************************************** + * + * Author: "Sjors H.W. Scheres" + * MRC Laboratory of Molecular Biology + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * This complete copyright notice must be included in any revised version of the + * source code. Additional authorship citations may be added, but existing + * author citations must be preserved. + ***************************************************************************/ +#include + +int main(int argc, char *argv[]) +{ + AmyloidFinderMpi prm; + + try + { + prm.read(argc, argv); + + prm.initialise(prm.getRank()); + +#if defined _CUDA_ENABLED + if (prm.do_gpu) prm.deviceInitialise(); +#endif + + prm.run(); + + MPI_Barrier(MPI_COMM_WORLD); + + prm.finalise(); + + } + + catch (RelionError XE) + { + if (prm.verb > 0) std::cerr << XE; + MPI_Abort(MPI_COMM_WORLD, RELION_EXIT_FAILURE); + + return RELION_EXIT_FAILURE; + } + + MPI_Barrier(MPI_COMM_WORLD); + return RELION_EXIT_SUCCESS; +} + diff --git a/src/apps/image_handler.cpp b/src/apps/image_handler.cpp index 249d50e00..af3d2bed5 100644 --- a/src/apps/image_handler.cpp +++ b/src/apps/image_handler.cpp @@ -36,9 +36,9 @@ class image_handler_parameters { public: FileName fn_in, fn_out, fn_sel, fn_img, fn_sym, fn_sub, fn_mult, fn_div, fn_add, fn_subtract, fn_mask, fn_fsc, fn_adjust_power, fn_correct_ampl, fn_fourfilter, fn_cosDPhi; - int bin_avg, avg_first, avg_last, edge_x0, edge_xF, edge_y0, edge_yF, filter_edge_width, new_box, minr_ampl_corr, my_new_box_size; - bool do_add_edge, do_invert_hand, do_flipXY, do_flipmXY, do_flipZ, do_flipX, do_flipY, do_shiftCOM, do_stats, do_calc_com, do_avg_ampl, do_avg_ampl2, do_avg_ampl2_ali, do_average, do_remove_nan, do_average_all_frames, do_power, do_guinier, do_ignore_optics, do_optimise_scale_subtract, write_float16; - RFLOAT multiply_constant, divide_constant, add_constant, subtract_constant, threshold_above, threshold_below, angpix, requested_angpix, real_angpix, force_header_angpix, lowpass, highpass, logfilter, bfactor, shift_x, shift_y, shift_z, replace_nan, randomize_at, optimise_bfactor_subtract; + int bin_avg, avg_first, avg_last, edge_x0, edge_xF, edge_y0, edge_yF, filter_edge_width, new_box, minr_ampl_corr, my_new_box_size, pix_x, pix_y, pix_z; + bool do_add_edge, do_invert_hand, do_flipXY, do_flipmXY, do_flipZ, do_flipX, do_flipY, do_shiftCOM, do_stats, do_power_image, do_calc_com, do_avg_ampl, do_avg_ampl2, do_avg_ampl2_ali, do_average, do_remove_nan, do_average_all_frames, do_power, do_guinier, do_ignore_optics, do_optimise_scale_subtract, write_float16, do_set_pixel; + RFLOAT multiply_constant, divide_constant, add_constant, subtract_constant, threshold_above, threshold_below, angpix, requested_angpix, real_angpix, force_header_angpix, lowpass, highpass, logfilter, bfactor, shift_x, shift_y, shift_z, replace_nan, randomize_at, optimise_bfactor_subtract, pix_val; // PNG options RFLOAT minval, maxval, sigma_contrast, guinier_fit_minres, guinier_fit_maxres; int color_scheme; // There is a global variable called colour_scheme in displayer.h! @@ -124,7 +124,8 @@ class image_handler_parameters shift_x = textToFloat(parser.getOption("--shift_x", "Shift images this many pixels in the X-direction", "0.")); shift_y = textToFloat(parser.getOption("--shift_y", "Shift images this many pixels in the Y-direction", "0.")); shift_z = textToFloat(parser.getOption("--shift_z", "Shift images this many pixels in the Z-direction", "0.")); - do_avg_ampl = parser.checkOption("--avg_ampl", "Calculate average amplitude spectrum for all images?"); + do_power_image = parser.checkOption("--power_image", "Output image with Fourier squared amplitudes?"); + do_avg_ampl = parser.checkOption("--avg_ampl", "Calculate average amplitude spectrum for all images?"); do_avg_ampl2 = parser.checkOption("--avg_ampl2", "Calculate average amplitude spectrum for all images?"); do_avg_ampl2_ali = parser.checkOption("--avg_ampl2_ali", "Calculate average amplitude spectrum for all aligned images?"); do_average = parser.checkOption("--average", "Calculate average of all images (without alignment)"); @@ -133,8 +134,12 @@ class image_handler_parameters do_remove_nan = parser.checkOption("--remove_nan", "Replace non-numerical values (NaN, inf, etc) in the image(s)"); replace_nan = textToFloat(parser.getOption("--replace_nan", "Replace non-numerical values (NaN, inf, etc) with this value", "0")); randomize_at = textToFloat(parser.getOption("--phase_randomise", "Randomise phases beyond this resolution (in Angstroms)", "-1")); + pix_val = textToFloat(parser.getOption("--pixel_value", "Replace pixel specified below with this value (default is don't replace)", "-999")); + pix_x = textToInteger(parser.getOption("--pixel_x", "Pixel X-coordinate to replace value n absolute coordinates", "-1")); + pix_y = textToInteger(parser.getOption("--pixel_y", "Pixel Y-coordinate to replace value n absolute coordinates", "-1")); + pix_z = textToInteger(parser.getOption("--pixel_z", "Pixel Z-coordinate to replace value n absolute coordinates", "-1")); - int three_d_section = parser.addSection("3D operations"); + int three_d_section = parser.addSection("3D operations"); fn_sym = parser.getOption("--sym", "Symmetrise 3D map with this point group (e.g. D6)", ""); int preprocess_section = parser.addSection("2D-micrograph (or movie) operations"); @@ -431,6 +436,18 @@ class image_handler_parameters } MDpower.write(std::cout); } + else if (do_power_image) + { + MultidimArray< Complex > FT; + FourierTransformer transformer; + transformer.FourierTransform(Iin(), FT); + Iout().resize(ZSIZE(FT), YSIZE(FT), XSIZE(FT)); + FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(FT) + { + DIRECT_MULTIDIM_ELEM(Iout(), n) = NZYXSIZE(Iin())*norm(DIRECT_MULTIDIM_ELEM(FT, n)); + } + DIRECT_MULTIDIM_ELEM(Iout(), 0) = 0.; //remove zero-component + } else if (do_guinier) { @@ -618,6 +635,14 @@ class image_handler_parameters DIRECT_A3D_ELEM(Iout(), k, i, j) = A3D_ELEM(Iin(), k, i, dest_x); } } + else if (fabs(pix_val+999) > 0.1) + { + Iout() = Iin(); + if (ZSIZE(Iout()) < 2) + DIRECT_A2D_ELEM(Iout(), pix_y, pix_x) = pix_val; + else + DIRECT_A3D_ELEM(Iout(), pix_z, pix_y, pix_x) = pix_val; + } // Shifting if (do_shiftCOM) @@ -907,7 +932,7 @@ class image_handler_parameters avg_ampl = Iop(); } - if (fn_mult != "" || fn_div != "" || fn_add != "" || fn_subtract != "" || fn_fsc != "" || fn_adjust_power != "" ||fn_fourfilter != "") + if (fn_mult != "" || fn_div != "" || fn_add != "" || fn_subtract != "" || fn_fsc != "" || fn_adjust_power != "") if (XSIZE(Iop()) != xdim || YSIZE(Iop()) != ydim || ZSIZE(Iop()) != zdim) REPORT_ERROR("Error: operate-image is not of the correct size"); diff --git a/src/apps/import.cpp b/src/apps/import.cpp index 954eab98d..e34d7d45f 100644 --- a/src/apps/import.cpp +++ b/src/apps/import.cpp @@ -30,6 +30,7 @@ class import_parameters bool do_write_types, do_continue, do_movies, do_micrographs, do_coordinates, do_halfmaps, do_particles, do_other; FileName optics_group_name, node_type, particles_optics_group_name; RFLOAT kV, Cs, Q0, beamtilt_x, beamtilt_y, pixel_size; + long int do_at_most; // I/O Parser IOParser parser; @@ -65,6 +66,7 @@ class import_parameters beamtilt_x = textToFloat(parser.getOption("--beamtilt_x", "Beam tilt (X; mrad)", "0.0")); beamtilt_y = textToFloat(parser.getOption("--beamtilt_y", "Beam tilt (Y; mrad)", "0.0")); do_continue = parser.checkOption("--continue", "Continue and old run, add more files to the same import directory"); + do_at_most = textToInteger(parser.getOption("--do_at_most", "Add at most this many new movies or micrographs", "-1")); // Check for errors in the command-line option if (parser.checkForErrors()) @@ -83,7 +85,8 @@ class import_parameters MetaDataTable MDout, MDopt; std::vector fns_in; long nr_input_files = fn_in.globFiles(fns_in); - std::ofstream fh; + long int nr_added = 0; + std::ofstream fh; int nr_count = 0; if (do_movies) nr_count++; @@ -96,6 +99,10 @@ class import_parameters } std::cout << " importing..." << std::endl; + if (do_at_most > 0) + { + std::cout << " - do at most " << do_at_most << " instances" << std::endl; + } // For micrographs or movies if (do_movies || do_micrographs) { @@ -182,11 +189,12 @@ class import_parameters break; } } - if (!already_there) + if (!already_there && !(do_at_most > 0 && nr_added >= do_at_most)) { MDout.addObject(); MDout.setValue(mylabel, fns_in[i]); MDout.setValue(EMDL_IMAGE_OPTICS_GROUP, optics_group_number); + nr_added++; } } diff --git a/src/apps/maingui.cpp b/src/apps/maingui.cpp index 74caacb03..01305425f 100644 --- a/src/apps/maingui.cpp +++ b/src/apps/maingui.cpp @@ -35,27 +35,14 @@ int main(int argc, char *argv[]) #define _MAX_PATH 200 char my_dir[_MAX_PATH]; - char short_dir[49]; + char short_dir[39]; char* res = getcwd(my_dir, _MAX_PATH); - // Get last 45 characters of my_dir to fit in titlebar of window - if (strlen(my_dir) > 45) - { - short_dir[0]=short_dir[1]=short_dir[2]='.'; - int j = 3; - for (int i = strlen(my_dir)-45; i < strlen(my_dir); i++, j++) - { - short_dir[j] = my_dir[i]; - } - short_dir[j] = '\0'; - } - else - { - int i; - for (i = 0; i < strlen(my_dir); i++) - short_dir[i] = my_dir[i]; - short_dir[i] = '\0'; - } + std::string s(res); + unsigned long pos = s.find_last_of('/'); + std::string basename = (pos == std::string::npos) ? s : s.substr(pos + 1); + if (basename.size() > 35) + basename = basename.substr(basename.size() - 35); char titletext[256]; snprintf(titletext, 256, "RELION-%s", g_RELION_VERSION); @@ -64,7 +51,7 @@ int main(int argc, char *argv[]) #endif strcat(titletext,": "); - strcat (titletext, short_dir); + strcat (titletext, basename.c_str()); try { diff --git a/src/apps/particle_symmetry_expand.cpp b/src/apps/particle_symmetry_expand.cpp index ecdea938d..86d8305f4 100644 --- a/src/apps/particle_symmetry_expand.cpp +++ b/src/apps/particle_symmetry_expand.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -29,14 +30,15 @@ class particle_symmetry_expand_parameters { public: - FileName fn_sym, fn_in, fn_out; + FileName fn_sym, fn_localsym, fn_in, fn_out; // Helical symmetry - bool do_helix, do_ignore_optics; + bool do_helix, do_localsym, do_ignore_optics, is_tomo; RFLOAT twist, rise, angpix; int nr_asu, frac_sampling; RFLOAT frac_range; ObservationModel obsModel; + std::vector > locsym_operators; // I/O Parser IOParser parser; @@ -68,6 +70,18 @@ class particle_symmetry_expand_parameters frac_range = textToFloat(parser.getOption("--frac_range", "Range of the rise [-0.5, 0.5> to be sampled", "0.5")); do_ignore_optics = parser.checkOption("--ignore_optics", "Provide this option for relion-3.0 functionality, without optics groups"); + // Local symmetry + int localsym_section = parser.addSection("Local symmetry"); + fn_localsym = parser.getOption("--local_sym", "STAR file with local symmetry operators", ""); + do_localsym = (fn_localsym == "") ? false : true; + + if (do_localsym) + { + if (fn_sym != "C1") + REPORT_ERROR("Provide either --local_sym OR --helix, but not both!"); + + } + // Check for errors in the command-line option if (parser.checkForErrors()) REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); @@ -85,12 +99,29 @@ class particle_symmetry_expand_parameters void run() { MetaDataTable DFi, DFo; - RFLOAT rot, tilt, psi, x, y; - RFLOAT rotp, tiltp, psip, xp, yp; + RFLOAT rot, tilt, psi, x, y, z = 0; + RFLOAT rotp, tiltp, psip, xp, yp, zp = 0; Matrix2D L(3,3), R(3,3); // A matrix from the list RFLOAT z_start, z_stop, z_step; // for helices SymList SL; + if (do_ignore_optics) + { + DFi.read(fn_in); + } + else + { + ObservationModel::loadSafely(fn_in, obsModel, DFi, "particles", 1, false); + if (obsModel.opticsMdt.numberOfObjects() == 0) + { + std::cerr << " + WARNING: could not read optics groups table, proceeding without it ..." << std::endl; + DFi.read(fn_in); + do_ignore_optics = true; + } + } + + bool do_z = DFi.containsLabel(EMDL_ORIENT_ORIGIN_Z_ANGSTROM); + // For helices, pre-calculate expansion range if (do_helix) { @@ -111,6 +142,23 @@ class particle_symmetry_expand_parameters } std::cout << " Helical: z_start= " << z_start << " z_stop= " << z_stop << " z_step= " << z_step << std::endl; } + else if (do_localsym) + { + std::vector fn_mask_list; + std::vector > > op_list; + std::vector > weights; + // set angpix to 1, so translations keep being in Angstroms + readRelionFormatMasksAndOperators(fn_localsym, fn_mask_list, op_list, weights, 1., false); + for (int imask = 0; imask < fn_mask_list.size(); imask++) + { + for (int iop = 0; iop < op_list[imask].size(); iop++) + { + Matrix2D op_mat; + Localsym_operator2matrix(op_list[imask][iop], op_mat, false); + locsym_operators.push_back(op_mat); + } + } + } else { SL.read_sym_file(fn_sym); @@ -118,20 +166,6 @@ class particle_symmetry_expand_parameters REPORT_ERROR("ERROR Nothing to do. Provide a point group with symmetry!"); } - if (do_ignore_optics) - { - DFi.read(fn_in); - } - else - { - ObservationModel::loadSafely(fn_in, obsModel, DFi, "particles", 1, false); - if (obsModel.opticsMdt.numberOfObjects() == 0) - { - std::cerr << " + WARNING: could not read optics groups table, proceeding without it ..." << std::endl; - DFi.read(fn_in); - do_ignore_optics = true; - } - } int barstep = XMIPP_MAX(1, DFi.numberOfObjects()/ 60); init_progress_bar(DFi.numberOfObjects()); @@ -146,13 +180,18 @@ class particle_symmetry_expand_parameters DFi.getValue(EMDL_ORIENT_PSI, psi); DFi.getValue(EMDL_ORIENT_ORIGIN_X_ANGSTROM, x); DFi.getValue(EMDL_ORIENT_ORIGIN_Y_ANGSTROM, y); + if (do_z) DFi.getValue(EMDL_ORIENT_ORIGIN_Z_ANGSTROM, z); if (do_helix) { + if (do_z) + { + // TODO: make this work for 3D coordinates too!!!! + REPORT_ERROR("ERROR: helical symmetry expansion has not yet been implemented for 3D images..."); + } for (RFLOAT z_pos = z_start; z_pos <= z_stop; z_pos += z_step) { - // TMP - //if (fabs(z_pos) > 0.01) + if (fabs(z_pos) > 0.01) { // Translation along the X-axis in the rotated image is along the helical axis in 3D. // Tilted images shift less: sin(tilt) @@ -168,6 +207,55 @@ class particle_symmetry_expand_parameters } } } + else if (do_localsym) + { + // Get the original line from the STAR file + DFo.addObject(); + DFo.setObject(DFi.getObject()); + + // And loop over all symmetry mates + for (int ilocsym = 0; ilocsym < locsym_operators.size(); ilocsym++) + { + DFo.addObject(); + DFo.setObject(DFi.getObject()); + + // Get rotation from euler angles of this particle + Matrix2D euler(3, 3), neweuler(3, 3), my_op(3,3); + Euler_angles2matrix(rot, tilt, psi, euler, false); + my_op = locsym_operators[ilocsym]; + + // get com of local symmetry mask, and rotate it + Matrix1D com(3), newcom(3); + XX(com) = my_op(0,3); + YY(com) = my_op(1,3); + ZZ(com) = my_op(2,3); + newcom = euler * com; + xp = x + XX(newcom); + yp = y + YY(newcom); + zp = z + ZZ(newcom); + DFo.setValue(EMDL_ORIENT_ORIGIN_X_ANGSTROM, xp); + DFo.setValue(EMDL_ORIENT_ORIGIN_Y_ANGSTROM, yp); + if (do_z) DFo.setValue(EMDL_ORIENT_ORIGIN_Z_ANGSTROM, zp); + + // Apply rotation to the Euler angles too + my_op.resize(3,3); + neweuler = euler * my_op.inv(); + Euler_matrix2angles(neweuler, rotp, tiltp, psip); + DFo.setValue(EMDL_ORIENT_ROT, rotp); + DFo.setValue(EMDL_ORIENT_TILT, tiltp); + DFo.setValue(EMDL_ORIENT_PSI, psip); + + if (do_z) + { + // For subtomograms: give each particle a new partname + FileName partname; + DFo.getValue(EMDL_TOMO_PARTICLE_NAME, partname); + partname += "-" + integerToString(ilocsym); + DFo.setValue(EMDL_TOMO_PARTICLE_NAME, partname); + } + } + + } else { // Get the original line from the STAR file diff --git a/src/apps/project.cpp b/src/apps/project.cpp index e18160244..9998a5398 100644 --- a/src/apps/project.cpp +++ b/src/apps/project.cpp @@ -43,7 +43,7 @@ class project_parameters RFLOAT rot, tilt, psi, xoff, yoff, zoff, angpix, maxres, stddev_white_noise, particle_diameter, ana_prob_range, ana_prob_step, sigma_offset; int padding_factor; int r_max, r_min_nn, interpolator, nr_uniform; - bool do_only_one, do_ctf, do_ctf2, ctf_phase_flipped, do_ctf_intact_1st_peak, do_timing, do_add_noise, do_subtract_exp, do_ignore_particle_name, do_3d_rot, write_float16; + bool do_only_one, do_ctf, do_ctf2, ctf_phase_flipped, do_ctf_intact_1st_peak, do_timing, do_add_noise, do_subtract_exp, do_overwrite_exp, do_ignore_particle_name, do_3d_rot, write_float16; bool do_simulate; RFLOAT simulate_SNR; // I/O Parser @@ -81,6 +81,7 @@ class project_parameters stddev_white_noise = textToFloat(parser.getOption("--white_noise", "Standard deviation of added white Gaussian noise", "0")); fn_model = parser.getOption("--model_noise", "Model STAR file with power spectra for coloured Gaussian noise", ""); do_subtract_exp = parser.checkOption("--subtract_exp", "Subtract projections from experimental images (in --ang)"); + do_overwrite_exp = parser.checkOption("--overwrite_exp", "Overwrite experimental images with projections (in --ang)"); do_ignore_particle_name = parser.checkOption("--ignore_particle_name", "Ignore the rlnParticleName column (in --ang)"); do_only_one = (fn_ang == "None" && nr_uniform < 0); do_3d_rot = parser.checkOption("--3d_rot", "Perform 3D rotations instead of projection into 2D images"); @@ -641,19 +642,31 @@ class project_parameters } else { - // Write this particle to the stack on disc - // First particle: write stack in overwrite mode, from then on just append to it - fn_img.compose(imgno+1,fn_out+".mrcs"); - if (imgno == 0) - img.write(fn_img, -1, false, WRITE_OVERWRITE, write_float16 ? Float16: Float); + if (do_overwrite_exp) + { + DataType dt = static_cast(expimg.dataType()); + img.write(fn_expimg, -1, false, WRITE_REPLACE, dt); + } else - img.write(fn_img, -1, false, WRITE_APPEND, write_float16 ? Float16: Float); + { + // Write this particle to the stack on disc + // First particle: write stack in overwrite mode, from then on just append to it + fn_img.compose(imgno+1,fn_out+".mrcs"); + if (imgno == 0) + img.write(fn_img, -1, false, WRITE_OVERWRITE, write_float16 ? Float16: Float); + else + img.write(fn_img, -1, false, WRITE_APPEND, write_float16 ? Float16: Float); + } } // Set the image name to the output STAR file DFo.addObject(); DFo.setObject(MDang.getObject()); - DFo.setValue(EMDL_IMAGE_NAME,fn_img); + + if (do_overwrite_exp) + DFo.setValue(EMDL_IMAGE_NAME, fn_expimg); + else + DFo.setValue(EMDL_IMAGE_NAME, fn_img); if (do_simulate) { diff --git a/src/apps/pseudotomo_expansion.cpp b/src/apps/pseudotomo_expansion.cpp index 2cfa46583..7faaeee76 100644 --- a/src/apps/pseudotomo_expansion.cpp +++ b/src/apps/pseudotomo_expansion.cpp @@ -119,9 +119,9 @@ class pseudotomo_expansion shift3d_x, shift3d_y, shift3d_z, shift2d_x, shift2d_y, shift2d_z ); - md.setValue(EMDL_ORIENT_ORIGIN_X_ANGSTROM, shift3d_x); - md.setValue(EMDL_ORIENT_ORIGIN_Y_ANGSTROM, shift3d_y); - md.setValue(EMDL_ORIENT_ORIGIN_Z_ANGSTROM, shift3d_z); + md.setValue(EMDL_ORIENT_ORIGIN_X_ANGSTROM, shift2d_x); + md.setValue(EMDL_ORIENT_ORIGIN_Y_ANGSTROM, shift2d_y); + md.setValue(EMDL_ORIENT_ORIGIN_Z_ANGSTROM, shift2d_z); } } diff --git a/src/apps/star_handler.cpp b/src/apps/star_handler.cpp index 2a96b9b6c..10c319640 100644 --- a/src/apps/star_handler.cpp +++ b/src/apps/star_handler.cpp @@ -217,9 +217,9 @@ class star_handler_parameters compareMetaDataTable(MD1, MD2, MDboth, MDonly1, MDonly2, label1, eps, label2, label3); - std::cout << MDboth.numberOfObjects() << " entries occur in both input STAR files." << std::endl; - std::cout << MDonly1.numberOfObjects() << " entries occur only in the 1st input STAR file." << std::endl; - std::cout << MDonly2.numberOfObjects() << " entries occur only in the 2nd input STAR file." << std::endl; + std::cout << MDboth.numberOfObjects() << " entries from the 1st input STAR file also have an entry in the 2nd STAR file." << std::endl; + std::cout << MDonly1.numberOfObjects() << " entries from the 1st input STAR file do NOT have an entry in the 2nd STAR file." << std::endl; + std::cout << MDonly2.numberOfObjects() << " entries from the 2nd Sinput STAR file do NOT have an entry in the 1st STAR file." << std::endl; write_check_ignore_optics(MDboth, fn_out.insertBeforeExtension("_both"), MD1.getName()); std::cout << " Written: " << fn_out.insertBeforeExtension("_both") << std::endl; @@ -833,7 +833,8 @@ class star_handler_parameters fnt0 = integerToString(nr_split); for (int isplit = 0; isplit < nr_split; isplit ++) { - FileName fnt = fn_out.insertBeforeExtension("_split"+integerToString(isplit+1)); + FileName fnt; + fnt.compose(fn_out.withoutExtension() + "_split",isplit+1, "star", 5); MDouts[isplit].setName(MD.getName()); write_check_ignore_optics(MDouts[isplit], fnt, MD.getName()); std::cout << " Written: " < Asubtomo; + Euler_angles2matrix( phi, theta, psi, Asubtomo, false); + A3D = Asubtomo * A3D; + } - // Project the center-coordinates - Euler_angles2matrix(rot, tilt, psi, A3D, false); + // Project the recenter-coordinates my_projected_center = A3D * my_center; + xoff /= angpix; + yoff /= angpix; xoff -= XX(my_projected_center); yoff -= YY(my_projected_center); diff --git a/src/autopicker.cpp b/src/autopicker.cpp index 81c7af3fb..f1c2fe467 100644 --- a/src/autopicker.cpp +++ b/src/autopicker.cpp @@ -1083,7 +1083,19 @@ void AutoPicker::generatePDFLogfile() FileName fn_coords = fn_odir + fn_out + ".star"; MDcoords.setName("coordinate_files"); - MDcoords.write(fn_coords); + + MetaDataTable MDhead; + MDhead.setName("general"); + MDhead.setIsList(true); + MDhead.addObject(); + std::string picktype("particles"); + if (autopick_helical_segments) picktype = "startend"; + MDhead.setValue(EMDL_MICROGRAPH_PICKTYPE, picktype); + + std::vector MDins; + MDins.push_back(MDhead); + MDins.push_back(MDcoords); + writeMultipleTablesToStar(MDins, fn_coords); if (verb > 0 ) { diff --git a/src/backprojector.cpp b/src/backprojector.cpp index e76ff72ad..6ba1f8919 100644 --- a/src/backprojector.cpp +++ b/src/backprojector.cpp @@ -1287,6 +1287,9 @@ void BackProjector::externalReconstruct(MultidimArray &vol_out, cmd += " " + blush_args; + // The typical command will look something like this: + // relion_python_blush Refine3D/job024/run_it006_half2_class001_external_reconstruct.star -m v1.0 --gpu 1 + FILE* pipe = popen(cmd.c_str(), "r"); if (!pipe) throw std::runtime_error("Failed to dispatch command: " + cmd); @@ -2140,7 +2143,7 @@ void BackProjector::symmetrise(int nr_helical_asu, RFLOAT helical_twist, RFLOAT enforceHermitianSymmetry(); // Then apply helical and point group symmetry (order irrelevant?) - applyHelicalSymmetry(nr_helical_asu, helical_twist, helical_rise); + applyHelicalSymmetry(nr_helical_asu, helical_twist, helical_rise, threads); applyPointGroupSymmetry(threads); } @@ -2164,7 +2167,7 @@ void BackProjector::enforceHermitianSymmetry() } } -void BackProjector::applyHelicalSymmetry(int nr_helical_asu, RFLOAT helical_twist, RFLOAT helical_rise) +void BackProjector::applyHelicalSymmetry(int nr_helical_asu, RFLOAT helical_twist, RFLOAT helical_rise, int threads) { if ( (nr_helical_asu < 2) || (ref_dim != 3) ) return; @@ -2172,110 +2175,94 @@ void BackProjector::applyHelicalSymmetry(int nr_helical_asu, RFLOAT helical_twis int rmax2 = ROUND(r_max * padding_factor) * ROUND(r_max * padding_factor); Matrix2D R(4, 4); // A matrix from the list - MultidimArray sum_weight; - MultidimArray sum_data; - RFLOAT x, y, z, fx, fy, fz, xp, yp, zp, r2; - bool is_neg_x; - int x0, x1, y0, y1, z0, z1; - Complex d000, d001, d010, d011, d100, d101, d110, d111; - Complex dx00, dx01, dx10, dx11, dxy0, dxy1, ddd; - RFLOAT dd000, dd001, dd010, dd011, dd100, dd101, dd110, dd111; - RFLOAT ddx00, ddx01, ddx10, ddx11, ddxy0, ddxy1; + MultidimArray sum_weight(weight); + MultidimArray sum_data(data); // First symmetry operator (not stored in SL) is the identity matrix - sum_weight = weight; - sum_data = data; int h_min = -nr_helical_asu/2; int h_max = -h_min + nr_helical_asu%2; for (int hh = h_min; hh < h_max; hh++) { - if (hh != 0) // h==0 is done before the for loop (where sum_data = data) + if (hh == 0) continue; // h==0 is done before the for loop (where sum_data = data) + + RFLOAT rot_ang = hh * (-helical_twist); + rotation3DMatrix(rot_ang, 'Z', R); + R.setSmallValuesToZero(); // TODO: invert rotation matrix? + + //Only the positive half of the z-range has to be calculated. + //The other half is calculated by the x<0 part of the x-loop. + #pragma omp parallel for schedule(dynamic) num_threads(threads) default(none) shared(data,weight,sum_data,sum_weight,rmax2,helical_twist,helical_rise,ori_size,padding_factor) firstprivate(hh,R) + for (long int k=STARTINGZ(sum_weight); k<=FINISHINGZ(sum_weight); k++) { - RFLOAT rot_ang = hh * (-helical_twist); - rotation3DMatrix(rot_ang, 'Z', R); - R.setSmallValuesToZero(); // TODO: invert rotation matrix? + // Allocate minimal 2D slices per thread instead of full 3D arrays + MultidimArray slice_weight(YSIZE(data), XSIZE(data)); + MultidimArray slice_data(YSIZE(data), XSIZE(data)); + slice_weight.xdim = sum_weight.xdim; + slice_weight.ydim = sum_weight.ydim; + slice_weight.yxdim = sum_weight.yxdim; + slice_weight.xinit = sum_weight.xinit; + slice_weight.yinit = sum_weight.yinit; + slice_data.xdim = sum_data.xdim; + slice_data.ydim = sum_data.ydim; + slice_data.yxdim = sum_data.yxdim; + slice_data.xinit = sum_data.xinit; + slice_data.yinit = sum_data.yinit; + + slice_weight.initZeros(weight.ydim,weight.xdim); + slice_data.initZeros(data.ydim,data.xdim); - // Loop over all points in the output (i.e. rotated, or summed) array - FOR_ALL_ELEMENTS_IN_ARRAY3D(sum_weight) + for (long int i=STARTINGY(sum_weight); i<=FINISHINGY(sum_weight); i++) + for (long int j=STARTINGX(sum_weight); j<=FINISHINGX(sum_weight); j++) { - x = (RFLOAT)j; // STARTINGX(sum_weight) is zero! - y = (RFLOAT)i; - z = (RFLOAT)k; - r2 = x*x + y*y + z*z; + RFLOAT x = (RFLOAT)j; // STARTINGX(sum_weight) is zero! + RFLOAT y = (RFLOAT)i; + RFLOAT z = (RFLOAT)k; + RFLOAT r2 = x*x + y*y + z*z; + if (r2 <= rmax2) { // coords_output(x,y) = A * coords_input (xp,yp) - xp = x * R(0, 0) + y * R(0, 1) + z * R(0, 2); - yp = x * R(1, 0) + y * R(1, 1) + z * R(1, 2); - zp = x * R(2, 0) + y * R(2, 1) + z * R(2, 2); + RFLOAT xp = x * R(0, 0) + y * R(0, 1); + RFLOAT yp = x * R(1, 0) + y * R(1, 1); + RFLOAT zp = z; // Z remains unchanged // Only asymmetric half is stored - if (xp < 0) + bool is_neg_x = xp < 0; + if (is_neg_x) { - // Get complex conjugated hermitian symmetry pair xp = -xp; yp = -yp; zp = -zp; - is_neg_x = true; - } - else - { - is_neg_x = false; } // Trilinear interpolation (with physical coords) // Subtract STARTINGY and STARTINGZ to accelerate access to data (STARTINGX=0) // In that way use DIRECT_A3D_ELEM, rather than A3D_ELEM - x0 = FLOOR(xp); - fx = xp - x0; - x1 = x0 + 1; + int x0 = FLOOR(xp); + RFLOAT fx = xp - x0; + int x1 = x0 + 1; - y0 = FLOOR(yp); - fy = yp - y0; - y0 -= STARTINGY(data); - y1 = y0 + 1; + int y0 = FLOOR(yp); + RFLOAT fy = yp - y0; + y0 -= STARTINGY(data); + int y1 = y0 + 1; - z0 = FLOOR(zp); - fz = zp - z0; + int z0 = FLOOR(zp); z0 -= STARTINGZ(data); - z1 = z0 + 1; -#ifdef CHECK_SIZE - if (x0 < 0 || y0 < 0 || z0 < 0 || - x1 < 0 || y1 < 0 || z1 < 0 || - x0 >= XSIZE(data) || y0 >= YSIZE(data) || z0 >= ZSIZE(data) || - x1 >= XSIZE(data) || y1 >= YSIZE(data) || z1 >= ZSIZE(data) ) - { - std::cerr << " x0= " << x0 << " y0= " << y0 << " z0= " << z0 << std::endl; - std::cerr << " x1= " << x1 << " y1= " << y1 << " z1= " << z1 << std::endl; - data.printShape(); - REPORT_ERROR("BackProjector::applyPointGroupSymmetry: checksize!!!"); - } -#endif // First interpolate (complex) data - d000 = DIRECT_A3D_ELEM(data, z0, y0, x0); - d001 = DIRECT_A3D_ELEM(data, z0, y0, x1); - d010 = DIRECT_A3D_ELEM(data, z0, y1, x0); - d011 = DIRECT_A3D_ELEM(data, z0, y1, x1); - d100 = DIRECT_A3D_ELEM(data, z1, y0, x0); - d101 = DIRECT_A3D_ELEM(data, z1, y0, x1); - d110 = DIRECT_A3D_ELEM(data, z1, y1, x0); - d111 = DIRECT_A3D_ELEM(data, z1, y1, x1); - - dx00 = LIN_INTERP(fx, d000, d001); - dx01 = LIN_INTERP(fx, d100, d101); - dx10 = LIN_INTERP(fx, d010, d011); - dx11 = LIN_INTERP(fx, d110, d111); - dxy0 = LIN_INTERP(fy, dx00, dx10); - dxy1 = LIN_INTERP(fy, dx01, dx11); + Complex d00 = DIRECT_A3D_ELEM(data, z0, y0, x0); + Complex d01 = DIRECT_A3D_ELEM(data, z0, y0, x1); + Complex d10 = DIRECT_A3D_ELEM(data, z0, y1, x0); + Complex d11 = DIRECT_A3D_ELEM(data, z0, y1, x1); + Complex dx00 = LIN_INTERP(fx ,d00, d01); + Complex dx10 = LIN_INTERP(fx ,d10, d11); // Take complex conjugated for half with negative x - ddd = LIN_INTERP(fz, dxy0, dxy1); + Complex ddd = LIN_INTERP(fy, dx00, dx10); - if (is_neg_x) - ddd = conj(ddd); + if (is_neg_x) ddd = conj(ddd); - // Also apply a phase shift for helical translation along Z if (ABS(helical_rise) > 0.) { RFLOAT zshift = hh * helical_rise; @@ -2291,31 +2278,37 @@ void BackProjector::applyHelicalSymmetry(int nr_helical_asu, RFLOAT helical_twis ddd = Complex(ac - bd, ab_cd - ac - bd); } // Accumulated sum of the data term - A3D_ELEM(sum_data, k, i, j) += ddd; + A2D_ELEM(slice_data,i,j) += ddd; // Then interpolate (real) weight - dd000 = DIRECT_A3D_ELEM(weight, z0, y0, x0); - dd001 = DIRECT_A3D_ELEM(weight, z0, y0, x1); - dd010 = DIRECT_A3D_ELEM(weight, z0, y1, x0); - dd011 = DIRECT_A3D_ELEM(weight, z0, y1, x1); - dd100 = DIRECT_A3D_ELEM(weight, z1, y0, x0); - dd101 = DIRECT_A3D_ELEM(weight, z1, y0, x1); - dd110 = DIRECT_A3D_ELEM(weight, z1, y1, x0); - dd111 = DIRECT_A3D_ELEM(weight, z1, y1, x1); - - ddx00 = LIN_INTERP(fx, dd000, dd001); - ddx01 = LIN_INTERP(fx, dd100, dd101); - ddx10 = LIN_INTERP(fx, dd010, dd011); - ddx11 = LIN_INTERP(fx, dd110, dd111); - ddxy0 = LIN_INTERP(fy, ddx00, ddx10); - ddxy1 = LIN_INTERP(fy, ddx01, ddx11); - - A3D_ELEM(sum_weight, k, i, j) += LIN_INTERP(fz, ddxy0, ddxy1); - - } // end if r2 <= rmax2 - } // end loop over all elements of sum_weight - } // end if hh!=0 - } // end loop over hh + RFLOAT dd00 = DIRECT_A3D_ELEM(weight, z0, y0, x0); + RFLOAT dd01 = DIRECT_A3D_ELEM(weight, z0, y0, x1); + RFLOAT dd10 = DIRECT_A3D_ELEM(weight, z0, y1, x0); + RFLOAT dd11 = DIRECT_A3D_ELEM(weight, z0, y1, x1); + RFLOAT ddx00 = LIN_INTERP(fx, dd00, dd01); + RFLOAT ddx10 = LIN_INTERP(fx, dd10, dd11); + + A2D_ELEM(slice_weight,i,j) += LIN_INTERP(fy, ddx00, ddx10); + } + } + #pragma omp critical + { + for (long int i=STARTINGY(sum_weight); i<=FINISHINGY(sum_weight); i++) + for (long int j=STARTINGX(sum_weight); j<=FINISHINGX(sum_weight); j++) + { + RFLOAT x = (RFLOAT)j; // STARTINGX(sum_weight) is zero! + RFLOAT y = (RFLOAT)i; + RFLOAT z = (RFLOAT)k; + RFLOAT r2 = x*x + y*y + z*z; + if (r2 <= rmax2) + { + A3D_ELEM(sum_data,k,i,j) += A2D_ELEM(slice_data,i,j); + A3D_ELEM(sum_weight,k,i,j) += A2D_ELEM(slice_weight,i,j); + } + } + } + } + } data = sum_data; weight = sum_weight; diff --git a/src/backprojector.h b/src/backprojector.h index 2933274f6..48b6d97f4 100644 --- a/src/backprojector.h +++ b/src/backprojector.h @@ -372,7 +372,7 @@ class BackProjector: public Projector /* Applies helical symmetry. Note that helical_rise is in PIXELS here, as BackProjector doesn't know angpix */ - void applyHelicalSymmetry(int nr_helical_asu = 1, RFLOAT helical_twist = 0., RFLOAT helical_rise = 0.); + void applyHelicalSymmetry(int nr_helical_asu = 1, RFLOAT helical_twist = 0., RFLOAT helical_rise = 0., int threads = 1); /* Applies the symmetry from the SymList object to the weight and the data array */ diff --git a/src/ctffind_runner.cpp b/src/ctffind_runner.cpp index 9dd4d63a2..7a77fc7ba 100644 --- a/src/ctffind_runner.cpp +++ b/src/ctffind_runner.cpp @@ -66,6 +66,9 @@ void CtffindRunner::read(int argc, char **argv, int rank) int ctffind4_section = parser.addSection("CTFFIND4 parameters"); is_ctffind4 = parser.checkOption("--is_ctffind4", "The provided CTFFIND executable is CTFFIND4 (version 4.1+)"); use_given_ps = parser.checkOption("--use_given_ps", "Use pre-calculated power spectra?"); + ice_min = textToFloat(parser.getOption("--ice_min", "Minimum frequency for ice ring density (in 1/A)", "0.25")); + ice_max = textToFloat(parser.getOption("--ice_max", "Maximum frequency for ice ring density (in 1/A)", "0.28")); + do_extra_ice = parser.checkOption("--extra_ice_stats", "When using pre-calculated power spectra, one can calculate extra ice statistics, which may be useful for selection of icy data sets"); do_movie_thon_rings = parser.checkOption("--do_movie_thon_rings", "Calculate Thon rings from movie frames?"); avg_movie_frames = textToInteger(parser.getOption("--avg_movie_frames", "Average over how many movie frames (try to get 4 e-/A2)", "1")); movie_rootname = parser.getOption("--movie_rootname", "Rootname plus extension for movies", "_movie.mrcs"); @@ -75,7 +78,7 @@ void CtffindRunner::read(int argc, char **argv, int rank) phase_step = textToFloat(parser.getOption("--phase_step", "Step in phase shift (in degrees)", "10.")); nr_threads = textToInteger(parser.getOption("--j", "Number of threads (for CTFIND4 only)", "1")); do_fast_search = parser.checkOption("--fast_search", "Disable \"Slower, more exhaustive search\" in CTFFIND4.1 (faster but less accurate)"); - + do_tilt_search = parser.checkOption("--tilt_search", "Run CTFFIND-4.1.15+ tilt search algorithm"); // Initialise verb for non-parallel execution verb = 1; @@ -116,6 +119,9 @@ void CtffindRunner::initialise(bool is_leader) if (use_given_ps) do_use_without_doseweighting = false; + if (do_extra_ice && !use_given_ps) + REPORT_ERROR("ERROR: You cannot use --extra_ice_stats without also using --use_given_ps"); + // Make sure fn_out ends with a slash if (fn_out[fn_out.length()-1] != '/') fn_out += "/"; @@ -268,9 +274,9 @@ void CtffindRunner::initialise(bool is_leader) if (continue_old) { FileName fn_microot = fn_mic_ctf_given_all[imic].withoutExtension(); - RFLOAT defU, defV, defAng, CC, HT, CS, AmpCnst, XMAG, DStep, maxres=-1., valscore = -1., phaseshift = 0., icering = 0.; + RFLOAT defU, defV, defAng, CC, HT, CS, AmpCnst, XMAG, DStep, maxres=-1., valscore = -1., phaseshift = 0., icering = 0., icepowfrac = 0., icekurtosis = 0.; if (getCtffindResults(fn_microot, defU, defV, defAng, CC, - HT, CS, AmpCnst, XMAG, DStep, maxres, valscore, phaseshift, icering, false)) // false: dont warn if not found Final values + HT, CS, AmpCnst, XMAG, DStep, maxres, valscore, phaseshift, icering, icepowfrac, icekurtosis, false)) // false: dont warn if not found Final values { process_this = false; // already done } @@ -418,9 +424,10 @@ void CtffindRunner::joinCtffindResults() { FileName fn_microot = fn_micrographs_ctf_all[imic].withoutExtension(); RFLOAT defU, defV, defAng, CC, HT, CS, AmpCnst, XMAG, DStep; - RFLOAT maxres = -999., valscore = -999., phaseshift = -999., icering = 0.; + RFLOAT maxres = -999., valscore = -999., phaseshift = -999., icering = 0., icepowerfrac = 0., icekurtosis = 0.; bool has_this_ctf = getCtffindResults(fn_microot, defU, defV, defAng, CC, - HT, CS, AmpCnst, XMAG, DStep, maxres, valscore, phaseshift, icering); + HT, CS, AmpCnst, XMAG, DStep, maxres, valscore, phaseshift, + icering, icepowerfrac, icekurtosis); if (!has_this_ctf) { @@ -453,8 +460,12 @@ void CtffindRunner::joinCtffindResults() if (fabs(valscore + 999.) > 0.) MDctf.setValue(EMDL_CTF_VALIDATIONSCORE, valscore); - if (icering > 0.) - MDctf.setValue(EMDL_CTF_ICERINGDENSITY, icering); + MDctf.setValue(EMDL_CTF_ICERINGDENSITY, icering); + if (use_given_ps && do_extra_ice) + { + MDctf.setValue(EMDL_CTF_ICERINGPOWERFRACTION, icepowerfrac); + MDctf.setValue(EMDL_CTF_ICERINGKURTOSIS, icekurtosis); + } if (is_tomo) { @@ -515,6 +526,11 @@ void CtffindRunner::joinCtffindResults() plot_labels.push_back(EMDL_CTF_FOM); plot_labels.push_back(EMDL_CTF_VALIDATIONSCORE); plot_labels.push_back(EMDL_CTF_ICERINGDENSITY); + if (use_given_ps) + { + plot_labels.push_back(EMDL_CTF_ICERINGPOWERFRACTION); + plot_labels.push_back(EMDL_CTF_ICERINGKURTOSIS); + } FileName fn_eps, fn_eps_root = fn_out+"micrographs_ctf"; std::vector all_fn_eps; for (int i = 0; i < plot_labels.size(); i++) @@ -535,7 +551,8 @@ void CtffindRunner::joinCtffindResults() // Histogram std::vector histX, histY; CPlot2D *plot2D=new CPlot2D(""); - MDctf.columnHistogram(label,histX,histY,0, plot2D); + if (label == EMDL_CTF_ICERINGKURTOSIS) MDctf.columnHistogram(label,histX,histY,0, plot2D, -1, -1, 6); + else MDctf.columnHistogram(label,histX,histY,0, plot2D); fn_eps = fn_eps_root + "_hist_" + EMDL::label2Str(label) + ".eps"; plot2D->OutputPostScriptPlot(fn_eps); all_fn_eps.push_back(fn_eps); @@ -767,8 +784,11 @@ void CtffindRunner::executeCtffind4(long int imic) } else fh << "no" << std::endl; - // Set determine sample tilt? (as of ctffind-4.1.15) - fh << "no" << std::endl; + // Set determine sample tilt? (as of ctffind-4.1.15) + if (do_tilt_search) + fh << "yes" << std::endl; + else + fh << "no" << std::endl; // Set expert options? fh << "no" << std::endl; @@ -791,16 +811,16 @@ void CtffindRunner::executeCtffind4(long int imic) bool CtffindRunner::getCtffindResults(FileName fn_microot, RFLOAT &defU, RFLOAT &defV, RFLOAT &defAng, RFLOAT &CC, RFLOAT &HT, RFLOAT &CS, RFLOAT &AmpCnst, RFLOAT &XMAG, RFLOAT &DStep, - RFLOAT &maxres, RFLOAT &valscore, RFLOAT &phaseshift, RFLOAT &icering, bool do_warn) + RFLOAT &maxres, RFLOAT &valscore, RFLOAT &phaseshift, RFLOAT &icering, RFLOAT &icepowerfrac, RFLOAT &icekurtosis, bool do_warn) { if (is_ctffind4) { return getCtffind4Results(fn_microot, defU, defV, defAng, CC, HT, CS, AmpCnst, XMAG, DStep, - maxres, phaseshift, icering, do_warn); + maxres, phaseshift, icering, icepowerfrac, icekurtosis, do_warn); } else { - icering = 0.; + icering = icepowerfrac = icekurtosis = 0.; return getCtffind3Results(fn_microot, defU, defV, defAng, CC, HT, CS, AmpCnst, XMAG, DStep, maxres, phaseshift, valscore, do_warn); } @@ -883,7 +903,7 @@ bool CtffindRunner::getCtffind3Results(FileName fn_microot, RFLOAT &defU, RFLOAT bool CtffindRunner::getCtffind4Results(FileName fn_microot, RFLOAT &defU, RFLOAT &defV, RFLOAT &defAng, RFLOAT &CC, RFLOAT &HT, RFLOAT &CS, RFLOAT &AmpCnst, RFLOAT &XMAG, RFLOAT &DStep, - RFLOAT &maxres, RFLOAT &phaseshift, RFLOAT &icering, bool do_warn) + RFLOAT &maxres, RFLOAT &phaseshift, RFLOAT &icering, RFLOAT &icepowerfrac, RFLOAT &icekurtosis, bool do_warn) { FileName fn_root = getOutputFileWithNewUniqueDate(fn_microot, fn_out); FileName fn_log = fn_root + "_ctffind4.log"; @@ -968,10 +988,11 @@ bool CtffindRunner::getCtffind4Results(FileName fn_microot, RFLOAT &defU, RFLOAT in2.close(); - // Also try and get rlnIceRingDensity, as suggested by Rafael Leiro from the CNIO in Madrid + + // Get rlnIceRingDensity, as suggested by Rafael Leiro from the CNIO in Madrid FileName fn_avrot = fn_root + "_avrot.txt"; std::ifstream av(fn_avrot.data(), std::ios_base::in); - icering = 0.; + icering = 0.; if (!av.fail()) { std::string s1, s2; @@ -985,12 +1006,12 @@ bool CtffindRunner::getCtffind4Results(FileName fn_microot, RFLOAT &defU, RFLOAT int imin = -999; int imax = -999; for (int i = 0; i < words.size(); i++) - if (imin < 0 && textToFloat(words[i]) >= 0.25) { + if (imin < 0 && textToFloat(words[i]) >= ice_min) { imin = i; break; } for (int i = imin; i < words.size(); i++) - if (imax < 0 && imin > 0 && textToFloat(words[i]) > 0.28) { + if (imax < 0 && imin > 0 && textToFloat(words[i]) > ice_max) { imax = i; break; } @@ -1002,5 +1023,70 @@ bool CtffindRunner::getCtffind4Results(FileName fn_microot, RFLOAT &defU, RFLOAT } } + + // Be careful, because avgrot files from CTFFIND-4.1 are somehow normalized badly, so re-read power spectrum image + // This only works if given the power spectrum from RELION's motioncorr. Otherwise, fall back on Rafa's approach below + if (use_given_ps && do_extra_ice) + { + // Use standard deviation in the diagnostics image for ice ring density instead of Rafa's. + // Calculate stddev of power, relative to stddev of power in a band with lower resolution than ice ring + // Richard suggested using a higher band as well, but some strange ice artefacts extend well into the higher band... + Image Ips; + FileName fn_ps = fn_root + ".mrc"; + Ips.read(fn_ps); + Ips().setXmippOrigin(); + RFLOAT mysize = angpix*XSIZE(Ips()); + RFLOAT r2ice_min=4*mysize*mysize/(3.9*3.9); + RFLOAT r2ice_max=4*mysize*mysize/(3.5*3.5); + RFLOAT r2low_min=4*mysize*mysize/(4.5*4.5); + RFLOAT r2low_max=4*mysize*mysize/(4.0*4.0); + RFLOAT r2high_min=4*mysize*mysize/(3.4*3.4); + RFLOAT r2high_max=4*mysize*mysize/(3.0*3.0); + RFLOAT n=0., mean=0., pow_ice=0., pow_band=0., n_band= 0., M2=0., M3=0., M4=0.; + for (long int i=0; i<=FINISHINGY(Ips()); i++) // Use only bottom half of the diagnostic image, as top contains model and averaged spectra!! + for (long int j=STARTINGX(Ips()); j<=FINISHINGX(Ips()); j++) + { + RFLOAT r2 = RFLOAT(i*i + j*j); + if (r2 > r2ice_min && r2 < r2ice_max) + { + n += 1.; + mean += A2D_ELEM(Ips(), i, j); + } + else if (r2 > r2low_min && r2 < r2low_max || r2 > r2high_min && r2 < r2high_max) + { + n_band += 1.; + pow_band += A2D_ELEM(Ips(), i, j); + } + } + mean /= n; + pow_band /= n_band; + if (pow_band > 0.) icepowerfrac = (mean - pow_band) / pow_band; + else icepowerfrac = 0.; + + for (long int i=0; i<=FINISHINGY(Ips()); i++) // Use only bottom half of the diagnostic image, as top contains model and averaged spectra!! + for (long int j=STARTINGX(Ips()); j<=FINISHINGX(Ips()); j++) + { + RFLOAT r2 = RFLOAT(i*i + j*j); + if (r2 > r2ice_min && r2 < r2ice_max) + { + RFLOAT delta = A2D_ELEM(Ips(), i, j) - mean; + M2 += delta*delta; + //M3 += delta*delta*delta; + M4 += delta*delta*delta*delta; + } + } + + RFLOAT s2 = M2 / (n - 1); + RFLOAT s = sqrt(s2); + //RFLOAT skewness = (s > 0.) ? (n / ((n - 1) * (n - 2))) * (M3 / (s * s * s)) : 0.; + icekurtosis = (n * (n + 1) * M4) / ((n - 1) * (n - 2) * (n - 3) * (s2 * s2)) - (3 * (n - 1) * (n - 1)) / ((n - 2) * (n - 3)); + + } + else + { + icepowerfrac = 0.; + icekurtosis =0.; + } + return Final_is_found; } diff --git a/src/ctffind_runner.h b/src/ctffind_runner.h index 4c8e34b52..69c0d6bce 100644 --- a/src/ctffind_runner.h +++ b/src/ctffind_runner.h @@ -88,6 +88,9 @@ class CtffindRunner // Use pre-calculated power spectra bool use_given_ps; + // Calculate extra ice statistics when using pre-calculated power spectra + bool do_extra_ice; + // Calculate Thon rings from movies? bool do_movie_thon_rings; @@ -136,6 +139,9 @@ class CtffindRunner RFLOAT angpix; + // Resolution band for Rafa's ice ring statistics + RFLOAT ice_min, ice_max; + // Flag to only join results into a star file bool do_only_join_results; @@ -148,6 +154,9 @@ class CtffindRunner // Disable "Slower, more exhaustive search?" in CTFFIND 4.1.5- bool do_fast_search; + // As of CTFFINF-4.1.15 one can search for the tilt angle and axis too. This will be written to the logfile, but for now relion doesn't do anything with it. + bool do_tilt_search; + // Which GPU devices to use? std::string gpu_ids; std::vector < std::vector < std::string > > allThreadIDs; @@ -180,13 +189,13 @@ class CtffindRunner // Get micrograph metadata bool getCtffindResults(FileName fn_mic, RFLOAT &defU, RFLOAT &defV, RFLOAT &defAng, RFLOAT &CC, RFLOAT &HT, RFLOAT &CS, RFLOAT &AmpCnst, RFLOAT &XMAG, RFLOAT &DStep, - RFLOAT &maxres, RFLOAT &valscore, RFLOAT &phaseshift, RFLOAT &icering, bool do_warn = true); + RFLOAT &maxres, RFLOAT &valscore, RFLOAT &phaseshift, RFLOAT &icering, RFLOAT &icepowerfrac, RFLOAT &icekurtosis, bool do_warn = true); bool getCtffind3Results(FileName fn_mic, RFLOAT &defU, RFLOAT &defV, RFLOAT &defAng, RFLOAT &CC, RFLOAT &HT, RFLOAT &CS, RFLOAT &AmpCnst, RFLOAT &XMAG, RFLOAT &DStep, RFLOAT &maxres, RFLOAT &phaseshift, RFLOAT &valscore, bool do_warn = true); bool getCtffind4Results(FileName fn_mic, RFLOAT &defU, RFLOAT &defV, RFLOAT &defAng, RFLOAT &CC, RFLOAT &HT, RFLOAT &CS, RFLOAT &AmpCnst, RFLOAT &XMAG, RFLOAT &DStep, - RFLOAT &maxres, RFLOAT &phaseshift, RFLOAT &icering, bool do_warn = true); + RFLOAT &maxres, RFLOAT &phaseshift, RFLOAT &icering, RFLOAT &icepowerfrac, RFLOAT &icekurtosis, bool do_warn = true); }; diff --git a/src/displayer.cpp b/src/displayer.cpp index abfdcf098..16ade2368 100644 --- a/src/displayer.cpp +++ b/src/displayer.cpp @@ -41,7 +41,7 @@ const int NUM_COLORS = 6; /************************************************************************/ void DisplayBox::draw() { - if (!img_data) return; + if (!img_data) return; short xpos = x() + xoff; short ypos = y() + yoff; @@ -50,8 +50,18 @@ void DisplayBox::draw() //fl_push_clip(x(),y(),w(),h()); /* Redraw the whole image */ - int depth = (colour_scheme) ? 3 : 1; - fl_draw_image((const uchar *)img_data, xpos, ypos, (short)xsize_data, (short)ysize_data, depth); + int depth; + if (fom_is_grey_instead) + { + // Even though we colour the FOM image red/yellow, we can toggle to an only-grey micrograph! + depth = 1; + fl_draw_image((const uchar *)img_data2, xpos, ypos, (short)xsize_data, (short)ysize_data, depth); + } + else + { + depth = (colour_scheme) ? 3 : 1; + fl_draw_image((const uchar *)img_data, xpos, ypos, (short)xsize_data, (short)ysize_data, depth); + } if (img_label != "") { fl_color(FL_WHITE); @@ -149,8 +159,9 @@ void DisplayBox::setData(MultidimArray &img, MetaDataContainer *MDCin, i maxval = _maxval; ipos = _ipos; selected = NOTSELECTED; + fom_is_grey_instead = false; - // Set its own MetaDataTable + // Set its own MetaDataTable MDimg.setIsList(true); MDimg.addObject(MDCin); @@ -267,6 +278,240 @@ void DisplayBox::setData(MultidimArray &img, MetaDataContainer *MDCin, i } } +void DisplayBox::setData(MultidimArray &img, MultidimArray &fom_img, MetaDataContainer *MDCin, int _ipos, + RFLOAT _minval, RFLOAT _maxval, RFLOAT _fom_min, RFLOAT _fom_max, RFLOAT _scale, bool do_relion_scale) +{ + scale = _scale; + minval = _minval; + maxval = _maxval; + ipos = _ipos; + selected = NOTSELECTED; + fom_is_grey_instead = false; + + if (fabs(_fom_min) < 0.001 && fabs(_fom_max) < 0.001 ) + { + RFLOAT fom_min=9999., fom_max=-9999.; + FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(fom_img) + { + RFLOAT aux = DIRECT_MULTIDIM_ELEM(fom_img, n); + if (aux > fom_max) fom_max = aux; + if (aux < fom_min) fom_min = aux; + } + _fom_min= fom_min; + _fom_max = fom_max; + } + // Cap high and low values of FOM + FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(fom_img) + { + RFLOAT aux = DIRECT_MULTIDIM_ELEM(fom_img, n); + if (aux > _fom_max) DIRECT_MULTIDIM_ELEM(fom_img, n) = _fom_max; + if (aux < _fom_min) DIRECT_MULTIDIM_ELEM(fom_img, n) = _fom_min; + } + + + RFLOAT fom_range = _fom_max - _fom_min; + RFLOAT fom_step = fom_range / 255; + // Set its own MetaDataTable + MDimg.setIsList(true); + MDimg.addObject(MDCin); + + // For volumes only show the central slice + if (ZSIZE(img) > 1) + { + MultidimArray slice; + img.getSlice(ZSIZE(img)/2, slice); + img=slice; + } + + // create array for the scaled image data + xsize_data = CEIL(XSIZE(img) * scale); + ysize_data = CEIL(YSIZE(img) * scale); + xoff = (xsize_data < w() ) ? (w() - xsize_data) / 2 : 0; + yoff = (ysize_data < h() ) ? (h() - ysize_data) / 2 : 0; + img_data = new unsigned char [3 * xsize_data * ysize_data]; + img_data2 = new unsigned char [xsize_data * ysize_data]; + RFLOAT range = maxval - minval; + RFLOAT step = range / 255; // 8-bit scaling range from 0 to 255 + RFLOAT* old_ptr=NULL; + long int n; + + // For micrographs use relion-scaling to avoid bias in down-sampled positions + // For multi-image viewers, do not use this scaling as it is slower... + if (do_relion_scale && ABS(scale - 1.0) > 0.01) + { + selfScaleToSize(img, xsize_data, ysize_data); + selfScaleToSize(fom_img, xsize_data, ysize_data); + } + + // Use the same nearest-neighbor algorithm as in the copy function of Fl_Image... + if (ABS(scale - 1.0) > 0.01 && !do_relion_scale) + { + int xmod = XSIZE(img) % xsize_data; + int xstep = XSIZE(img) / xsize_data; + int ymod = YSIZE(img) % ysize_data; + int ystep = YSIZE(img) / ysize_data; + int line_d = XSIZE(img); + int dx, dy, sy, xerr, yerr; + + for (dy = ysize_data, sy = 0, yerr = ysize_data, n = 0; dy > 0; dy --) + { + for (dx = xsize_data, xerr = xsize_data, old_ptr = img.data + sy * line_d; dx > 0; dx --, n++) + { + RFLOAT val = (maxval - DIRECT_MULTIDIM_ELEM(img, n)) / range; + RFLOAT fom = (DIRECT_MULTIDIM_ELEM(fom_img, n) - _fom_min) / fom_range; + if (fom < 0.5) + { + img_data[3*n] = FLOOR(127*val); + img_data[3*n+1] = FLOOR(127*val); + img_data[3*n+2] = FLOOR(127*val); + } + else + { + img_data[3*n] = FLOOR(127*val + 127*fom); + img_data[3*n+1] = FLOOR(127*val + 127*(2*fom-1)); + img_data[3*n+2] = FLOOR(127*val); + } + + // Also store greyscale image data in img_data2 + img_data2[n] = FLOOR((*old_ptr - minval) / step); + + old_ptr += xstep; + xerr -= xmod; + if (xerr <= 0) + { + xerr += xsize_data; + old_ptr += 1; + } + } + + sy += ystep; + yerr -= ymod; + if (yerr <= 0) + { + yerr += ysize_data; + sy ++; + } + } + } + else + { + FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(img) + { + RFLOAT val = (maxval - DIRECT_MULTIDIM_ELEM(img, n)) / range; + RFLOAT fom = (DIRECT_MULTIDIM_ELEM(fom_img, n) - _fom_min) / fom_range; + if (fom < 0.5) + { + img_data[3*n] = FLOOR(127*val); + img_data[3*n+1] = FLOOR(127*val); + img_data[3*n+2] = FLOOR(127*val); + } + else + { + img_data[3*n] = FLOOR(127*val + 127*fom); + img_data[3*n+1] = FLOOR(127*val + 127*(2*fom-1)); + img_data[3*n+2] = FLOOR(127*val); + + } + // Also store greyscale image data in img_data2 + img_data2[n] = FLOOR((DIRECT_MULTIDIM_ELEM(img, n) - minval) / step); + + } + } +} + + +void DisplayBox::setData(MultidimArray &img, MultidimArray &mask_img, int _ipos, + RFLOAT _minval, RFLOAT _maxval, RFLOAT _scale, bool do_relion_scale) +{ + scale = _scale; + minval = _minval; + maxval = _maxval; + ipos = _ipos; + selected = NOTSELECTED; + fom_is_grey_instead = false; + + // For volumes only show the central slice + if (ZSIZE(img) > 1) + { + MultidimArray slice; + img.getSlice(ZSIZE(img)/2, slice); + img=slice; + } + + // create array for the scaled image data + xsize_data = CEIL(XSIZE(img) * scale); + ysize_data = CEIL(YSIZE(img) * scale); + xoff = (xsize_data < w() ) ? (w() - xsize_data) / 2 : 0; + yoff = (ysize_data < h() ) ? (h() - ysize_data) / 2 : 0; + img_data = new unsigned char [3 * xsize_data * ysize_data]; + RFLOAT range = maxval - minval; + RFLOAT step = range / 255; // 8-bit scaling range from 0 to 255 + RFLOAT* old_ptr=NULL; + long int n; + + // For micrographs use relion-scaling to avoid bias in down-sampled positions + // For multi-image viewers, do not use this scaling as it is slower... + if (do_relion_scale && ABS(scale - 1.0) > 0.01) + { + selfScaleToSize(img, xsize_data, ysize_data); + selfScaleToSize(mask_img, xsize_data, ysize_data); + } + + // Use the same nearest-neighbor algorithm as in the copy function of Fl_Image... + if (ABS(scale - 1.0) > 0.01 && !do_relion_scale) + { + int xmod = XSIZE(img) % xsize_data; + int xstep = XSIZE(img) / xsize_data; + int ymod = YSIZE(img) % ysize_data; + int ystep = YSIZE(img) / ysize_data; + int line_d = XSIZE(img); + int dx, dy, sy, xerr, yerr; + + for (dy = ysize_data, sy = 0, yerr = ysize_data, n = 0; dy > 0; dy --) + { + for (dx = xsize_data, xerr = xsize_data, old_ptr = img.data + sy * line_d; dx > 0; dx --, n++) + { + RFLOAT val = (DIRECT_MULTIDIM_ELEM(img, n) - minval) / range; + img_data[3*n] = FLOOR(127*val); + img_data[3*n+1] = FLOOR(127*val); + img_data[3*n+2] = FLOOR(127*val); + if (DIRECT_MULTIDIM_ELEM(mask_img, n) > 0.5) img_data[3*n] += 127; + + old_ptr += xstep; + xerr -= xmod; + if (xerr <= 0) + { + xerr += xsize_data; + old_ptr += 1; + } + } + + sy += ystep; + yerr -= ymod; + if (yerr <= 0) + { + yerr += ysize_data; + sy ++; + } + } + } + else + { + FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(img) + { + RFLOAT val = (DIRECT_MULTIDIM_ELEM(img, n) - minval) / range; + img_data[3*n] = FLOOR(127*val); + img_data[3*n+1] = FLOOR(127*val); + img_data[3*n+2] = FLOOR(127*val); + if (DIRECT_MULTIDIM_ELEM(mask_img, n) > 0.5) img_data[3*n] += 127; + } + } +} + + + + + int DisplayBox::toggleSelect(int set_selected) { if (selected > 0) @@ -385,10 +630,10 @@ int basisViewerWindow::fillCanvas(int viewer_type, MetaDataTable &MDin, Observat return -1; } -int basisViewerWindow::fillPickerViewerCanvas(MultidimArray image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, - RFLOAT _scale, RFLOAT _coord_scale, int _particle_radius, bool _do_startend, FileName _fn_coords, +int basisViewerWindow::fillPickerViewerCanvas(MultidimArray image, MultidimArray fom_image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, + RFLOAT _scale, RFLOAT _coord_scale, int _particle_radius, bool _do_startend, bool _do_lines, FileName _fn_coords, FileName _fn_color, FileName _fn_mic, FileName _color_label, RFLOAT _color_blue_value, RFLOAT _color_red_value, - RFLOAT _minimum_pick_fom) + RFLOAT _minimum_pick_fom, RFLOAT _min_fom, RFLOAT _max_fom) { current_selection_type = 2; // Green @@ -398,11 +643,16 @@ int basisViewerWindow::fillPickerViewerCanvas(MultidimArray image, RFLOA int ysize_canvas = CEIL(YSIZE(image)*_scale); pickerViewerCanvas canvas(0, 0, xsize_canvas, ysize_canvas); canvas.particle_radius = _particle_radius; - canvas.do_startend = _do_startend; + canvas.do_startend = _do_startend; + canvas.do_lines = _do_lines; canvas.coord_scale = _coord_scale; canvas.SetScroll(&scroll); - canvas.fill(image, _minval, _maxval, _sigma_contrast, _scale); - canvas.fn_coords = _fn_coords; + if (NZYXSIZE(fom_image) > 0) + canvas.fill(image, fom_image, _minval, _maxval, _min_fom, _max_fom, _sigma_contrast, _scale); + else + canvas.fill(image, _minval, _maxval, _sigma_contrast, _scale); + + canvas.fn_coords = _fn_coords; canvas.fn_color = _fn_color; canvas.fn_mic = _fn_mic; canvas.color_label = EMDL::str2Label(_color_label); @@ -421,6 +671,32 @@ int basisViewerWindow::fillPickerViewerCanvas(MultidimArray image, RFLOA return Fl::run(); } + +int basisViewerWindow::fillMaskerViewerCanvas(MultidimArray image, MultidimArray mask_image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, + RFLOAT _scale, int _pencil_radius, FileName _fn_mask, RFLOAT _angpix) +{ + // Scroll bars + Fl_Scroll scroll(0, 0, w(), h()); + int xsize_canvas = CEIL(XSIZE(image)*_scale); + int ysize_canvas = CEIL(YSIZE(image)*_scale); + maskerViewerCanvas canvas(0, 0, xsize_canvas, ysize_canvas); + canvas.pencil_radius = _pencil_radius; + canvas.mask_scale = _scale; + canvas.angpix = _angpix; + canvas.SetScroll(&scroll); + if (mask_image.xdim > 0) canvas.Imask() = mask_image; + else canvas.Imask().resize(image); + canvas.fill(image, canvas.Imask(), _minval, _maxval, _sigma_contrast, _scale); + + int xsize_data = CEIL(image.xdim * _scale); + canvas.Imask.setSamplingRateInHeader(_angpix * image.xdim / xsize_data); + + canvas.fn_mask = _fn_mask; + resizable(*this); + show(); + return Fl::run(); +} + int basisViewerWindow::fillSingleViewerCanvas(MultidimArray image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, RFLOAT _scale) { // Scroll bars @@ -648,6 +924,40 @@ void basisViewerCanvas::fill(MultidimArray &image, RFLOAT _minval, RFLOA boxes.push_back(my_box); } +void basisViewerCanvas::fill(MultidimArray &image, MultidimArray &fom_image, + RFLOAT _minval, RFLOAT _maxval, RFLOAT _fom_min, RFLOAT _fom_max, + RFLOAT _sigma_contrast, RFLOAT _scale) +{ + xoff = yoff = 0; + nrow = ncol = 1; + getImageContrast(image, _minval, _maxval, _sigma_contrast); + xsize_box = CEIL(_scale * XSIZE(image)); + ysize_box = CEIL(_scale * YSIZE(image)); + DisplayBox* my_box = new DisplayBox(0, 0, xsize_box, ysize_box, "dummy"); + MetaDataTable MDtmp; + MDtmp.addObject(); + //FileName fn_tmp = "dummy"; + //MDtmp.setValue(EMDL_IMAGE_NAME, fn_tmp); + my_box->setData(image, fom_image, MDtmp.getObject(), 0, + _minval, _maxval, _fom_min, _fom_max, _scale, true); + my_box->redraw(); + boxes.push_back(my_box); +} + +void basisViewerCanvas::fill(MultidimArray &image, MultidimArray &mask_image, + RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, RFLOAT _scale) +{ + xoff = yoff = 0; + nrow = ncol = 1; + getImageContrast(image, _minval, _maxval, _sigma_contrast); + xsize_box = CEIL(_scale * XSIZE(image)); + ysize_box = CEIL(_scale * YSIZE(image)); + DisplayBox* my_box = new DisplayBox(0, 0, xsize_box, ysize_box, "dummy"); + my_box->setData(image, mask_image, 0, _minval, _maxval, _scale, true); + my_box->redraw(); + boxes.push_back(my_box); +} + void basisViewerCanvas::draw() { for (int ipos = 0 ; ipos < boxes.size(); ipos++) @@ -1602,6 +1912,7 @@ void basisViewerCanvas::setFOMThreshold() } + int popupSelectionTypeWindow::fill() { color(GUI_BACKGROUND_COLOR); @@ -1767,6 +2078,7 @@ void pickerViewerCanvas::draw() RFLOAT scale = boxes[0]->scale; long int icoord = 0; + int my_prev_type = 0; int xcoori_start, ycoori_start; FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDcoords) { @@ -1775,6 +2087,8 @@ void pickerViewerCanvas::draw() RFLOAT xcoor, ycoor; MDcoords.getValue(EMDL_IMAGE_COORD_X, xcoor); MDcoords.getValue(EMDL_IMAGE_COORD_Y, ycoor); + int mytype; + MDcoords.getValue(EMDL_PARTICLE_SELECTION_TYPE, mytype); if (MDcoords.containsLabel(EMDL_PARTICLE_AUTOPICK_FOM) && fabs(minimum_pick_fom + 9999.) > 1e-6) { @@ -1832,50 +2146,73 @@ void pickerViewerCanvas::draw() { int selected; MDcoords.getValue(EMDL_PARTICLE_SELECTION_TYPE, selected); - if (selected >= 1 && selected <= 6) - fl_color(color_choices[selected - 1].labelcolor_); - else - REPORT_ERROR("ERROR: rlnParticleSelectionType in coordinate file has value outside allowed [1,6] range"); + int mycol = (selected-1)%6; + fl_color(color_choices[mycol].labelcolor_); } else { fl_color(FL_GREEN); } - int xcoori, ycoori; - xcoori = ROUND(xcoor * coord_scale * scale) + scroll->x() - scroll->hscrollbar.value(); - ycoori = ROUND(ycoor * coord_scale * scale) + scroll->y() - scroll->scrollbar.value(); - fl_circle(xcoori, ycoori, particle_radius); + int xcoori, ycoori; + xcoori = ROUND(xcoor * coord_scale * scale) + scroll->x() - scroll->hscrollbar.value(); + ycoori = ROUND(ycoor * coord_scale * scale) + scroll->y() - scroll->scrollbar.value(); - if (do_startend) - { - if (icoord % 2 == 1) - { - xcoori_start = xcoori; - ycoori_start = ycoori; - } - else - { - fl_line(xcoori_start, ycoori_start, xcoori, ycoori); - } - } - } + if (do_lines) + { + if (mytype == my_prev_type) + { + fl_line(xcoori_start, ycoori_start, xcoori, ycoori); + } + xcoori_start = xcoori; + ycoori_start = ycoori; + } + else + { + fl_circle(xcoori, ycoori, particle_radius); + + if (do_startend) + { + if (icoord % 2 == 1) + { + xcoori_start = xcoori; + ycoori_start = ycoori; + } + else + { + fl_line(xcoori_start, ycoori_start, xcoori, ycoori); + } + } + } + my_prev_type = mytype; + } } int pickerViewerCanvas::handle(int ev) { const int button = Fl::event_button() ; const bool with_shift = (Fl::event_shift() != 0); - const bool with_control = (Fl::event_ctrl() != 0); + const bool with_control = (Fl::event_ctrl() != 0); const int key = Fl::event_key(); - if (ev==FL_PUSH || (ev==FL_DRAG && (button == FL_MIDDLE_MOUSE || (button == FL_LEFT_MOUSE && with_shift)))) + if (do_lines && has_dragged && ev == FL_RELEASE) + { + current_selection_type++; + } + has_dragged = false; + + if (ev==FL_PUSH || (ev==FL_DRAG && + ( (button == FL_MIDDLE_MOUSE) || + (do_lines && button == FL_LEFT_MOUSE) || + (button == FL_LEFT_MOUSE && with_shift) ) )) { RFLOAT scale = boxes[0]->scale; int xc = (int)Fl::event_x() - scroll->x() + scroll->hscrollbar.value(); int yc = (int)Fl::event_y() - scroll->y() + scroll->scrollbar.value(); RFLOAT xcoor = (RFLOAT)ROUND(xc / (coord_scale * scale)); RFLOAT ycoor = (RFLOAT)ROUND(yc / (coord_scale * scale)); + int iaux = current_selection_type; RFLOAT rad2 = particle_radius * particle_radius / (coord_scale * coord_scale * scale * scale); + has_dragged = (ev==FL_DRAG && (do_lines && button == FL_LEFT_MOUSE)); if (button == FL_LEFT_MOUSE && !with_shift && !with_control) { // Left mouse for picking @@ -1892,8 +2229,6 @@ int pickerViewerCanvas::handle(int ev) return 0; } RFLOAT aux = -999., zero = 0.; - int iaux = current_selection_type; - // Else store new coordinate if (!MDcoords.isEmpty()) { @@ -1921,7 +2256,7 @@ int pickerViewerCanvas::handle(int ev) MDcoords.setValue(EMDL_PARTICLE_AUTOPICK_FOM, zero); redraw(); - return 1; + return 1; } else if ((button == FL_MIDDLE_MOUSE) || (button == FL_LEFT_MOUSE && with_shift)) { @@ -1937,7 +2272,25 @@ int pickerViewerCanvas::handle(int ev) if (xcoor_p*xcoor_p + ycoor_p*ycoor_p < rad2) { - MDcoords.removeObject(); + if (do_lines) + { + int delval; + MDcoords.getValue(EMDL_PARTICLE_SELECTION_TYPE, delval); + MetaDataTable MDout; + MDout.setName(MDcoords.getName()); + FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDcoords) + { + int val; + MDcoords.getValue(EMDL_PARTICLE_SELECTION_TYPE, val); + + if (val != delval) MDout.addObject(MDcoords.getObject(current_object)); + } + MDcoords = MDout; + } + else + { + MDcoords.removeObject(); + } break; } } @@ -1949,12 +2302,13 @@ int pickerViewerCanvas::handle(int ev) redraw(); Fl_Menu_Item rclick_menu[] = { { "Save STAR with coordinates (CTRL-s)" }, + { "Toggle FOM colouring (CTRL-f)" }, // { "Save_as STAR with coordinates" }, { "Load coordinates" }, { "Reload coordinates" }, { "Clear coordinates" }, { "Set selection type" }, - { "Set FOM threshold" }, + { "Set FOM threshold" }, { "Help" }, { "Quit (CTRL-q)" }, { 0 } @@ -1979,6 +2333,8 @@ int pickerViewerCanvas::handle(int ev) setFOMThreshold(); loadCoordinates(false); } + else if ( strcmp(m->label(), "Toggle FOM colouring (CTRL-f)") == 0) + toggleFomImageIsGreyInstead(); else if ( strcmp(m->label(), "Help") == 0 ) printHelp(); else if ( strcmp(m->label(), "Quit (CTRL-q)") == 0 ) @@ -2003,6 +2359,13 @@ int pickerViewerCanvas::handle(int ev) sleep(1); // to prevent multiple saves... dirty but don't know how to do this otherwise... return 1; // (tells caller we handled this event) } + if (key == 'f') + { + toggleFomImageIsGreyInstead(); + redraw(); + sleep(1); // to prevent multiple toggles? + return 1; // (tells caller we handled this event) + } else if (key == 'q') { sleep(1); @@ -2019,6 +2382,13 @@ int pickerViewerCanvas::handle(int ev) return 0; } +void pickerViewerCanvas::toggleFomImageIsGreyInstead() +{ + fom_is_grey_instead = !fom_is_grey_instead; + boxes[0]->redraw(); +} + + void pickerViewerCanvas::saveCoordinates(bool ask_filename) { FileName fn_out; @@ -2074,6 +2444,17 @@ void pickerViewerCanvas::loadCoordinates(bool ask_filename) fn_coord_in = (fn_coords=="") ? "picked.star" : fn_coords; } MDcoords.read(fn_coord_in); + if (do_lines) + { + int ifil_max =0; + FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDcoords) + { + int ifil; + MDcoords.getValue(EMDL_PARTICLE_SELECTION_TYPE, ifil); + if (ifil > ifil_max) ifil_max=ifil; + } + current_selection_type = ifil_max+1; + } if (fn_color != "") { @@ -2169,6 +2550,157 @@ void pickerViewerCanvas::printHelp() std::cout <<" + Refresh picked particles by moving out of the window and back in again ..." << std::endl; } +int maskerViewerCanvas::handle(int ev) +{ + const int button = Fl::event_button() ; + const bool with_shift = (Fl::event_shift() != 0); + const bool with_control = (Fl::event_ctrl() != 0); + const int key = Fl::event_key(); + has_dragged = false; + + int xc = (int)Fl::event_x() - scroll->x() + scroll->hscrollbar.value(); + int yc = (int)Fl::event_y() - scroll->y() + scroll->scrollbar.value(); + if (ev==FL_PUSH || ev==FL_DRAG) + { + + if ((ev==FL_PUSH || ev==FL_DRAG) && (button == FL_LEFT_MOUSE || button == FL_MIDDLE_MOUSE)) + { + RFLOAT myval = (button == FL_LEFT_MOUSE) ? 1. : 0.; + int xstart = xc - pencil_radius; + xstart = std::max(0, xstart); + int xstop = xc + pencil_radius; + xstop = std::min((int)(Imask().xdim), xstop); + int ystart = yc - pencil_radius; + ystart = std::max(0, ystart); + int ystop = yc + pencil_radius; + ystop = std::min((int)(Imask().ydim), ystop); + for (int y=ystart; y < ystop; y++) + { + int dy2 = (y-yc)*(y-yc); + for (int x=xstart; x < xstop; x++) + { + int d2 = dy2 + (x-xc)*(x-xc); + if (d2 < pencil_radius*pencil_radius) + { + if (button == FL_LEFT_MOUSE && DIRECT_A2D_ELEM(Imask(), y, x) < 0.5 ) + { + long n = Imask().xdim * y + x; + boxes[0]->img_data[3*n] += 127; + DIRECT_A2D_ELEM(Imask(), y, x) = 1.; + } + else if (button == FL_MIDDLE_MOUSE && DIRECT_A2D_ELEM(Imask(), y, x) > 0.5 ) + { + long n = Imask().xdim * y + x; + boxes[0]->img_data[3*n] -= 127; + DIRECT_A2D_ELEM(Imask(), y, x) = 0.; + } + } + } + } + boxes[0]->redraw(); + return 1; + } + else if ((button == FL_RIGHT_MOUSE) || (button == FL_LEFT_MOUSE && with_control)) + { + redraw(); + Fl_Menu_Item rclick_menu[] = { + { "Save image with mask (CTRL-s)" }, + { "Set pencil radius" }, + { "Help" }, + { "Quit (CTRL-q)" }, + { 0 } + }; + const Fl_Menu_Item *m = rclick_menu->popup(Fl::event_x(), Fl::event_y(), 0, 0, 0); + if ( !m ) + return 0; + else if ( strcmp(m->label(), "Save image with mask (CTRL-s)") == 0 ) + saveMask(); + else if ( strcmp(m->label(), "Set pencil radius") == 0 ) + setPencilRadius(); + else if ( strcmp(m->label(), "Help") == 0 ) + printHelp(); + else if ( strcmp(m->label(), "Quit (CTRL-q)") == 0 ) + exit(0); + redraw(); + return 1; // (tells caller we handled this event) + } + return 0; + } + // Update the drawing every time something happens .... + else if (ev==FL_RELEASE || ev==FL_LEAVE || ev==FL_ENTER || ev==FL_MOVE || ev == FL_FOCUS || ev == FL_UNFOCUS) + { + redraw(); + return 1; + } + // CTRL-s will save the coordinates in a picker window + else if (with_control) + { + if (key == 's') + { + saveMask(); + sleep(1); // to prevent multiple saves... dirty but don't know how to do this otherwise... + return 1; // (tells caller we handled this event) + } + else if (key == 'q') + { + sleep(1); + exit(0); + return 1; // (tells caller we handled this event) + } + else if (key >= '1' && key <= '6') + { + std::cout << "debug key = " << key << std::endl; + current_selection_type = key - '0'; + return 1; + } + } + return 0; +} + + +void maskerViewerCanvas::saveMask() +{ + if (fn_mask == "") + { + char *newfile; + newfile = fl_file_chooser("Save mask image as?", "*.mrc", ""); + if (newfile == NULL) + return; + FileName fn_tmp(newfile); + fn_mask = fn_tmp; + } + + FileName fn_dirs = fn_mask.beforeLastOf("/"); + if (!(exists(fn_dirs))) + { + std::string command = "mkdir -p " + fn_dirs; + int res = system(command.c_str()); + } + + Imask.write(fn_mask); + + std::cout << "Saved mask as "<< fn_mask << std::endl; + +} + +void maskerViewerCanvas::setPencilRadius() +{ + const char *rad; + std::string currentval = floatToString(pencil_radius/mask_scale); + rad = fl_input("Pencil radius (pixel): ", currentval.c_str()); + if (rad == NULL) + return; + std::string newval(rad); + pencil_radius = mask_scale * textToFloat(rad); + +} + +void maskerViewerCanvas::printHelp() +{ + std::cout <<" + Left-mouse click: add to mask " << std::endl; + std::cout <<" + Middle-mouse click: delete from mask " << std::endl; +} + void singleViewerCanvas::printMetaData() { boxes[0]->MDimg.write(std::cout); @@ -2603,7 +3135,7 @@ void Displayer::read(int argc, char **argv) parser.setCommandLine(argc, argv); int gen_section = parser.addSection("General options"); - fn_in = parser.getOption("--i", "Input STAR file, image or stack",""); + fn_in = parser.getOption("--i", "Input STAR file, image or stack",""); do_gui = parser.checkOption("--gui", "Use this to provide all other parameters through a GUI"); display_label = EMDL::str2Label(parser.getOption("--display", "Metadata label to display", "rlnImageName")); text_label = EMDL::str2Label(parser.getOption("--text_label", "Metadata label to display text", "EMDL_UNDEFINED")); @@ -2644,7 +3176,8 @@ void Displayer::read(int argc, char **argv) int pick_section = parser.addSection("Picking options"); do_pick = parser.checkOption("--pick", "Pick coordinates in input image"); - do_pick_startend = parser.checkOption("--pick_start_end", "Pick start-end coordinates in input image"); + do_pick_startend = parser.checkOption("--pick_start_end", "Pick start-end coordinates in input image"); + do_pick_lines = parser.checkOption("--pick_lines", "Pick lines in input image"); fn_coords = parser.getOption("--coords", "STAR file with picked particle coordinates", ""); coord_scale = textToFloat(parser.getOption("--coord_scale", "Scale particle coordinates before display", "1.0")); particle_radius = textToFloat(parser.getOption("--particle_radius", "Particle radius in pixels", "100")); @@ -2658,6 +3191,14 @@ void Displayer::read(int argc, char **argv) color_label = parser.getOption("--color_label", "MetaDataLabel to color particles on (e.g. rlnParticleSelectZScore)", ""); color_blue_value = textToFloat(parser.getOption("--blue", "Value of the blue color", "1.")); color_red_value = textToFloat(parser.getOption("--red", "Value of the red color", "0.")); + fn_fom = parser.getOption("--fom_img", "FOM-image to colour the micrograph for picking",""); + fom_min = textToFloat(parser.getOption("--fom_min", "Pixel value for lowest FOM value (black)", "0")); + fom_max = textToFloat(parser.getOption("--fom_max", "Pixel value for highest FOM value (yellow)", "0")); + + int mask_section = parser.addSection("Mask design options"); + do_mask = parser.checkOption("--paint_mask", "Paint mask in input image"); + fn_mask = parser.getOption("--fn_mask", "Name for MRC file of the designed mask", ""); + pencil_radius = textToFloat(parser.getOption("--pencil_radius", "Pencil radius to draw masks (in original pixels)", "25")); verb = textToInteger(parser.getOption("--verb", "Verbosity", "1")); @@ -2769,7 +3310,7 @@ void Displayer::initialise() REPORT_ERROR("Displayer::initialise ERROR: cannot display Fourier amplitudes and phase angles at the same time!"); if (show_fourier_amplitudes || show_fourier_phase_angles) { - if (do_pick || do_pick_startend) + if (do_pick || do_pick_startend || do_pick_lines) REPORT_ERROR("Displayer::initialise ERROR: cannot pick particles from Fourier maps!"); if (fn_in.isStarFile()) REPORT_ERROR("Displayer::initialise ERROR: use single 2D image files as input!"); @@ -2888,8 +3429,13 @@ int Displayer::runGui() win.display_labels.push_back(EMDL::label2Str(EMDL_TOMO_RECONSTRUCTED_TOMOGRAM_PROJ2D_HALF1_FILE_NAME)); if (MD.containsLabel(EMDL_TOMO_RECONSTRUCTED_TOMOGRAM_PROJ2D_HALF2_FILE_NAME)) win.display_labels.push_back(EMDL::label2Str(EMDL_TOMO_RECONSTRUCTED_TOMOGRAM_PROJ2D_HALF2_FILE_NAME)); + if (MD.containsLabel(EMDL_MICROGRAPH_AUTOPICK_FOM)) + win.display_labels.push_back(EMDL::label2Str(EMDL_MICROGRAPH_AUTOPICK_FOM)); + if (MD.containsLabel(EMDL_MICROGRAPH_AUTOPICK_PSI)) + win.display_labels.push_back(EMDL::label2Str(EMDL_MICROGRAPH_AUTOPICK_PSI)); - } + + } else { // Try reading as an image/stack header @@ -2917,9 +3463,9 @@ void Displayer::run() basisViewerWindow win(CEIL(scale*XSIZE(img())), CEIL(scale*YSIZE(img())), fnt.c_str()); win.fillSingleViewerCanvas(img(), 0., 255., 0., scale); } - else if (do_pick || do_pick_startend) + else if (do_pick || do_pick_startend || do_pick_lines || do_mask) { - Image img; + Image img, fom_img; if (do_topaz_denoise) { @@ -2929,8 +3475,14 @@ void Displayer::run() { img.read(fn_in); // dont read data yet: only header to get size } + if (fn_fom != "") + { + colour_scheme = BLACKGREYREDSCALE; + fom_img.read(fn_fom); + selfScaleToSize(fom_img(), img().xdim, img().ydim); + } - if (lowpass > 0.) + if (lowpass > 0.) lowPassFilterMap(img(), lowpass, angpix); if (highpass > 0.) highPassFilterMap(img(), highpass, angpix, 25); // use a rather soft high-pass edge of 25 pixels wide @@ -2938,8 +3490,20 @@ void Displayer::run() basisViewerWindow win(CEIL(scale*XSIZE(img())), CEIL(scale*YSIZE(img())), fn_in.c_str()); if (fn_coords=="") fn_coords = fn_in.withoutExtension()+"_coords.star"; - win.fillPickerViewerCanvas(img(), minval, maxval, sigma_contrast, scale, coord_scale, ROUND(scale*particle_radius), do_pick_startend, fn_coords, - fn_color, fn_in, color_label, color_blue_value, color_red_value, minimum_pick_fom); + + if (do_mask) + { + colour_scheme = BLACKGREYREDSCALE; + RFLOAT angpix = img.samplingRateX(); + Image Imask; + if (fn_mask != "" && exists(fn_mask)) Imask.read(fn_mask); + win.fillMaskerViewerCanvas(img(), Imask(), minval, maxval, sigma_contrast, scale, ROUND(scale*pencil_radius), fn_mask, angpix); + } + else + { + win.fillPickerViewerCanvas(img(), fom_img(), minval, maxval, sigma_contrast, scale, coord_scale, ROUND(scale*particle_radius), do_pick_startend, do_pick_lines, fn_coords, + fn_color, fn_in, color_label, color_blue_value, color_red_value, minimum_pick_fom, fom_min, fom_max); + } } else if (fn_in.isStarFile()) { diff --git a/src/displayer.h b/src/displayer.h index cf9ed5437..cafabef67 100644 --- a/src/displayer.h +++ b/src/displayer.h @@ -49,7 +49,7 @@ #define GUI_BACKGROUND_COLOR (fl_rgb_color(240,240,240)) #define GUI_INPUT_COLOR (fl_rgb_color(255,255,230)) -#define GUI_RUNBUTTON_COLOR (fl_rgb_color(100, 60, 255)) +#define GUI_RUNBUTTON_COLOR (fl_rgb_color(100, 178, 178)) @@ -72,9 +72,9 @@ static int predrag_xc; static int predrag_yc; static bool has_shift; static int preshift_ipos; - static int current_selection_type; static int colour_scheme; +static int fom_is_grey_instead; class DisplayBox : public Fl_Box { @@ -99,6 +99,9 @@ class DisplayBox : public Fl_Box // The actual image data array unsigned char *img_data; + // A copy of the actual image data array (to allow toggling of FOM-colouring) + unsigned char *img_data2; + std::string img_label; // For getting back close the original image values from the uchar ones... @@ -112,6 +115,12 @@ class DisplayBox : public Fl_Box void setData(MultidimArray &img, MetaDataContainer *MDCin, int ipos, RFLOAT minval, RFLOAT maxval, RFLOAT _scale, bool do_relion_scale = false); + void setData(MultidimArray &img, MultidimArray &fom_img, MetaDataContainer *MDCin, int ipos, + RFLOAT minval, RFLOAT maxval, RFLOAT _fom_min, RFLOAT _fom_max, + RFLOAT _scale, bool do_relion_scale = false); + void setData(MultidimArray &img, MultidimArray &mask_img, int _ipos, + RFLOAT _minval, RFLOAT _maxval, RFLOAT _scale, bool do_relion_scale); + // Destructor ~DisplayBox() { @@ -147,10 +156,13 @@ class basisViewerWindow : public Fl_Window int _nr_regroup = -1, bool do_recenter = false, bool _is_data = false, MetaDataTable *MDgroups = NULL, bool do_allow_save = false, FileName fn_selected_imgs="", FileName fn_selected_parts="", int max_nr_parts_per_class = -1); int fillSingleViewerCanvas(MultidimArray image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, RFLOAT _scale); - int fillPickerViewerCanvas(MultidimArray image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, RFLOAT _scale, RFLOAT _coord_scale, - int _particle_radius, bool do_startend = false, FileName _fn_coords = "", + int fillPickerViewerCanvas(MultidimArray image, MultidimArray fom_image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, RFLOAT _scale, RFLOAT _coord_scale, + int _particle_radius, bool do_startend = false, bool do_lines = false, FileName _fn_coords = "", FileName _fn_color = "", FileName _fn_mic= "", FileName _color_label = "", RFLOAT _color_blue_value = 0., RFLOAT _color_red_value = 1., - RFLOAT _minimum_pick_fom = -999.); + RFLOAT _minimum_pick_fom = -999., RFLOAT _min_fom = 0., RFLOAT _max_fom = 0.); + int fillMaskerViewerCanvas(MultidimArray image, MultidimArray mask_image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, + RFLOAT _scale, int _pencil_radius, FileName _fn_mask, RFLOAT angpix); + }; class basisViewerCanvas : public Fl_Widget @@ -189,7 +201,10 @@ class basisViewerCanvas : public Fl_Widget void fill(MetaDataTable &MDin, ObservationModel *obsModel, EMDLabel display_label, EMDLabel text_label, bool _do_apply_orient, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, RFLOAT _scale, int _ncol, bool do_recenter = false, long int max_images = -1, RFLOAT lowpass = -1.0, RFLOAT highpass = -1.0); - void fill(MultidimArray &image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, RFLOAT _scale = 1.); + void fill(MultidimArray &image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, RFLOAT _scale = 1.); + void fill(MultidimArray &image, MultidimArray &fom_image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _fom_min, RFLOAT _fom_max, RFLOAT _sigma_contrast, RFLOAT _scale = 1.); + void fill(MultidimArray &image, MultidimArray &mask_image, RFLOAT _minval, RFLOAT _maxval, RFLOAT _sigma_contrast, RFLOAT _scale); + void setSelectionType(); void setFOMThreshold(); }; @@ -410,6 +425,9 @@ class pickerViewerCanvas : public basisViewerCanvas // Draw lines between start-end coordinates? bool do_startend; + // Draw lines for curvy filaments? + bool do_lines; + // Micrograph name (useful to search relevant particles in fn_color) FileName fn_mic; @@ -424,12 +442,50 @@ class pickerViewerCanvas : public basisViewerCanvas private: // Functionalities for popup menu + void toggleFomImageIsGreyInstead(); void saveCoordinates(bool ask_filename = false); void clearCoordinates(); void printHelp(); void viewExtractedParticles(); }; + +class maskerViewerCanvas : public basisViewerCanvas +{ +protected: + int handle(int ev); + void draw() {}; + +public: + + int pencil_radius; + + // Scale for pencil_radius + RFLOAT mask_scale; + + // Original angpix + RFLOAT angpix; + + // Filename of the mask + FileName fn_mask; + + // Image with the mask + Image Imask; + + // Constructor with w x h size of the window and a title + maskerViewerCanvas(int X, int Y, int W, int H, const char* title=0): basisViewerCanvas(X,Y,W, H, title) { } + +private: + + // Functionalities for popup menu + void saveMask(); + void setPencilRadius(); + void clearMask(); + void printHelp(); + +}; + + // This class only puts scrollbars around the resizable canvas class displayerGuiWindow : public Fl_Window { @@ -555,7 +611,10 @@ class Displayer RFLOAT coord_scale; // Input & Output rootname - FileName fn_in; + FileName fn_in, fn_fom; + + // Min and max for FOM scale + RFLOAT fom_min, fom_max; // Ignore optics groups bool do_ignore_optics; @@ -584,6 +643,9 @@ class Displayer // Flag to pick start-end bool do_pick_startend; + // Flag to pick lines + bool do_pick_lines; + // Flag for looking at classes bool do_class; @@ -651,6 +713,15 @@ class Displayer // Shell for calling Topaz FileName fn_shell; + // Flag to design mask + bool do_mask; + + // Filename for coordinates star file + FileName fn_mask; + + // pencil radius for drawing masks + int pencil_radius; + public: // Read command line arguments void read(int argc, char **argv); diff --git a/src/exp_model.cpp b/src/exp_model.cpp index d685fa5a7..dc5e91f0b 100644 --- a/src/exp_model.cpp +++ b/src/exp_model.cpp @@ -991,7 +991,7 @@ bool Experiment::read(FileName fn_exp, FileName fn_tomo, FileName fn_motion, if (tomo_name != prev_tomo_name) { - tomogram = tomogramSet.loadTomogram(tomo_id, false); + tomogram = tomogramSet.loadTomogram(tomo_id, false, false, false, -999, -999, -999, true); // Ignore tomo size prev_tomo_name = tomo_name; // Tomogram sanity checks diff --git a/src/gui_background.xpm b/src/gui_background.xpm index a13604579..b93217159 100644 --- a/src/gui_background.xpm +++ b/src/gui_background.xpm @@ -2,593 +2,593 @@ static const char *gui_background[] = { /* columns rows colors chars-per-pixel */ "598 332 256 2 ", -" c #010101", -". c #09090A", -"X c #100F0F", -"o c #0D0814", -"O c #120C1A", -"+ c #171618", -"@ c #29121C", -"# c #1E201F", -"$ c #170D26", -"% c #1C1427", -"& c #1E1132", -"* c #251B28", -"= c #371927", -"- c #38152C", -"; c #251738", -": c #282528", -"> c #35252C", -", c #2C2436", -"< c #362A36", -"1 c #393639", -"2 c #50172E", -"3 c #5B1530", -"4 c #701236", -"5 c #472837", -"6 c #4D2D3C", -"7 c #2B1946", -"8 c #331D53", -"9 c #362748", -"0 c #3C3445", -"q c #3B2557", -"w c #1F2761", -"e c #3D2363", -"r c #463947", -"t c #583747", -"y c #4D2E50", -"u c #463757", -"i c #752147", -"p c #772949", -"a c #6E344E", -"s c #442969", -"d c #4B3567", -"f c #50376F", -"g c #4A2A77", -"h c #543879", -"j c #3E4242", -"k c #484649", -"l c #504551", -"z c #564956", -"x c #585659", -"c c #674757", -"v c #6E4C5C", -"b c #574768", -"n c #5D5764", -"m c #5B4477", -"M c #675966", -"N c #71526D", -"B c #685777", -"V c #5F6263", -"C c #686669", -"Z c #706770", -"A c #766976", -"S c #787679", -"D c #910538", -"F c #A8013D", -"G c #921746", -"H c #B80345", -"J c #AD134E", -"K c #8E2E55", -"L c #AD275A", -"P c #B71F60", -"I c #953A63", -"U c #B13568", -"Y c #C70249", -"T c #D30B55", -"R c #E80356", -"E c #F30259", -"W c #FD005D", -"Q c #E4125E", -"! c #C4225E", -"~ c #D51963", -"^ c #FF0164", -"/ c #FF006B", -"( c #FC0A68", -") c #E91065", -"_ c #FA156B", -"` c #FF0B73", -"' c #FF1877", -"] c #CF306F", -"[ c #E92D76", -"{ c #FC257A", -"} c #974769", -"| c #924F6B", -" . c #8E536E", -".. c #AB4A72", -"X. c #B84877", -"o. c #A75679", -"O. c #886878", -"+. c #906A7C", -"@. c #C7477A", -"#. c #D5487C", -"$. c #E1467E", -"%. c #80817F", -"&. c #03398C", -"*. c #083D8D", -"=. c #073E91", -"-. c #512D87", -";. c #593787", -":. c #5C3595", -">. c #623C98", -",. c #5F34A0", -"<. c #663BA6", -"1. c #6E3DB7", -"2. c #144996", -"3. c #2E5DA1", -"4. c #654888", -"5. c #6F558B", -"6. c #694797", -"7. c #765898", -"8. c #59609E", -"9. c #7A668E", -"0. c #7E7A83", -"q. c #734BA9", -"w. c #7249AC", -"e. c #7956A7", -"r. c #7648B8", -"t. c #733FC1", -"y. c #7B47C7", -"u. c #7E47D0", -"i. c #FB2082", -"p. c #FF2885", -"a. c #EC3A85", -"s. c #FD3789", -"d. c #FF3A95", -"f. c #B55884", -"g. c #877886", -"h. c #977788", -"j. c #8C7092", -"k. c #AF6F8E", -"l. c #835AB5", -"z. c #8768A7", -"x. c #8E70AF", -"c. c #9877B8", -"v. c #A26FA2", -"b. c #C75788", -"n. c #D5518A", -"m. c #E84987", -"M. c #F8488B", -"N. c #EC528D", -"B. c #FE4798", -"V. c #E85897", -"C. c #FB559A", -"Z. c #CD6A97", -"A. c #E8649C", -"S. c #FF4BA3", -"D. c #E95CA4", -"F. c #FE58A8", -"G. c #FF5CB2", -"H. c #D477A6", -"J. c #FA66AA", -"K. c #E971AA", -"L. c #FF68B7", -"P. c #FC76B9", -"I. c #8757C8", -"U. c #864FD5", -"Y. c #8A55D7", -"T. c #976BCD", -"R. c #A47AD3", -"E. c #9153ED", -"W. c #9C65E7", -"Q. c #AB74F0", -"!. c #DD79C0", -"~. c #FE6EC1", -"^. c #FF79C6", -"/. c #6788B9", -"(. c #7A97C2", -"). c #878689", -"_. c #94848D", -"`. c #8D8B93", -"'. c #978896", -"]. c #979699", -"[. c #A78798", -"{. c #AC8D9D", -"}. c #9987AB", -"|. c #9D9CA2", -" X c #A799A6", -".X c #AF92AF", -"XX c #9EA2A7", -"oX c #A6A5AA", -"OX c #B3A4AE", -"+X c #ADACB2", -"@X c #B6A9B6", -"#X c #B3B2B6", -"$X c #B6B5BA", -"%X c #BABABD", -"&X c #C3849F", -"*X c #D08FB1", -"=X c #EC8ABA", -"-X c #CAA9BB", -";X c #B18FCF", -":X c #90A7CB", -">X c #B6AACD", -",X c #BCB4C6", -" c #B4B4C4", +", c #CCCCDC", +"< c #ECECF9", +"1 c #A4A4AD", +"2 c #C4C4CC", +"3 c #BCBCC4", +"4 c #B4B4BC", +"5 c #D4D4DC", +"6 c #CCCCD4", +"7 c #F4F4FC", +"8 c #DCDCE4", +"9 c #04147E", +"0 c #676A75", +"q c #989BA5", +"w c #051747", +"e c #B4BCD4", +"r c #7F8490", +"t c #042C89", +"y c #8C9098", +"u c #A9ACB2", +"i c #2B559F", +"p c #4467A6", +"a c #C3CCDC", +"s c #134394", +"d c #5878AE", +"f c #6C88B6", +"g c #8098BE", +"h c #585B60", +"j c #93A8C6", +"k c #787C82", +"l c #727477", +"z c #AABED9", +"x c #A7B7CC", +"c c #9BA6B5", +"v c #B8C4D4", +"b c #D0DCEB", +"n c #CCD4DD", +"m c #BCC4CC", +"M c #B4BCC4", +"N c #C4CCD4", +"B c #D5E4F2", +"V c #C4D4E1", +"C c #BCD4E4", +"Z c #E0EEF6", +"A c #9BA5AA", +"S c #ACB4B8", +"D c #ECF4F7", +"F c #244851", +"G c #68A4B2", +"H c #2F5B65", +"J c #041417", +"K c #388896", +"L c #37494C", +"P c #BCCCCE", +"I c #155C60", +"U c #236C6D", +"Y c #346465", +"T c #508C8D", +"R c #2C6464", +"E c #306C6C", +"W c #ACD4D4", +"Q c #B1CCCC", +"! c #CFE9E9", +"~ c #C4DCDC", +"^ c #C2D4D4", +"/ c #C4CCCC", +"( c #BCC4C4", +") c #B4BCBC", +"_ c #F3FCFC", +"` c #D4DCDC", +"' c #CCD4D4", +"] c #DCE4E4", +"[ c #8CC8C6", +"{ c #084C48", +"} c #09544F", +"| c #186F69", +" . c #3BABA4", +".. c #357470", +"X. c #285451", +"o. c #7DBDBA", +"O. c #1A645E", +"+. c #29867E", +"@. c #31938B", +"#. c #174440", +"$. c #163A37", +"%. c #265C58", +"&. c #39847D", +"*. c #367C76", +"=. c #458A85", +"-. c #72B4AF", +";. c #A2BCBA", +":. c #0A5E56", +">. c #0A3E38", +",. c #06211E", +"<. c #0C312D", +"1. c #194C47", +"2. c #1C544E", +"3. c #2A7C73", +"4. c #24645D", +"5. c #2B746C", +"6. c #3A9C92", +"7. c #3B8C83", +"8. c #44948B", +"9. c #579C94", +"0. c #5CA49D", +"q. c #58948E", +"w. c #759C98", +"e. c #86A29F", +"r. c #1C5C54", +"t. c #246C63", +"y. c #43A497", +"u. c #2D6C64", +"i. c #499C92", +"p. c #4FA499", +"a. c #57AEA2", +"s. c #68A8A0", +"d. c #48746E", +"f. c #557C77", +"g. c #658B86", +"h. c #294C47", +"j. c #365C56", +"k. c #3C645E", +"l. c #4B7C74", +"z. c #436C66", +"x. c #35544F", +"c. c #5B8C84", +"v. c #56847D", +"b. c #6B9C94", +"n. c #66948D", +"m. c #77A49D", +"M. c #30645B", +"N. c #26433D", +"B. c #7BACA2", +"V. c #85ACA4", +"C. c #95BCB4", +"Z. c #AFC4C0", +"A. c #ACBCB9", +"S. c #89B4AA", +"D. c #C0E4DC", +"F. c #B6D4CD", +"G. c #46635C", +"H. c #8BBCB0", +"J. c #55766D", +"K. c #9CC4B9", +"L. c #A6CBC1", +"P. c #BADCD3", +"I. c #77978E", +"U. c #ACD4C8", +"Y. c #96B8AD", +"T. c #75A494", +"R. c #B4CCC4", +"E. c #C4DCD4", +"W. c #CCDCD5", +"Q. c #BCCCC4", +"!. c #C7D4CC", +"~. c #F3FCF4", +"^. c #040C04", +"/. c #C4CCC4", +"(. c #D4DCD4", +"). c #ECF4EC", +"_. c #E4ECE4", +"`. c #DCE4DC", +"'. c #4F504F", +"]. c #F4FCEC", +"[. c #656662", +"{. c #6F7241", +"}. c #EDEED5", +"|. c #0C0C04", +" X c #FCFCEC", +".X c #B4B4A9", +"XX c #CCCCC4", +"oX c #BCBCB4", +"OX c #D4D4CC", +"+X c #FCFCF4", +"@X c #F4F4EC", +"#X c #ECECE4", +"$X c #E4E4DC", +"%X c #DACC1B", +"&X c #DED23A", +"*X c #E6E2B1", +"=X c #E1D76F", +"-X c #A8992A", +";X c #A19F90", +":X c #C7B229", +">X c #927D10", +",X c #6D5A0D", +"XyX>X3XQ.d.d.d.d.d.S.G.G.~.~.^.7XtX7XtX7X7X^.^.~.~.G.~.D.].DXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX+X=XwXqXwXwXxXmXbXbXzXxX0X,X;X}.}.A U { s.s.s.s.s.M.M.C.C.$.*X*X=X6XwXwXwXwXmXwXVXVXVXSXKXUXUXKXwXwX=XA.&X$.o.vXGXPXGXPXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX .R E _ ' { d.B.C.G.J.L.L.J.L.G.G.F.L.=X*X-X@X>X.X;X3X;X;X;XS.i.d.d.S.S.S.S.G.G.~.^.7XtX7X8X8X7X4X~.G.G.~.G.D.m JXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX_.wX6X6XwXwXmXmXbXbXvXcXjX,X>XXXz.K $.$.s.{ s.M.M.C.C.C.C.A.$.=X=X6X6X6X6X6XwXwX6XqXqXaXVXKXKXKXmX6X*Xk.o.k.o.C PXGXPXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXhX X X{.O.m.C.F.J.L.P.=XP.^.^.^.L.P.4X5X-X@X.X}.x.;X;X;X;X.XS.d.d.d.d.S.S.G.G.~.~.^.tXtXtX8X7X7X^.~.~.G.G.G.D.}.JXJXJXJXJXJXJXGXoXnXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXGXJXJXJXJXPXGXGX{.6X6X5XwXwXxXmXnXbXbXMX0X0X0X,X>X9.} $.[ M.M.s.B.C.C.C.C.A.A.=X6X=X6X6X-X=XwX5X6X6XwXwXwXVXVXKXVXwX*X%.kXkXvXGXJXGXGXPXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX$Xo.A.J.P.=X6X4X=X4X6X4X4X6X5X-X.Xc.j.7.9.z.c.c..X3XF.d.d.d.S.S.S.G.~.~.^.^.tXpXtXtX8X7X^.~.G.G.G.G.f.NXJXJXJXJXJXJXGX .P L +.OXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHX@Xh.| gXJXJXJXJXGXGXPXoX=X6X=X*X5XxXmXnXbXNXNXNXMXMXyX0X>X9...n.m.{ M.B.C.C.A.C.C.$.A.=X=X=X=X*X*X*X*X=X=X5X6X6X6XwXaXVXwX{.nXKXJXJXJXJXPXGXPXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[.H.=X=X6X6X6X6X6X8X8X6X5X.X Xx.9.4.5.7.7.7.j.>X5XF.d.S.S.S.G.G.G.~.~.^.tXtXaXpXqX8X8X^.~.G.G.G.G.h.JXJXJXJXJXJXFX .R ^ / / ) } X>X>X.Xv.{ s.s.M.C.C.A.A.C.C.$.#.&X#.&X+.k.h.o.&Xo.&X=X=X=X=X=X=XwXoXGXKXJXJXJXJXJXGXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXHX'.K.=X=X=X6XqXqX6X=X6X=X*X.Xj.m b f h h m 4.m 4..XwXP.G.S.S.S.G.G.G.~.7X8X0XyX0XyX0XwX5X4XK.Z.k.f.&XGXJXJXJXJXJXJXJX+XG H H T ( ( / / / / R .GXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXO.p ] ' p.i.p.{ { ! K K Z FXGXPXGXGXGXPX$X=X6X5X0X-X-X9XmXPXLXFXMX9X9X>X;X@X;XN $.s.$.M.M.C.C.C.$.$.$.$.#.&X+.O.C O.v Z O.k.&X=X=X=X=X$.=XK.%.nXJXGXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXzX+.C.J.=X4X4X6XqX8X8X4X=X=Xv.j.n n c y r y r r f m v.wX4XL.F.G.G.G.G.^.qXaX;XT.T.T.;X;X-X+.).|.$XzXJXLXJXJXJXJXJXJXJXGX9XK D D F T ^ ( ( ( / / J a OXHXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX+Xa.i.i.i.i.' p.' { { P 6 gXJXJXGXGXPXGXPXGXjXoXoXOXg.g.OXxXFXBXNX9X0X9X>X@X>X>X .$.{ [ { { M.M.$.$.$.{ $.#.@.t V Z C C v C o.#.&X$.=X=X=X=X=X=Xk.%XPXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHX.X@.M.C.J.P.^.P.=X4X6X=XK.K.k. .B ).+.I i 2 5 5 5 - u z.4X4XP.P.J.L.L.L.tXZXR.T.I.T.T.;X;X/.GXHXJXJXJXJXJXJXJXJXJXJXJXOX| T ~ ~ G D J Q _ ` ` ( ( / ` ! cXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJX .L ' p.i.{ i.' i.' { { { _ U O.vXPXGXGXPXGXGXPXGXGXJXJXvX).|.xXxXlX9X0X9X>X>X>X9X} $.[ ] ] ] $.[ $.] ] ] ] ! U U S C x O.S O.+.o.&XA.&X$.A.A.A.=XA.A._.GXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXvXx ~ { s.B.C.J.P.P.P.=XP.P.H.Z.v ].kXJXh.G p 6 2 2 2 5 q 5.H.4X^.P.L.J.G.=XwXR.I.I.I.T.1X1X'.%XGXJXJXJXJXJXJXJXJXJXJXJXJX> G ! ! ] G 4 J ~ _ ' _ _ / ` / ` {.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX X] P i.i.i.{ p.p.p.p.p.{ { _ [ ! t HXPXGXGXPXGXGXGXPXJXJXJXJX].9X9X0X0X,X>X3X>X>X>X| [ @.] U ! ] ] ] ] ] ! U L L K O.GXkX].S C O.o.o.k.#.Z.Z.Z.Z.N.A.C.X.v +XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFX[.{.} ( ] ' p.d.B.F.G.L.J.P.J.J.D.C.n.k.kXJXBXO.a 4 3 5 = = u z.c.v.*XP.L.G.L.3X;XT.T.T.T.R.;Xj.%XJXJXJXJXJXJXJXJXJXJXJXJXJXJXM L ] ] U G G J [ { { ' ' ' ` ` ` o.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXJXJXO.d.L p.{ p.p.{ p.p.s.p.s.{ { [ L O.HXJXJXJXJXHXHXPXGXJXJXJXJXGX|.>X,X>X>X,XyX0X9X>X .#.@.@.U ......I ..U L L K .].GXGXzX-XS C C C | | O.| O.v | | o.n.Z.C.b.O.v -XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXnX..^ ^ / ( _ [ p.s.M.B.S.S.F.F.J.F.F.d.p.] t XXJXHX9XA a 3 2 < b x.;X;X}.H.J.D.c.c.T.T.T.x.T.c.0.vXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX).I U ] U G G ! a.s.{ { ' i.' ' ` N LXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX .d.a.p.p.p.s.s.p.s.{ s.{ s.[ [ @.].GXJXJXJXJXPXHXPXGXJXJXJXJXGXJX+X}.>X>X>XcXjXgX@XN #.#.....I K v K a v v v _.nXPXGX|._.k.%.O.C V v v x v v v V v v N.N.M.M.M.M.@.OXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXBX@.^ E W ^ ( _ J { p.d.M.B.B.B.B.B.S.d.' ' ` ) a V FXGXJXoXr + r 9.}..X;X;X}.c.c.c.c.x.x.z.z.9. XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX+X| X.U K G U [ a.s.d.s.p.i.' ' ' c JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXk.s.B.s.p.p.s.s.s.s.s.s.s.$.[ @.o.oXJXJXJXGXJXPXHXGXHXJXJXJXJXJXJXJXhX).}.>X>XkXX>X.Xc.x.z.z.7.5.5.).cXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX } V.J.J.J.P.L.G.F.S.S.S.S.V.{.JXJXJXJXJXJXJX].OXwX0X>X@X.Xk.h. .} o.U f.n.V.F.F.G.L.J.F.S.M.[ ....j.FXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX#X].cX#XPXPXPXPXPXnXXXoX+XXX+XFXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXgX].PXPXPX].].GXHXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFXNXHXJXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX.XU J ~ ) ) OXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX#X+.+.C.J.J.K.K.=XK.H.H.H.K.H.&X*X*XH.P.P.^.^.^.6X*X#XGXHXJXJXJXJXJX+Xh.+._.OX Xn c {.-XKXIXIXUXUXUXIXIXIXmXZ HXGXJXJXJX{.D.G.F.S.F.S.S.S.M.M.n.n.n.V.V.V.H.H.h.c a v 1 `.+.HXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[.'.z h.4X4XH.b. .v I a a 6 5 v 2 3 I U ] U I 3 a *XlXJXJXJXFXA h. .t 5 K f.P.=X4X6X7X7X^.^.^.^.P.K.'.S JXJXJXJXJXJX]..X;X;X;X.X.X{.{.k.h.j.f.f.f.b.A.V.V.J.L.G.G.S.d.s.{ i.) +.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX].PX#XPXPXPXPXPXPXPXPXPXPXPXBX].|.JXJXJXJXJXJXJXJXJXJXJXJXGXGXJXJXJXJXJXJXJXJXGX$X+XPXPXPXPXPXcXS bXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNXJXJXlXOXh.'. X,XcXJXJXlXk.o.I L J J L U k.{.,XBXJXPXPXJXJXJXJXJXJXJXJXJXJXJXJXJXHXBXj.~ / ` / / / I BXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX-Xc m.C.C.J.J.J.K.K.K.=X=XK.*X*X=X*X*X=X=X4X7X7X8X8X6XmX#X+XHXJXJXJXJXJX`.Z 9X@XOXXX`.6 N {.wXSXSXSXSXAXSXSXKXKX].%XPXJXGX[.F.G.G.G.G.F.F.B.M.b.X.I I .A.A.K.K.K.=X5Xh. .b.F.m.].JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXoXP.6Xh.qXP.G.D.Z.f.I a a t i 5 k l 6 5 2 3 K K a f.K.Z.9XJXLX_.c.j.N 5 @.Z.*X8XqXqXaXaXaXqX8X8X4X5X;X,X@XXJXJXJXJXFX%.jX,X@X.X}.`./.t c }.iXsXMXpXCXVXCXCXxXxX|.BXLXv.G.G.G.G.G.L.F.F.F.C...K a 6 5 o.Z.H.H.H.P.P.L.F.d.p.{ } JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXh.=Xk.AX8X~.S.S.V.Z.f.I a a a = 1 6 j 6 c a 6 6 c .+.Z.k.+X|.x.z.j.c n.P.4XqXaXVXAXVXVXSXVXpXpXwX>X>XMXCX{.nXJXJX].5.7.9.x.}.}.#X 6 o.f.Z.J.P.L.F.d.` ( E P '.LXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX+X+.h.CXaX^.~.G.S.F.A.Z.f.I a p > # 1 1 6 a c v c c v v .b.a 7.l.z.9.N L.7XqXaXSXIXIXIXUXIXIXSXZXiXyXyXZXPXKXC ,XS 5.4.5.5.9.`.|.>XXoXoX|.].h.k.Z.Z.H.H.A.J.J.J.S.d.i.` / / f.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXoXPXPXPXPXPXPXPXPXPXPXPXPXcXXXcXX0X0X 1 6 k c c k z c M .o.a T.z.z.5.b t H.pXVXSXIXIXSXAXSXSXSXZXZXuXiXCXIXIXM 6.4.;.m h b B 9.x.}.;X;Xc.x.}.}.g.A S g.{.&X*X=XH.A.L.J.F.d.p.i./ / f.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXoXGXPXPXPXPXPXPXPXPXPXPXPXPXS %.#XGXJXJXJXJXJXGX].PXPXPXPXPXPXPXPXPXPXPXGXoXkXPX].BXGXPXPXPXPXPXPXPXPXPXoXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXLXFXh./ / / / / / / / ` / / ` / / / / / / / / / / / / ` / / / / / / / K cXJXJXJXJXJXJXJXvX .R R E E W W W W E ^ / / / ` ] h.GXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX[.d.S.F.G.L.J.J.=XJ.=X=X*X&X-X-X9XjX,XoX X>XwXVXSXVXVXCXCXCXZXZXsXiX;Xj.A S XX}.e.}.9.}.`.}.}.j.: 7.c.}.>X@X@X|.`.+.0.m m.G.S.G.G.G.L.G.J.J.J.F.N. .C v v l 5 | K.P.P.L.L.M.[ ~ L k.#XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXg.CXIXSXaXtXtX7X^.4X6X6X*X+.v a ).A 5 1 5 k k l l z z v N v 5.l.c.j.B u < r *XiXZXZXZXdXdXdXAXAXZXiXsXiXZXSXIXA ;.m h f d b 4.5.e.l.z.e.e.5.9.b x z l Z '..X*X-X*XK.K.J.J.S.d.i.` / o.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXcXJXJXJXJXJXJXGXhXkXPXPXPXPXPXPXPXPXPXPXPXPXnXXXGXJXJXJXJXJXJX$XcXPXPXPXPXPXPXPXPXPXJXPXJXJX%X].vX).FXFXGXPXPXPXPXPXPXPXGXoXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX .( / / / / / / ` / / / / / / / / / / / / / / ` ` / / / / / / / / / .LXJXJXJXJXJXJXJXvXI R R R E E E E E ^ ^ / / / / ( o. XDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXh.B.G.G.J.L.J.P.J.K.=X&X&X_._.{.oXOX}.x.j.j.>X0XVXAXCXmXMXZXLXLXZXZXZXLXZX1XZ }.}.}.9.}.x.}.}.}.z d 7.z.9.M r 0.S Z B x N.S.G.G.G.G.G.J.L.J.F.F.C...l N M M : o.K.P.K.V.V.m.] I .c.}.].kXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXgX'.pXSXIXSXAXdXpXtX7X8XqXaX-X+.v C %.t t 6 j k l l k l z z t - b h.h. .v r , 5.z.;XrXrXuXuXpXuXuXpXsXuXsXuXsXSXSXn m 4.m h h f ;.4.6.q.6.6.;.m ).XX+XXX).k A ].OX-X*X*X=XJ.A.C.d.p.i.` I NXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX`.).].].oXkXBXkXoX).PXPXPXPXPXPXPXPXPXPXPXPXPXJX`.FXJXJXJXJXJXJX].PXPXPXPXPXGXPXPXPXPXPXFXFXFXFXBX_.).%XFXFXPXPXPXPXPXPXPXPX#XnXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXcXK / / / / / / / / / / / / / / / / / / / / / / / / / ` / / / / / / / ) zXJXJXJXJXJXJXJXJXh.Y Y Y R E E E E W ^ ^ ^ / / / / [ f. XDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXh.S.G.J.J.J.P.J.K.K.Z.[.&X%.O.]. XS ).S 0.9.z.;X0XCXMXZXMXZXZXLXIXSXSXSXSXiX}.m 9.e.x.9.x.}.}.x.0.1 b n .XAXAX9.C M n l V.F.G.S.F.G.L.G.G.G.J.F.C.n.c : Z v 5 K.A.D.b.b.f...I v z 9.;XyX}.B V < y M h.O.N c z z 0 z.;X1XrXuXrXrXuXrXrXuXuXuXsXuXsXAXyX0 4.6.6.4.h h ;.;.>.>.;.;.m `.JXJXJXJXJXXXj g.oX9X-X*X*X=XJ.F.S.d.p.' a.#XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXhXXXJXPXPXPXcX+X+XhXFXPXPXFXFXGXFXPXPXPXPXPXPXPXGXGXXXoXJXJXJXJXJXJX].GXGXGXFXGXGXGXGXGXGXGXFXBXBXBXFXFX#Xk vXFXPXPXPXPXPXPXPXPXPXoXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJX", -"LXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX.XU / / / / / / / / / / / / / / / / / / / / / / / / ` / ` / ` / / / / / / n.JXJXJXJXJXJXJXJX%XL Y Y R R R E E W W ^ W ^ / ^ / / / ) ..'.GXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX .F.G.J.J.P.J.J.K.A.Z.Z.h.+.V ].].JXJXJXJX`.5.x.>X,X0XyXZXZXLXZXLXIXSXZXZXZX>X7.m 9.e.x.x.}.}.9.b r .XSXSXIXLXlXn n l q d } V.A.G.L.G.L.G.G.F.F.C.B.p j Z v < a | | | N N a r < 0 5.x.;X1XyX>Xl z BXJXJXJXJXJXJXJXJXJXJXJXcX|.>XCX'.pXSXZXIXIXSXSXIXIXSXIXSXxXOX X'._.k 6 x l x z z k Z j.z.R.c.j.S Z N z u t d 9.R.1XeXrXrXuXrXuXuXuXpXpXsXuXrXeXz h 4.6.6.>.>.h h ;.;.;.h m C JXJXJXJXJXJXvX0 0. XhXxXwX5X=X=XP.J.S.p.i.` ].LXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXhXX0X9X@Xh.IXSXZXIXSXSXSXUXUXPXCX>X0XgX-X-X-X%.6 k z z k S >Xc.z.z.7.B M M M c z 0 5.e.;X2XeXrXuXuXuXuXtXuXdXuXpXuXQ.m m m ;.4.>.>.;.g f -.h ;.c /.JXJXJXJXJXJXJXJXk 9. X9XxXmXwXwX6X=XP.S.d.i.` h.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXkXXXPXPXPXPXPXPXPXPXPXJXPXPXPXPXFXFXFXFXPXPXGXGXFXFXnX%.FXJXJXJXJXJXJXkXGXGXPXFXGXGXPXGXPXGXGXGXFXBXnXvXcXvXnXBXBXFXPXPXPXPXPXPXPXPXPXPXS FXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHX| / / ^ / ^ ^ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / ( / {.JXPXGXGXPXPXGXGX| F F F Y Y R R R E E W W ^ ^ ^ / / / / / / / / L h.GXLXJXJXJXJXJXJXJXJXJXJXJXJX-XZ.L.P.L.P.P.P.P.P.=X=X&Xk.M 0 $XJXJXJXJXJXJXJX`.m 5.5.5.5.}.MXZXZXZXZXiXuXyX1X1X1X>Xm }.B B yXAXAXAXdXZXAXSXZXMX>Xx , 0 m 5.e.;X}.B f.F.G.S.S.d.B.a.U < C C A r r 9 < 9 9 q u d m 5.5.z.x.;X;XyXMXyXA 9XJXJXJXJXJXJXGXZ 9.}.}.}.'.j.n LXZXZXZXLXSXSXPXLXZXyX0XMXMXVXCXmX0X{.x j l M .Xx.z.7.4.m b b N n b y u z.c.R.1XeXrXrXuXuXpXdXuXdXdXsXrX6.h 5.>.m >.;.h h g e e q b XXJXJXJXJXJXJXJXJXNXV B j.>XjXxXmXwXwX8XP.F.d.p.i.b.LXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXKXzX%.PXPXPXPXPXPXPXPXPXPXGXGXPXPXGXGXFXFXGXPXPXGXGXFXBX%.FXGXJXJXJXJXJXJXJX+XcXGXFXJXPXJXJXFXPXFXFXFXFXnXnXcXcXnXnXnXnXFXGXGXPXPXPXPXPXPXPXhXV JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXOX) / / / ^ / ^ / / / / / / / / / / / / / ` / / / / / / / / / / / / / / / ^ ~ %XJXGXGXPXFXGXKX#XT F F F F Y R R R R W W W W W ^ ^ / / / / / / / / ` U ,XJXJXJXJXJXJXJXJXJXJXJXJX$XS.L.P.P.^.4X4X4X=X4X=X&Xk.M k BXJXJXJXJXJXJXJXJX`.B m m 4.7.yXZXZXZXiXuXuX2X1X1XeXyXj.M MXSXSXAXZXdXdXsXZXAXZXiX>X}.1 q f 6.e.c.;X>X}.N m.S.d.d.d.] L 1 Z 9.0.x n u u 0 9 u d h m 4.4.4.e.T.;XyXMXMXlXS nXJXJXJXJXJX0.9.9.9.9.5.B n x j.ZXiXMXZXZXZXZXMXyXyXiXMXCXAXAXwXwX5XOX5 t '.9.5.4.m f u u u b d u , m T.R.1XQ.2XrXuXsXsXuXdXdXsXuXrXT.d m 5.5.>.h h g s e q u A lXJXJXJXJXJXJXJXJXJXhX9.5.}.@XcXCXFXKXVXqX^.F.B.p.i.{.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXcX/.PXPXPXPXPXPXPXPXPXPXPXGXGXGXGXGXGXFXFXFXGXPXGXFXFX|.hXGXJXJXJXJXJXJXJXJXJX#XgXFXFXJXPXGXPXGXPXFXFXFXnXnXcXcXcXcXvXvXvXFXFXGXGXGXPXPXPXPXPXgX`.%XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLX} / / / ^ / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / P } +.GXJXGXPXFXPXPXFXU H D D F F Y Y R R E E W W ^ ^ ^ ^ ^ / / / ^ / / / / / ] j.GXJXJXJXJXJXJXJXJXJXGX0XF.P.^.^.P.=X4X4X4X6X=X&Xh.Z k cXJXJXJXJXJXJXJXJXJXXXl b b 4.>XZXZXiXuXrX2X1X1X1X;X>X XIXIXSXAXAXdXsXuXpXsXZXZXiXyX;X`.9 f 6.x.;X;X.X}.c.a n.d.B.a.U p n A A 0.'.A z u r y d d h ;.4.4.4.l.;X>XyXMXMXxXlX).JXJXJXJXoX0.b B m B B n b l l ZXrXuXuXiXiXyX1X1XiXuXyXiXiXyXaXCXwX0XZ : b B m d f d q u y u u 9 m 7.T.Q.1X1XeXrXuXsXZXdXZXdXuX2XT.y.m m z.;.m g s e g n |.zXJXJXJXJXJXJXJXJXJXJXJXoXb 9.}.9XCXVXSXVXVXqX4XG.G.d.p.}.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFX].JXPXPXPXPXPXPXPXPXPXPXPXGXPXPXGXGXGXFXFXFXFXBXGXFXnX).PXPXJXJXJXJXJXJXJXJXJXJX%XXXFXFXPXGXPXGXPXGXFXFXnXnXnXcXcXcXcXcXcXvXFXBXFXFXFXPXPXPXPXPXPX#XnXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX.X~ / / / / ^ / / / / / / / / / / / / ` / / ` / / / / / / / / / / / / ) O.XLXZXrX1X2X1XQ.R.T.T.z.9XIXSXSXAXsXsXuXuXuXuXuXiXiX1X>X>X0.9 m T.;X;Xc.c.x.A 5 X.a.a.U 5 B 9.9.`..X{.[.B r 9 q u b m h h 7.T.;X1XyXyXmXxXzX$X$XJXJXvX).9.b u d m b b 0 0 0 x.uX2XrX2X1X2X2X2X2XrX1XrX3XyXZXIXKXmXOX< A 9.u s d u 9 7 9 9 0 u z.x.R.Q.eXQ.eXuXsXZXZXZXAXAXQ.I.r.I.W.7.;.;.f s e s h j.`.hXJXJXcXlXJXJXJXJXJXJXJX`.m 9.+XxXCXVXVXVXVXpX7X~.L.G.f.MXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXhXJXPXPXPXPXPXPXPXPXPXPXPXPXGXGXGXGXGXGXGXFXFXFXvXvXBXoXvXPXGXJXJXJXJXJXJXJXJXJXJXJX#X|.GXPXPXPXPXPXGXPXFXBXC oX%XhXOXX>X7.g u u b b b 9.9.B n y K 3 6 z B 9. X.X[. .O.N .N 9 d f d 4.l.R.;X3XyXMXbXmXxX-X$XGXJX0.0.B d 9 q b b 0 0 9 0 0 rXrX2XeXQ.Q.eX2X2X2X2X2XuXiXZXUXUXKXlXk 5.5.B 9 q s q ; 7 9 7 c.;XR.1XeXeXQ.eXpXAXSXAXSXSXiXr.w.w.r.T.T.e.f q q y g f B .Xk.j.nXC C %XJXJXJXJXJXgX9.B ].-XxXaXaXpXqXaXpXtX7X~.L.j.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXzXGXPXPXPXPXPXPXPXPXPXPXGXPXPXGXGXPXGXPXGXFXFXFXFXFXFXFXoXJXGXGXJXJXJXJXJXJXJXJXJXJXJXJXC GXPXPXPXPXPXPXGXFXFX].FXPXPXPXoXS %XcXcXcXnXBXFXFXGXPXPXPXPXPX$XXXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXGXU / / / / / / / / / / / / / / / / / / / / / / / / / / / ` / / / / ^ T I JXJXJXJXJXJXGXPXPXBXL R Y H F F F D D D F Y T T T Q R Q E W ^ ^ / ^ ^ ^ ^ ^ / / / / P cXJXJXJXJXJXJXJXJXJXJXO.P.4X4X4X4X7X8XqX8XqX5X*Xk.Z x hXJXJXJXJXJXGX0.V NX.e.T.R.;X;XyXyXxXbXwXwX=XOX+XB 5.b u 0 0 l q 9 7 , , 9 5.rXrXrXeXeXQ.2X2X2X2X2XrXiXZXIXUXPXMXl m 5.7.0 9 9 9 , % 7 , c.;XQ.1XQ.eXQ.Q.R.eXiXiXiXyXr.<.<.<.y.I.Q.1X4.7 q e s g f 9..Xk.j u b M ].JXJXJXBXZ b 5.}.-XjXaXaXaXpXdXaXtX7X^.L.'.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXoXPXPXPXPXPXPXPXPXPXGXGXGXFXFXFXFXGXGXGXPXGXGXGXFXGXFXGX|.GXPXPXJXJXJXJXJXJXJXJXJXJXJXGXXXGXGXGXPXGXFXFXGXFXFX].GXGXPXPXPXBXC %.cXcXvXnXBXFXGXGXGXPXPXPXoXFXoXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX X) ^ / / / / / / / / / / / / ^ ^ / / / / / / / / / / / ` / / / / ( R T I oXJXJXJXJXJXPXGXGXo.R Y Y Y Y Y D D 4 D D F Y Y ! Y Y ! T Q ( ^ ^ ( ( ^ ^ ^ ^ / / / / {.JXJXJXJXJXJXJXJXJXJX|.K.^.4X7X7X8X8X8XqXqX6X*Xk.O.x 0.NXJXJXJXcXS V z x k.7X8XtXyX0X;Xu.T.I.Y.Y.T.Y.e.h c.uXuXrXrXrXQ.Q.Q.rXrXQ.rXeXrXiXyXMX>X7.4.4.4.B B M n 0 < A '.j.g.O.b '.}.B 0XUXUXUXSXVXVXc.l.l.l.I.T.R.R.1X0XyXxXmXmX-X,XXX9.b b d q 9 , , , : ; , , 9 ;XrXrXeXeXeXrX2X2X2XrXuXsXSXUXUXIXMXf h ;.5.m ; ; , ; + % ; ;XR.Q.Q.Q.Q.Q.T.I.t.t.l.r.r.<.<.<.y.T.Q.2X2XeXy e s s s f m j.n 0 b 5.5.B ).oX#Xx l 4.9. XX3X-X@X9XkXb k d b q 0 9 , % , , , , 9 0 5.rXrXrXrXrXrXQ.rXrXuXiXAXIXIXLXyXg s h ;.4.9 % , 9 ; ; % b R.R.W.W.W.E.Y.U.U.u.y.y.t.1.t.Y.Q.Q.rXuXuXdXiXz 8 8 q q d ; 0 Z g.}.|..X}._.A B Z j.}.;X,XMXmXAXSXAXAXAXaXtXH.9XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX`.PXPXPXPXPXPXPXPXPXPXPXGXBXvXzXkXzXnXnXGXFXGXFXFXPXPXPXPXPXPXPXoXJXJXJXJXJXJXJXJXJXJXJXJXJXXXGXFXFXFXFXFXFXFXFXgXFXPXPXPXPXPXPXPXPXPXvXnXBXFXGXGXPXJXPXPXPX].JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX9X~ / / / / / / / / / ^ ^ W W E E E E E E E E E R R ^ / / / ` / / / ( ( _ ( ( ^ _.JXJXJXGXGXOXT Y Y Y F H F F F D D c OXJXJXJXJXJXBXC i J ! ) _ ' ' ' ' i.i.` ` i.X.cXJXJXJXJXJXJXJXJXJXJXzXk.7X8XtXtXaXaXmXjX$X].g.S C Z '.OXOXOX X).Z x M aXmXwXyXR.R.Y.Y.I.I.Y.T.R.Q.;X7.f d 9 w.Y.Y.W.W.E.Q.Q.Q.Q.uXuXuXiXsXyX;X;XT.;X;X;X+XOX{.&Xk. .u S g.].S +XIXUXUXIXLXCXyX,X}.z.7.l.e.r.e.e.e.l.T.c.x.j.|.GXBXj 0 0 q q 9 , , , * , , , , u d z.uXuXrXuXrXrXrX2XrXuXZXZXiXyX7.e s g ;.;.7 7 ; ; ; ; & ; h T.W.W.E.E.W.E.U.U.U.y.y.I.U.W.Q.Q.Q.uXsXAXyX9 8 q q y f d , 0 n 0.x.;X}.j.V x x B 9.}.}.>XyXMXSXSXIXSXdXtXh.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX`.PXPXPXPXPXPXPXPXPXPXGXFXnXzXkXhXoX).oXnXnXBXBXPXPXPXPXPXPXPXPX%XnXJXJXJXJXJXJXJXJXJXJXJXJX|.FXFXFXFXFXFXFXFXzX].PXPXPXPXPXPXPXPXPXPXvXFXFXGXGXGXJXJXPXPXPX|.BXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX'./ ^ / / ^ / / / / / ^ W W W R R Q Q ~ Q ~ Q E E R ^ / / / / / / ^ ` ' _ ` ( / +.PXJXJXPXPXoX! Y H Y F F H Y F F v gXGXJXJXJXJXJXJXvXM 4 L Q ' ' i.p.p.i.i.i.i.i.p. XJXJXJXJXJXJXJXJXJXJXJX_.8XtXaXaXVXVXBXxX%X|.`.S A C +.h.[.'.g.Z n k z mXCXMXeX1XR.R.Y.u.I.Y.W.R.1Xx.j.m s e 9 >.y.y.I.I.l.Y.T.Q.Q.rXyXsXsXyX;XR.T.R.}.;X.X9X0X5X=XZ.O.r z Z j.5.MXSXSXZXZXiX>X;Xx.7.5.7.6.q.6.;.;.4.h f l Z FXJXJXvX0.b 0 0 9 , , , : , , 9 9 u 4.N 5.yXuXuXuXuXQ.2X2XrXuXeX1Xe.q q d h 4.h 9 ; & ; & & ; O % ;.I.Y.E.E.E.E.E.E.U.U.Y.Y.W.Q.Q.eXuXuXdXsX;X; q q e s h 4.z., 0 k B C Z %.]./.k l k n z.c.;X>XZXIXUXSXAXwX+XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX`.PXPXPXPXPXPXPXPXPXPXGXBXcXkX+XS hXGXhX).].vXnXGXPXPXPXPXPXPXPXGX#XJXJXJXJXJXJXJXJXJXJXJXGXzXoXGXGXGXFXFXFXFX%.GXPXPXPXPXPXPXPXPXPXPXGXFXGXGXGXPXPXPXPXPXPXGX).JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXh./ / / / / / / / ^ ^ W W W W E R Q Q ~ ~ ~ ~ ) E E ^ ^ / / / / / ( ' ' ' ' _ W h.PXJXJXGXGXGX+.Y Y H F F Y F F D v PXGXJXJXJXJXJXJXJX].4 G ! { ' i.i.p.i.d.i.i.i.i.}.JXJXJXJXJXJXJXJXJXJXJXXmXKXqXwX{.A r u M b ;XuXiXiXuXyX;X}.z.5.5.6.6.6.;.e 7 9 q < %XJXJXJXJXJXJXcXx b q 0 9 , * , 9 0 u m 7.z.5.r R.eXuXpXuX1XQ.1XQ.R.I.:.h m 6.e.z.x.0 ; % % $ % ; 7 % 7 <.l.U.E.E.E.E.W.E.E.W.Q.Q.Q.rXrXuXsXsXsXf 7 q s f f h ;.9.].NXX>X}.9.C ].FXnXzX+X).S /.cXj.1XyX1X1XW.Y.T.Y.W.R.eXVX@Xz.m b f g ;.h 9 g r.y.r.r.r.r.Y.Q.ZXAXyX;XR.l.l.e.l.x.}..XyXHXKXmX@Xg.n 0 u b 4.;XeX2X1X;XR.x.z.5.5.6.;.;.e 7 ; q g h `.JXJXJXJXJXJXkX9.T.z.e.d , , , 9 u m 5.j.z.j.A q l.l.R.eX;XR.T.T.I.Y.W.;XT.T.;XyX>Xj.* $ $ $ & ; ; % 7 q r.y.U.Y.E.E.E.Q.Q.Q.Q.Q.eXrXuXpXsXsXyX, 7 s f 4.4.f h v DXJXJXJXJXJXJXhXN k 0 k b Z j.c.;X>XZXZXSXAX|.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX$XcXPXPXPXPXPXPXPXPXPXPXFXcXkX).FXGXGXGXGXPXGX].vXFXPXPXPXPXPXPXPXGX+XGXJXJXJXJXJXJXJXJXJXJXGXJX%XX}.}.'.OXJXJXJXJXJXHXGX`.;XR.1XW.W.W.W.Q.Q.eXmX0X'.B d d d s ;.;.;.- w.y.y.y.y.y.l.yXVXdX0X;XT.l.e.r.e.z.T.c.;XyXKXCX,Xz.B u 9 0 u T.1X1XR.R.T.l.7.5.4.4.h g q ; ; 7 e h 4.,XLXJXJXJXJX0.e.e.e.7.4.q , , 9 u m 5.z.z.}.}.y l.l.l.l.T.c.y.y.W.R.2X2XeXyXyXiXyXA & $ * & ; 7 9 o & 7 -.u.Y.W.E.Q.Q.Q.Q.Q.Q.^.rXuXpXuXuXeXl.l.u e f ;.;.f d /.JXJXJXJXJXJXJX).l 1 k n 0.9.x.}.;XyXZXAXSXAX].JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].PXPXPXPXPXPXPXPXPXPXGXBXcXhX].GXPXGXPXGXPXPX].vXFXPXPXPXPXPXPXPXGX+XGXJXJXJXJXJXJXJXJXJXJXJXJXPX].FXFXFXBX).nXFXFXBXFXGXPXPXPXPXPXPXPXPXPXPXPXPXPXJXPXPXPXPXPXPXPXFX).GXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX+X) / / / / ^ ^ W W W W E R R R R T Q Q ~ [ [ [ [ [ [ { _ ( ` / / ` ` i.' ` ` _ ) |.JXJXPXGXPXoX! F F F F Y Y H F F .GXJXJXJXJXJXJXJXJXlX6 K ! [ { p.' i.p.d.d.d.p.p.`.JXJXJXJXJXJXJXJXJXJXJX$XbXUXUXUXIXLXiXiXyX1X>X;X0XmX_.JXJXJXJXJXHXPXzX9.R.2XQ.W.W.Q.Q.eXaXAX0Xg.M d f s d -.;.;.8 I.U.U.U.y.U.y.yXSXpX1Xc.l.6.6.6.6.6.7.j.x.;XMXsX>Xj.5.q 9 , 9 ;X1X3XR.T.c.z.z.5.m m g e ; $ ; 7 e s -.9.GXJXJXJX|.5.6.7.5.4.4.b q , & 9 m 5.7.j.x.h.q l.Y.l.I.I.y.y.Y.R.1X2XZXiXZXZXZXyXl ; $ & & ; 7 % $ $ & 8 t.W.E.Q.Q.Q.Q.Q.Q.rXuXrXuXuXuX3XT.l.l.c.u g ;.h e b vXJXJXJXJXJXJXJXn < u b 5.z.x.}.}.1XyXCXAXAXAX'.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].PXPXPXPXPXPXPXPXPXGXFXBXzX%X#XGXGXGXGXPXGXGX#XgXBXGXPXPXPXPXPXPXPX%XvXJXJXJXJXJXJXJXJXGXGXJXJXJXoXnXBXnXnX|.FXBXnXBXBXFXPXPXPXPXPXPXGXGXPXPXPXGXPXJXPXPXPXPXPXPXPXPXGX).FXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXNXU / / ^ / ^ ^ W W E R R R T R T R Q ) Q Q Q [ [ [ { { ' _ ' ' ` ` ` ` ` ' ` ' _ @.gXJXJXJXcX| T H F F F H F H H F D @XJXJXJXJXJXJXJXJXGXM p L ] [ { i.i.i.p.d.p.d.s.f.FXJXJXJXJXJXJXJXJXJXJX#XbXUXUXUXIXZXiXuXrXyXyXyXsXpX.XhXJXJXJXJXHXHXHXO.T.2X2XQ.Q.Q.2XiXAXSX3X9.m f f d g h ;.;.e E.E.U.U.U.I.r.CXSXsX;Xx.q.6.;.4.6.m , < 5.c.3XyX;Xz.5.q , $ , >X1X1XR.T.c.z.7.N b d s 7 $ & 7 e s ;.;.;.).JXJXBXB ;.4.4.4.;.m e e q , 9 h m 5.5.0.O.d Y.T.T.R.W.Y.T.Y.W.2XuXZXZXSXIXZXyX; ; ; $ & ; ; O O . $ 7 i E.E.Q.Q.Q.Q.uXrXrXuXuXuXuX1Xq.>.r.l.T.R.s ;.g e S JXJXJXJXJXJXJXgX0 r b 5.x.c.c.R.;X1XiXNXSXAXAXh.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFXXXPXPXPXPXPXPXPXGXFXFXBXnXkXoXnXGXPXGXPXGXPXPXnX].nXFXGXPXPXPXPXPXPXBX].JXJXJXJXnXXX.h ;.h u ; < f 7.;X1XR.l.4.q ; $ : }.>X1X;X;Xx.e.5.b u 7 7 & 7 8 e -.;.6.6.6.u vXJX0.d h h ;.m e e e b e e , q 4.m b b k 4.I.T.R.Q.W.T.W.W.Q.eXuXZXIXIXIXiX9.7 7 & $ $ & ; o . X . $ 7 q.W.Q.Q.Q.Q.Q.eXeXeXeXyXR.:.;.,.r.I.T.R.h ;.s m `.JXJXJXJXJXJXJXV 9 b 4.x.}.T.;X;X1XrXMXSXSXSXAX`.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX].JXPXPXPXPXPXGXGXFXnXnXvXcXkXXXFXJXGXJXJXJXJXPXGX).cXnXBXGXPXPXPXPXPXPXV JXJXGXkXC V ].].nXnXnXoXx V S kXGXFXBXnXvXzXcXcXnXFXFXGXFXGXGXGXBXFXFXFXFXFXPXPXPXPXPXPXPXPXPXPXPXGX].PXGXPXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXA / / / / / ^ W W E R R Y R Y F Y T T T T T ~ Q [ _ [ _ { ' ' ' _ ' ' ' i.i.i.i.d.i.B JX}.! T Y J H H J H F H H Y H {.GXJXJXJXJXJXJXJXJXJXZ K L ] [ { ' ' p.p.p.d.p.i.j.CXJXJXJXJXJXJXJXJXJXX}.b DXJXJXJXJXJXJXJXj.2XuXuXrXrXrXrXyXeX;X7.h d s s s g h ;.h E.U.u.u.I.y.r.yXuX;Xc.<.>.:.h 4.h q , , d 7.T.1XR.l.m q ; + : 0 @X.X}.9.5.B u , ; 7 7 7 e -.:.:.>.q.l.e.s |.JXb s f h h f f e e e f e m m m b f l , r.T.1XeX3X3XQ.R.Q.2XrXuXsXSXSXZX>Xq 8 8 7 7 $ ; ; . . o X . O 7 W.Q.R.W.T.T.l.e.q.>.h e g :.<.l.T.Q.R.y -.e h ).JXJXJXJXJXJXkX9 l 9.x.;X;X;X;X1XeXiXZXLXIXSXCX|.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX#XgXPXPXPXPXPXPXPXGXFXvXcXzXkXgX+XvXJXPXJXJXJXJXGXPX].zXcXvXFXPXPXPXPXPXPXcX).XXoX%XGXGXFXnXnXnXnXoX%.nXGXGXGXFXBXvXzXkXhXkXzXcXBXBXFXFXGXGXnXnXnXnXBXFXGXGXPXPXPXPXPXPXPXPXPXPXvXoXPXGXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX XJ / / / / / ^ ^ W W E R Y R Y F F J D D D D J ~ Q _ _ _ _ _ ` ' ' ' i.i.i.i.p.d.d.U Z I ! J J H H Y H H H H H Y K jXJXJXJXJXJXJXJXJXJXJXzXM K L ] ) _ ' ' i.i.i.i.i.U cXJXJXJXJXJXJXJXJXJXGX XUXIXIXZXsXiXuXrXuXuXiXyX;X}.b ).JXJXJXJXJXJXGXj.iXsXsXuXeX2XeXeX1X1Xc.5.h g s s s f s q.E.U.U.U.y.y.y.T.1XR.x.<.<.;.>.6.;.y 9 ; h e.T.1XR.l.4.q * O % : < B B l 9 , ; 7 8 8 e g -.:.:.>.w.l.l.l.h XJXb q u s b e e q e b e m ;.;.m f d b % x.T.yXeXeXeXeX1X1XeXuXiXZXZXsXyX5.8 8 e 8 8 7 & ; X o o + O o o 7.T.T.5.q & & 7 7 ; 8 s -.:.<.r.Y.Q.R.8 s 7 s 9.GXJXJXJXJXJXC , m `.>X>X>X>XyXuXZXZXZXIXIXSXOXFXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFX`.PXPXPXPXPXPXPXPXGXBXnXcXkXkXkX.6.7.4.u d u 4.l.T.R.R.l.4.q o % + % : 9 0 + 8 8 7 7 q e -.-.:.<.<.w.w.r.r.q.6.oXJXz 7 9 q q e q q e e f -.m ;.m e b b u T.;XmXwXpXuXyXyXeXuXuXiXsXyXeXc.7 7 8 e -.g e & $ % X o O o O $ % 0 O o O $ $ & ; 7 8 g ;.>.1.l.T.R.T.9 ; 7 e 5.+XJXJXJXJX$Xk q 9.>XyXyXiXiXuXiXZXLXPXUXIXSX XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXXXnXPXPXPXPXPXPXPXPXGXFXnXcXzXkXcXkX/.#XzXcXkX.q.7.4.5.6.6.q.I.T.R.T.l.4.7 o # # # , d 9.n 8 7 7 8 e g -.,.<.w.r.w.1.6.6.w.6.'.kXk & 7 9 9 8 8 9 q e e ;.e m -.m f x 9.c.;XwXaXaXsXZXiXiXuXiXiXyX;Xx.9 7 7 e -.-.-.g e o $ X X X o X + $ ; O o o $ & ; 7 e h :.6.l.l.I.T.T.f $ & 7 8 4.j.JXJXJXzXS ; m }.yXNXNXZXZXiXZXLXLXUXUXIX XGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].PXPXPXPXPXPXPXPXPXGXFXBXcXkXgXcXBXBXkX#XoX+X+X].gXGXGXzXoXcXBXPXPXPXPXPXPXPXPXPX].BXnXnXnXnXnXvXx cXGXGXPXPXPXPXoXV hXhXgXhX.h g s s e Q.Q.E.E.E.Y.U.Y.E.W.E.U.y.1.q.q.l.7.q.l.r.l.T.R.T.l.e.h % % : : , b b 9.V 7 7 8 e -.>.w.w.r.r.r.w.q.<.w.<.6.5.).0 % % ; 7 , ; ; 9 e e e -.;.;.;.h z `.x.c.5X8XpXpXmXyXyXyXlX>X}.b & ; 7 7 s :.>.:.:.e % O O o + + o o x.;XQ.h 7 s h -.:.w.r.I.T.R.Q.eX3X3Xj.; ; ; 8 m ).JXJXcXC : q 9..XMXZXZXZXZXZXSXZXZXSXZX.XnXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].PXPXPXPXPXPXPXPXPXPXGXBXcX].C %XcXnXBXBXBXcXhXhX].#X+X%XC %XFXPXPXPXPXPXPXPXPXPXoXnXnXvXvXvXnXvX%.oXGXPXPXPXPXPXPXcX%.).hXkXkX`.PXGXGXnXkX.1.w.<.-.8 o O + + % $ 9.LXZXyXR.q.r.l.I.T.W.W.W.1XeXuXZXAXAXVX*X, & 7 f ].JXlXx O , d 7.}.yXZXZXZXZXZXZXuXrXrXeX|.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].PXPXPXPXPXPXPXPXPXPXGXFXFX).cX%.+XcXcXvXcXkXhXoXV GXFXgXgXFXPXPXPXPXPXPXPXPXPXGX].bXbXnXnXvXnXnX#X_.GXPXPXPXPXPXPXPXPX].kXkXgXoXGXGXGXJXGXPXPXGXcX.w.r.r.r.y.r.y.r.y.r.r.w.<.<.; , : % % + O O O 7 d g -.;.>.>.4.h u u n : A j.9.5.N u 9 , & $ o $ O & 7 8 s >.r.r.r.>.s $ + + $ % 0 JXUXUXZX1X;XR.R.Q.Q.Q.1XeXuXsXZXIXIXIXAXaX!.9 ; u XXgXk $ $ q m 9.;XMXCXZXZXZXiXeX1XR.2X.XvXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX|.PXPXPXPXPXPXPXPXPXPXPXPXPXGXoXPX#X].kXkXkXhX|.`.PXPXPXPXPXPXPXPXPXPXPXPXPXPXPXFX].cXnXnXvXnXnXnXnX%.FXPXPXPXPXPXPXPXPX].kXzX].BXGXPXPXGXXX).|.+XvXcXkXzXvXnXFXGXPXPXPXPXPXGX%X].kXFXgXzXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXkXK ^ ( ^ ^ ^ W E Y D |.JXJXJXJXJXJXJXJX_.[ P J 4 H Q _ i.p.p.d.d.S.S.S.S.S.S.S.S.S.d.i 4 i i p K G K K L U P U O.JXJXJXJXJXJXJXJXJXJXS p U [ a.[ [ a.[ s.s.s.p.d.d.h.JXJXJXJXJXJXJXJXJXJXJXJX`.sXuXsXuXuXuXrXuXuXrX1X;Xe.m q 9 0 ].DX/.yXyXeXQ.T.U.U.I.y.I.Q.eXT.7.h f s s e e u Q.Q.Q.E.E.Y.E.E.E.E.E.E.U.t.1.<.1.1.w.I.W.Q.R.6.- . o % : z V z l m m ;.>.6.w.w.r.I.I.r.I.I.y.I.I.y.I.1.1.<.9 , : % + + O X + q e -.;.:.4.>.4.f 9 , 9 0 j V z z 0 , % + O O & & $ O ; 8 e <.w.r.w.,.e & X % % : b PXUXUXIXZXrXQ.eXeXQ.eXeXrXiXZXSXIXIXSXAXpX5X; ; l nXn % $ % 9 d 5.}.yXyXiXZXZXuXyX1XW.2X;XhXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXoXPXPXPXPXPXPXPXPXPXPXPXPXPXgX%XJXJX.>.<.<.r.I.Q.W.W.I.r.1.>.; 7 9 7 % + # q g -.g g ;.h f q 7 + % , 9 9 0 x l 8 q s g d 9 , $ O o & 7 e :.:.:.:.g q 7 O % , + q }.MXSXIXIXAXsXuXuXrXrXrXuXsXSXSXSXIXAXaX5X% % 7 f 4.4.9 * 7 7 q h 5.e.c.1XiXAXZXsXuX2XQ.uXOXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXvXXXPXPXPXPXPXPXPXPXPXPXPXGXnX|.JXJXJXJXJXJX.>.>.<.1XZX0Xc.6.d s g g g s e 4.I.Y.I.r.<.,.E.E.Q.Q.E.E.U.U.U.U.U.U.U.r.w.q.* o . . X % % m >XZXZXyXeXR.T.T.I.w.<.g g h >.<.T.2X2XQ.T.I.w.>.e 9 e e q , ; e s s e d s e q 8 & + % ; 9 9 # ; e s 7 u b b u 0 & O o $ 7 e g -.-.g e 8 8 & % % & q 5.;XMXZXZXZXdXsXuXrXeXrXuXAXIXIXSXSXdXaX> O q g ;.7.x.1X0 7 9 q d h 6.x.;XuXZXZXAXZXrXeXuX0XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFX%.JXPXPXPXPXPXPXPXPXPXPXFXnXkXXXJXJXJXJXJXJXGXXXPXPXPXPXPXGXGXPXGXGXPXGXGXPXGXGXFXGXgXk %.].gXnXvXcX.uXiX1Xc.4.s s g g g g e s u 7 h <.;.g 1.Q.Q.E.E.E.E.E.E.u.u.t.t.<.>.m $ o . o ; 9 * 5.MXLXZXMXyX;XT.I.l.q.:.s 8 e g >.T.1XeXQ.R.T.q.6.e , s e e q q e e e s e e q 7 ; % + % * 7 : % e g 9 n l 0 7 , : % O o ; 7 q q s g e q q 7 $ O , % 9 d 4.l.;X1XrXeXQ.Q.Q.Q.2XuXsXSXIXIXVXaXN 7 8 e h 4.e.T.1X9.9 q 9 s d 4.7.;XrXZXAXAXAXuXrXuX0XFXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXcX%.GXPXPXPXPXPXPXPXPXPXPXFXFXcX.>.y o o ; 7 ; * 9 }.yXiXiXeXR.T.l.q.>.g 7 & & 7 s 6.R.1X1XR.l.7.;.q % q q q 8 8 e e e e e q 8 7 $ . + # % ; O e -.s 0.|.}.9.5.5.7.e.z.z.e.z.9.9.B d q 8 8 ; o , ).k ; s 4.6.w.l.I.I.I.I.I.I.T.;XyXZXCX,XB h g s s f ;.e.;X;XyXc.q d q 9 u m 7.}.yXAXSXAXAXsXrXsXSXcXJXJXJXJXJXJXJXJXJXJXJXJXJXJXzX%.PXPXPXPXPXPXPXPXPXPXGXFXBXbXcXoXhXJXJXJXJXJXPX+XkXPXPXPXPXPXGXGXGXGXGXPXPXPXHXFXzX%.FXPXPXPXPXPXPXPXPXPXzX#X).`.Z OXX.Q %XBXoXJXJXJXJXGXPXBXGXJXJXkX#XzXkXkXkXkXkXhXkXkXcXBXPXPX+XGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXo.E W W ^ ^ ^ W +.GXnXo.! [ U o.$XGXJXJXJX-X@.J 4 i i G 3 L ] m.s.M.B.B.B.d.d.S.d.d.d.d.d.S.d.S.p a I I } I .I o.o.+._.JXJXJXJXJXJXGXJXS i U m.F.C.C.F.F.F.G.G.G.G.G.G.j.KXJXJXJXJXJXJXJXJX+XUXSXZXuXrXrX^.~.F.b.I N M m 4.4.m e 0 , # l 0 q 0 , 7 , 7 4.2XyX1XI.q.;.-.g e e 8 8 8 ; O X # lXx l.Q.Q.Q.Q.E.U.u.t.1.,.:.:.:.>.:.-.7 ; 7 7 ; & $ m x.;X;X;XR.x.l.>.f ; $ O o O & 9 4.c.R.T.e.5.b 9 9 q 7 7 8 8 q q q e e q 7 & . X + + # + e ,.-.n 9XyXlX>X;X;X1X;X1X;X;X;X;X>XyX>Xz.f 7 $ O 0 FX.g g h -.g g g 5.c.;XZXZXx.d d u 9 9 d B }.yXCXSXSXAXdXuXsXSXkXJXJXJXJXJXJXJXJXJXJXJXJXJXJX).PXPXPXPXPXPXPXPXPXPXPXPXFXnXcXkXXXzXJXJXJXJXGXGX].GXPXGXPXPXPXGXHXPXHXHXnXnXPXHXnX].PXPXPXPXPXPXPXPXPXPXPXPXPXGX-XU E ~ k.zXnXS gXgX.<.6.>.h h ;.6.6.;.7.e.;XZXIXIX4.0 u u u 0 u 9..XMXKXIXIXIXAXsXdXIXkXJXJXJXJXJXJXJXJXJXJXJXJXhXzXPXPXPXPXPXPXPXPXPXPXPXPXPXGXFXvXkX#XgXGXPXGXGXPXvX+XJXPXPXPXPXPXPXPXPXJXPX-XwX%XFXcX].nXPXPXPXPXPXPXPXPXjXb.~ ) ] -XFX].kXhXkX).PXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXvXS k +XBXGXGXPXXXzXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX#XG / / ^ ^ ^ W W R 6 ! K K p p p p | FXGXGXGX| Q J G G G 4 i 2 U a.a.m.M.B.B.B.S.B.S.S.d.d.S.S.S.S.G.G.G.3 a a a I } } .O.g.JXJXJXJXJXJXJXGXS 2 K U m.C.F.F.G.L.G.G.~.G.~.L.f.GXJXJXJXJXJXJXJX.;.f s 9 ].JXNX5.Y.W.Y.y.w.<.-.g g g s g s -.;.4.;.h w 8 ; & O O 7 ; & 8 m e 7 o o o $ & 7 e e -.-.e 7 & ; 7 q e d s d q ; ; 7 8 e e 8 7 $ O * * ; g :.:.-.-.q >XMXiXsXsXuXsXsXsXZXsXZXZXSXIXIXIXIXIXLX0 s 0.JXJX< . & 8 g :.,.<.<.,.<.,.<.<.l.l.l.7.q.6.7.j.j.}.;XyXZXUXSX9 9 u u u 0 n g.OXxXIXUXUXUXuXsXdXCXgXJXJXJXJXJXJXJXJXJXJXJXFXoXPXPXPXPXPXPXPXPXPXPXPXPXGXGXGXnXcXkXgXoXGXGXGXPXXJXJXJXJXJXJXJX#XUXSXZXdXsXdXAXAXaX*Xv. .5.5.h 4.4.h d u 9 % 0 0 j 0 0 0 # 6.Y.W.Q.W.Y.U.y.y.r.r.w.w.w.>.h s 0.JXJX5.r.U.y.r.:.-.-.e e s s e g e.T.R.R.}.x.d 7 & O O & * ; ; % , : O o $ 8 e -.-.:.:.:.h e 7 7 8 8 q e e q 9 & & 7 8 e e 8 7 o * X q :.-.-.-.g g q >XZXiXiXuXuXiXsXZXAXSXZXSXIXIXIXIXIXIXUX>X, j nXhX# o 7 8 g -.:.,.,.<.,.,.<.l.I.T.T.l.l.x.x.h.}.>XiXLXIXUXg.& , y u u k B _.@XmXKXUXUXSXsXsXAX9XvXJXJXJXJXJXJXJXJXJXJXJX|.PXPXPXPXPXPXPXPXPXPXPXPXFXnXFXFXnXcXkXgX].PXPXGX).gXPXPXPXPXPXPXPXPXPXPXLXPXgXFXOXwXOXkX%X].PXPXBXY o.@.^ T &XBXPXPXPXHXBX).gXhXoXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXoXPXPXPXPXGXS GXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXPX0XD / ^ / / / ^ W E T | %.a K K p 6 p p O.FXBX| Q Q ! L G 4 4 3 3 2 b.m.N.C.S.F.S.S.S.S.S.S.S.S.S.S.G.G.G.L.L.a 5 a p K a N . .`.JXJXJXJXJXJXJX].= 2 K U a.m.C.F.G.L.G.G.G.~.~.~.].JXJXJXJXJXJXLX].UXSXZXZXsXAXIXIXKXmX*Xx.5.5.;.;.h h h d 0 , 0 0 u u 0 0 7 r.U.E.W.W.Y.U.y.y.r.y.y.I.y.r.>.s r DXgXj <.r.w.,.:.-.e e e s s f ;XyXrXyXyXyXyXyXl & $ o O $ % & 7 9 n $ & 8 e -.:.,.1.r.6.;.e q q 8 q q d q 9 7 & % ; 8 e e e 7 $ * u 6.6.:.-.-.s e 8 ;XuXuXuXuXuXiXZXZXZXAXSXSXSXSXIXIXIXIXIXiXm 7 < k O o 7 e e e -.-.-.:.:.>.1.l.l.T.T.T.v.c.v.k.Z.5XmXIXIX9X0 % ; 9 u l x O.'.@XmXSXIXIXsXuXsXAXoXJXJXJXJXJXJXJXJXJXJXJXhX#XPXPXPXPXPXPXPXPXPXPXPXBXcXcXnXnXvXkXgXgX].PXGX].FXPXPXPXPXPXPXPXPXPXPXFXOX] R -XjX.X*XkXkXS GXPXnXE ( T {.FXPXLXPXPXPXFXnX).gXhX$X%XPXPXPXPXPXPXPXPXPXPXPXPXGXGXPXPXPXPXPXPXGXPXPXoXPXPXPXPXPX$XvXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX{.H / / / / ^ ^ ^ R Y | FX%Xv I p 4 t t a O.C [ _ ! ! L G G i 4 3 = p n.V.B.F.S.F.F.C.S.S.F.S.S.G.S.G.G.G.~.G.G.Z.a t a I v . .Z FXHXGXJXJXJXPXoX= = p L ] m.M.B.F.G.G.G.G.G.~.^.{.JXJXJXJXJXJXJXoXCXSXSXZXZXSXUXUXUXKX0X;Xj.5.>.h h h f u 9 , 0 0 d u j 0 q u.I.Y.W.W.Y.U.r.r.r.y.I.U.I.r.>.g 7 : l < 6.r.w.,.:.-.e e s g m ZXZXZXsXZXZXZXZXyX,X, $ o X O O % % $ $ ; q g -.:.<.r.y.y.w.-.e 8 7 7 8 q 9 7 ; ; X $ % 8 e -.w 7 & $ h q.>.;.-.e e 8 7 0.iXuXrXeX2X1X2XeXrXiXAXZXAXZXSXZXsXZXZXT.6.f ; $ o o 7 e e -.-.-.-.,.<.1.l.I.T.T.T.z.v.j. .H.J.=X0XyXj.* O & 9 9 l m 0.].OX-XwXCXCXAXuXuXsXSX0.JXJXJXJXJXJXJXJXGXJXJX).PXPXPXPXPXPXPXPXPXPXFXBXcXzXkXvXcXcXkXgXXx.z.4.h s d d r > 0 z l b d u < ;.I.y.U.W.W.E.U.y.y.y.y.y.y.U.y.<.h ; O 1 1 h r.y.w.<.:.g g -.u yXSXIXIXIXIXSXZXiXiX>Xb o . o O $ O O $ q g ;.:.:.<.r.y.r.y.6.g 8 7 7 ; & ; & + $ o % O O 8 e e 8 7 & & h e.>.;.g e 8 7 & b iXuXrX2XW.T.T.T.T.1XrXsXiXiXiXyXuXuX2XT.I.r.h o $ o ; e -.-.-.:.:.<.1.I.Y.T.R.R.T.l.5.N f.P.J.C.v.C + o O % < u b B c.>X>X3X>X1X2XrXrXuXAXSXC JXJXJXJXJXJXJXJXPXGXzXXXPXPXPXPXPXPXPXPXPXFXnXzXkXkXkXcXzXkXgXXv.z.4.m d 9 q 9 5 5.9.4.b b u , 6.l.q.I.W.E.Y.I.y.r.y.U.y.y.U.y.<.g ; o * 1 q y.I.y.1.:.g g ;.5.IXIXUXUXUXUXUXIXZXyX>X}.. . o o O O $ 8 ;.:.w.<.<.1.r.r.r.w.:.e 7 ; $ O O O O O O $ O O O ; 7 e 7 ; & ; h 7.4.f e ; * ; ; 9 MXyX2XR.T.r.r.r.q.e.T.1XeXyX;X1X;X1XR.R.Q.T.r.q . o & e g :.,.:.,.1.l.Y.Y.W.Q.R.T.l.m m f.L.G.S.h.JXn O * u 9.[..X;XyXyX1XR.R.1XrXrXsXAX X].JXJXJXJXJXJXJXJXPXGX`.PXPXPXPXPXPXPXPXPXPXnXcXzXkXkXcXzXzXkXgXgX%X%.GX].PXPXPXPXFXZ.Q R U +.{.aXaXaXaXaXaXqXaXqXaXqX{.S GXxXE ^ Y T OXPXPXPXPXPXJXBX).zXvXnXBX%X].PXPXPXPXPXPXPXPXGXcXgXgXgXzXFXGXGXGXGXGXvXC GXGXJXPXPXzX.w.w.1.w.1.1.w.1.<.;.q 7 $ o 0 1 + o X O O , , v -Xv.q 7 & ; * f 4.h s ; y 5.5.m d +X1X1XT.l.q.6.>.:.4.;.6.z.c.T.T.I.T.Y.W.W.Y.y.-.. o $ 8 -.:.,.,.1.I.Y.W.Q.R.W.R.c.z.l.N b.L.G.S.h.DXV . : z g.-XxXmXyXyXeX1XQ.Q.2XrXuXsXSXz FXJXJXJXJXJXJXJXJXGXPX].PXPXPXPXPXPXPXPXPXPXnXcXkXzXzXzXcXzXgXgX.d 8 > _.JX+.'.oXb b % m 4.e.2X2XW.T.Y.Y.U.y.y.y.y.U.r.<.s ; o o + y I.U.r.<.:.-.-.h 9.mXSXSXIXUXIXLXiXyX;Xc.b + . . o O & q -.<.<.w.<.,.<.w.1.>.;.e 8 $ % V kXJX Xk % + ; 7 u wXwXiXMXz & & & & f d 9 9 j.z.5.m f q z.R.T.l.w.<.,.;.g h -.;.;.6.w.r.r.I.Y.Y.U.r.e o o o 7 -.6.<.w.r.T.W.Q.R.R.R.T.l.r.>.a f.^.G.G.j.JXj X n oX.XyXKXSXiXuX2X2XQ.Q.eXrXsXAX}.|.JXJXJXJXJXJXJXJXJXPXGX].PXPXPXPXPXPXPXPXPXPXBXcXzXzXzXzXcXzXhXgXXc.z.z.4.h u , /.JX_.+.O.l 0 ; d f 1XuXrX1XW.T.W.Y.U.y.U.U.I.r.>.e & o o X l.W.Y.I.1.<.:.,.<.:.z.;XyXsXZXiX1X;Xc.e.d , 9 o . . % e -.>.w.<.-.-.g g -.:.:.g 8 ; % V JXJXJXJXnX1 ; ; * u aXaXZXZXiX0 & & $ ; s ; 5.7.z.z.4.b q 7 4.I.r.w.1.6.:.g h ;.;.;.:.<.r.r.y.y.U.y.w.7 . o o & e 6.q.r.T.Q.1XQ.R.R.l.q.q.:.y .H.^.~.G.f.vX: < `.9XDXSXIXSXiXuX2XeXQ.eXrXuXsXyXA JXJXJXJXJXJXJXJXJXJXGXGXXXPXPXPXPXPXPXPXPXPXPXFXvXcXcXzXzXzXzXkXgX%XS hX%.BXFXFXGX] Q -XHX$X*X&X XPXGXnXvX%X[.&X6XwXqXqXqXqXqX*XF Y Y R Y Y R R ! -XGXBXcXzXC kXFXBXBXoXJXPXPXPXPXPXPXcXk kXkX%.].vXnXGXGXPXXX%XcXvXnXvX|.nXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXgXb.C.C.C.C.C.o.C.C.C.C.C.M.C.C.B.C.C.N.b.Z.gXPXGXPXGXHXPXPXJXJXGXPXHXPXPXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXhXi.` / / / / ^ ^ ^ ^ _ Q _ _ _ [ ~ .PXPXGX-XL L L K i i p p p i t - - 2 5 2 5 2 ..V.J.L.L.L.P.P.^.^.~.~.~.~.~.L.G.G.G.F.F.J.b.5 t a N JXJXJXPXGXC = 2 4 G L P ] ] [ [ s.d.S.F.G.L.L.~.f.|.JXJXJXJXJX9X@XZXsXiXSXIXIXIXZXyX;Xc.z.l.7.4.d 9 n JXS O.k d 0 : 7 b sXZXsXrX1XW.W.W.U.y.U.I.r.q.>.q & o . ; R.Q.W.U.r.1.>.,.<.<.<.4.z.;X;XT.x.e.4.9 % , 7 % X $ e g :.w.<.:.e 7 7 8 e q e 8 & $ $ , 0.BXJXvXx ; 7 0 5.y aXAXAXAXZX}.& % $ o O , B 7.7.7.4.h s q ; e r.1.w.6.:.-.h h -.:.>.<.r.r.r.y.U.y.w.$ o $ $ % 9 4.l.;X1X1X1X1XR.l.<.>.>.s a f.K.7X^.L.[.`.% l XXNXIXIXIXAXpXrX2X2X2XQ.uXuXyXg.GXJXJXJXJXJXJXJXJXJXJXGXPXoXPXPXPXPXPXPXPXPXPXGXBXvXcXcXzXcXzXzXkXgX%XC hX).cXnXBXBX! R ..bX{.{.*X{.JXFXvXvXkXkXhX[.&XqXqXwXqXqXOXo.Y Y Y Y Y Y R R R b.BXcXzXcX).%XnXnX|.GXPXPXPXPXPXGXoXj kXkXS hXvXGXGXPXPXJXS XX#XoXhXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXBX+.J.C.C.C.C.C.C.C.B.C.B.C.C.C.M.C.M.M.C.M.C.$.o.-XPXPXGXGXGXJXJXGXPXHXGXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXb./ ` / / / / / ( ( ( ( _ _ _ _ [ U #XBXoXkX| K K K i a p p p a i 3 = = = = - 5 5 V.J.J.P.P.^.^.^.^.^.^.^.^.~.G.G.G.S.S.S.F.J.X.5 t N JXJXJXHXGX%X5 5 t G K P ] ] [ [ s.M.C.G.G.L.L.~.L.N JXJXJXJXJXLX$X>XsXeXSXUXIXSXsX3X;Xc.l.l.z.7.h d z #XA x u d q & , }.UXUXZXiX2XQ.Q.T.Y.I.r.r.w.6.;.8 & o o 5.rXeXQ.Y.l.r.<.,.<.<.<.<.;.f g f g e q % % : , % & e -.:.r.w.:.e 7 $ & & ; ; & $ $ O $ & 7 n vX0 ; ; q 5.4.u .XyXZXZXsX;X0 O O o o , d 4.7.6.4.h e 8 ; $ w.w.1.w.:.;.b b h ;.:.<.r.r.y.I.y.y.w.o $ & & & ; m c.1XuXuXrX1XT.:.>.,.<.s a f.K.^.^.^.v.0 o q }.yXZXSXAXsXrX2X2XQ.2XQ.rX1X].JXJXJXJXJXJXJXJXJXJXJXJXPXGXXXPXPXPXPXPXPXPXPXPXGXBXvXvXcXcXcXkXkXkXhX|.].gX%XoXcXbXvXJ T Q L {.*X*X*XFXnXvXcXcXkXkXzXhX+.*X5X6XOXGXPXo.Y Y Y Y Y T T T T U cXcXcXzX].gXnX).vXPXPXPXPXGXvXV %.kX 6 a K.J.P.P.P.^.4X4X7X7X^.^.~.G.G.G.S.S.S.S.S.G.V.K 6 gXJXJXJXJXGXk - i p G L P ! ] a.a.B.B.S.G.G.L.G.G.k.LXJXJXJXJXJXJXXIXSXSXuXeXR.W.Y.Y.v.l.r.q.6.h q $ $ o y 1XrXQ.T.Y.l.1.<.<.<.<.<.,.-.g g e e g 8 & O O & q -.:.<.r.,.g 7 $ O o o o o o O O & ; ; ; ; z ; 7 & ;.q.5.d t }.iXuXiXc.% $ o o o . ; d 4.4.4.s q 7 & & r.y.r.r.<.9.}.}.j.4.;.w.r.r.U.y.y.r.6.o O & & & & u x.yXZXiXrXR.>.-.w.w.w.-.a f.H.^.7X8Xk.o o % u 9.1XsXsXrXQ.Q.Q.Q.Q.eXR.OXLXJXJXJXJXJXJXJXJXJXJXJXJXPXGXoXPXPXPXPXPXPXPXPXGXFXBXvXcXcXcXcXzXkXhXgXC gXgXhX).zXzXcXL T T ~ J [.*X*XzXvXvXcXcXzXzXzX).oXh.5XOXGXPXHXGXk.J H H Y Y Y H Y R @XcXcXkXzX].cX%.`.PXPXPXGXFX).|.kXkX%.zXFXPXPXPXPXPXPXPXPXPX].+XGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXPXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXvX..C.C.C.C.C.M.C.C.M.C.M.M.M.M.M.$.C.A.$.C.$.C.C.$.C.$._.FXGXHXJXJXJXJXGXPXPXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX9X` / / ` / / / / / _ ( ( _ ' ' _ ] L U I I I I p 3 G i 3 3 p a K a p = = = = = 5 5 } A.P.L.^.^.4X7X7X7X7X^.^.~.G.F.S.d.d.d.S.F.J.F.V.o._.kXJXJXFX/.= 5 p K L U ] [ [ a.s.B.C.F.G.G.G.~.f.JXJXJXJXJXJXJXLXzXb IXIXIXAXiX1X;XT.l.w.q.6.>.h s q , XOXl 9 0 & B iXsXsXuXeXQ.T.T.1X-X X7.6.4.s 8 & $ O $ x.uXrXQ.T.I.I.1.<.<.,.,.:.-.-.-.:.:.-.-.8 7 7 q e :.<.w.r.:.7 $ O $ $ o o o $ & 9 7 8 7 ; ; $ % $ q 5.7.5.f * b ;XrXrXe.O o X X + ; O , f ;.h s 7 & & % r.y.r.r.}.>XMXLXMX;Xc.e.w.r.1.y.r.w.:.o o $ $ & $ ; 9.;XZXyXe.g -.:.<.<.<.w.y f.A.P.7X8X=X+ O o 7 4.;XpXrXQ.Q.Q.Q.Q.Q.Q.3X#XJXJXJXJXJXJXJXJXJXJXJXJXJXGXPX.>.;.d d CXIX9Xl * q , , ;XeXeX1X1XW.Y.Q.mXmX-X}.5.h q 7 ; & & O z.uXrXeXR.T.I.w.<.,.:.:.-.-.:.:.-.:.:.-.e 8 e e g :.w.1.1.,.; o o o o o o $ & ; B 4.7 8 7 & $ . O f 5.7.;.f ; * x.2X1Xh o + + + O q 7 O 9 s s 9 ; & $ ; r.I.r.T.yXLXIXUXUXLXiX3XI.1.1.1.1.6.-.o o $ $ $ $ $ 0 .X}.s 7 8 e g -.>.:.6.y o.H.=X7X8X4X* $ $ ; ;.T.Q.Q.Q.W.Q.W.W.W.R.ZXoXJXJXJXJXJXJXJXJXJXJXJXJXJXGXGXGXV PXPXPXPXPXPXPXFXBXnXvXcXkXkXzXzXkXgX).oX.>.;.s 9.AXSX0Xl O q 0 , l.R.R.Q.Q.T.T.yXSXKX0X*Xj.h q ; 7 & & & m eXuXrXQ.T.I.r.<.:.-.-.g -.-.-.-.-.-.e e e e -.-.:.1.y.<.:.q 0 o o o $ $ & & 4.z.;Xu 7 & $ O . O d ;.4.h f & , R.2X2Xe.O j # + % e s 8 ; ; ; $ $ $ ; ; r.U.r.1XiXSXIXIXUXIXSXiX;Xq.q.w.1.<.:.$ $ O o O O o $ % ; ; 8 8 e g :.<.6.q.r.l.k.H.P.H. .& & ; 7 e e.Y.I.l.Y.Y.W.W.Q.1XZXoXJXJXJXJXJXJXJXJXJXJXJXJXJXPXGXhXzXPXPXPXPXPXPXPXFXBXnXvXcXkXgXkXkXgXgX`. > 6 a 6 v b.K.P.^.4X4X^.^.^.L.L.G.G.S.S.d.S.d.S.L.L.L.L.F.S.m.[.JX%X< @ 5 K U ] a.a.B.B.C.F.G.L.~.~.G.f.DXJXJXJXJXJXJXJXJX].UXIXSXSXZXuX1XR.I.l.1.<.>.;.7.yXAXSX0Xk . q q 9 0 e.R.W.W.I.Y.ZXSXVX9X.Xj.m q ; 7 ; ; & 7 R.1XeXQ.T.I.<.:.-.g g g g g g -.;.:.:.-.g :.,.,.1.1.1.<.-.q X o O O $ & & 4.T.1XyXMXwX`.r O . $ 9 h h s , j.2X2X2XQ.4.O # O 8 e e e 8 7 & $ $ & & 4.I.I.l.R.uXsXAXSXSXIXSXdXrXT.l.1.<.6.>.y O O O o o o & 7 7 e s h :.<.w.l.l.T.T.c.Z.v.$ & & 7 7 e g ;.<.1.l.I.Y.W.Q.Q.Q.dXoXGXJXJXJXJXJXJXJXJXJXJXJXJXJXBXoXPXPXPXPXPXPXJXGXFXBXBXvXcXkXgXgXgX+X%.%XgXgXgXgXgX 5 t c 5 .Z.K.P.P.4X^.P.P.L.J.F.S.S.d.S.d.B.d.L.L.L.L.L.F.C.b.NXGXM @ 2 p U U ] m.B.B.C.G.G.L.~.~.~.k.JXJXJXJXJXJXJXJXJX].UXIXSXSXdXiX1XQ.T.I.r.w.6.l.eXuXAXpX>X0 o 7 0 9 , b y.I.I.y.I.AXSXZX3X}.z.;.q 7 8 8 ; & & m c.R.1XT.q.;.g g s :.l.l.r.r.<.<.,.>.>.,.,.<.t.t.t.1.,.-.$ o O $ & & 4.;XyXZXZXAXVXVXaXwX*XO.r 0 y 9 0 9.eXeXeXeXeXR.b o + q e e q q 7 7 & & & ; l.W.I.1.T.eXuXsXZXAXAXAXdXuX1XI.l.6.<.6.>.$ O o o . $ 7 7 e s ;.>.<.l.l.I.T.R.Q.eXrXR.& 7 8 8 8 e g ;.<.q.r.I.T.W.Q.eX2XsX XJXJXJXJXJXJXJXJXJXJXJXJXJXJX).PXPXPXPXPXPXPXGXFXFXBXnXvXzXhX * = 5 t v c t o.Z.V.P.P.P.L.L.J.G.F.S.S.B.d.S.S.d.G.P.L.L.L.G.F.S.h.JXS + = 6 K U n.M.B.F.F.G.L.L.^.^.7Xk.JXJXJXJXJXJXJXJXJX].UXIXSXAXZXiXrXQ.R.Y.I.l.I.Q.eXsXiX0X}., X , 0 9 , , f w.w.r.I.SXIXmX;Xv.5.f q 7 8 e 8 7 7 7 e.T.T.l.6.g e q 6.Q.eXQ.Q.W.E.U.1.>.>.>.<.,.1.t.1.<.-.g $ o o $ $ $ 9 z.eXZXAXSXIXSXVXaXqXqXqXaXwXpXyX3X1XrXrXrXeXrXeXc., ; q e e e q 7 7 ; & & , l.T.I.1.I.Q.rXrXuXsXsXuXpXuXQ.T.l.l.q.q.7.m % o o o $ ; q s g >.6.l.I.I.T.R.3X1XuXuXf & 7 8 e g g -.:.>.1.l.I.T.Q.Q.eXrXyXoXJXJXJXJXJXJXJXJXJXJXJXJXJX|.zXPXPXPXPXPXPXJXGXFXFXBXBXvXzXhX > 5 l c c r .f.b.A.J.J.G.J.F.F.F.S.F.S.S.S.S.S.L.^.^.~.L.L.G.S.h.JX`.% - 2 p U ] m.C.F.G.L.L.^.7X7X8X{.JXJXJXJXJXJXJXJXJX].UXSXSXAXsXsXrX3XQ.T.I.U.W.eXeXuXuX>Xx.& o % q 0 9 9 & -.w.w.T.SXSXZX;Xx.5.h q 8 8 q 8 7 7 7 h l.T.r.;.s 8 q uXtXuXuXrXQ.Q.Y.I.<.:.:.:.,.1.,.,.:.-.e o o O $ & o q z.yXZXAXSXSXSXVXpXtXaXaXVXCXVXZXZXiXrXuXrXuXiXZX0Xx.; 9 q d e e 8 ; ; & % ; z.W.I.r.r.W.Q.eXrXrXrXeXeXQ.W.Y.W.R.R.R.R.R.7.o . o o % 8 s h >.6.r.l.I.T.T.Q.Q.rXuX1X; & 7 e e g -.-.:.>.1.1.I.W.Q.Q.rXuXc.FXJXJXJXJXJXJXJXJXJXJXJXJXFX].PXPXPXPXPXPXPXJXGXFXBXBXnXnXzXhX].kXFXx %XcXkXhXhXXsXZXdXsXuXrXeXQ.W.Y.Y.W.2XrXuXyX1X9.% O , 0 9 9 9 9 q y.y.1XCXIXZX>Xc.5.h s 8 8 q 8 7 & & s l.l.q.-.8 7 ; eXuXuXuXQ.Q.Q.E.1.>.;.-.:.,.,.,.,.-.-.; . o $ & 7 7 7 4.T.1X;X3X0XCXwXwX*XaXVXSXIXSXZXZXiXrXuXuXuXsXZXMX;X0 ; 7 q 7 7 7 $ $ $ $ * 7.T.I.l.w.Y.W.Q.Q.Q.Q.Q.W.W.Y.T.Q.Q.eXQ.eXeXQ.x.@ $ o ; 9 h ;.6.e.I.T.I.Y.R.Q.Q.rXrXq.; ; 7 e e g g ;.;.<.l.l.l.Y.Q.rXrXuX`.JXJXJXJXJXJXJXJXJXJXJXJXJX+XcXPXPXPXPXPXPXPXGXFXFXBXBXnXvXzXhX].GX].cXnXBXzXkXgXM o.[.J / / E ~ @.k.k.K 3 D Y R D =X XPXPXPXPXPXxX^ W E Y J .X9XbXbXvXcXcXcXzXhXcXnXFXPXPXPXGXcX%.cXBX%. 5 < 5 5 k z v : a o.f.n.n.n.C.C.F.F.F.J.J.F.L.L.P.^.4X^.^.^.^.~.L.[.JXFX< = = - p @.N.F.L.L.P.4X7X8XqXqX{.GXJXJXJXJXJXJXJXJXHX'.uXiXsXuXuXrXQ.Q.W.W.E.Q.2XrXrX1X;Xe.% + 9 9 9 0 9 q q Y.Y.1XiXAXAXuX;X7.;.s q 8 8 7 7 $ $ ; l.r.:.q 7 & & x.uXuXuXQ.Q.E.U.1.:.g -.-.-.-.-.-.-.e o o o $ & 7 8 8 y >.5.B b 9.@X@X*Xk {.mXVXCXDXZXsXuXuXrXuXuXZXZXMX1X9.$ % & $ o $ O $ $ $ O B l.l.q.<.w.l.W.W.Q.W.W.I.Y.Y.Y.W.Q.Q.eXeXeXeXeXT.O o ; y h 4.e.l.T.T.T.T.R.R.1X2XQ.-.s e 8 8 e s g ;.:.>.<.1.y.T.Q.Q.uXx.kXJXJXJXJXJXJXJXJXJXJXJXJXJX].PXPXPXPXPXPXPXJXPXGXBXBXnXvXvXzXgXoX#X%XzXvX`.kXhXC {.[. .W ^ ! OXFXPXGXFXkXM a I G } {.hXJXPXPXPXPXjXR Y F H H L OXnXnXvXvXcXkXgX%X 5 1 5 6 c v Z z ...f.b.n.V.V.F.F.F.F.L.L.L.^.^.^.7X^.7X^.^.^.P.}.JXJXV @ * 2 i I n.V.F.P.^.7X8XqXaXAXpX+XJXJXJXJXJXJXJXJXJX9X;XrXuXrXrXrXeXQ.Q.Q.Q.Q.Q.rX2X1X;Xe.; $ ; , , 9 u 9 q Y.R.2XrXiXsXuX1Xz.;.g q 8 8 7 7 $ O % r.s $ o o . f 2XeXeXQ.Q.E.t.,.-.g -.g -.g g e 8 o . o O & 7 8 e e 8 8 9 , ; 0 Z `.0.A z -X9XxXlXiXiXuXrXrXrXsXsXZXMX>Xz., O $ o o . % 7 8 8 & d z.e.q.>.>.w.l.I.I.I.I.l.u.U.I.E.Q.Q.rXeXrXuXrXeXT.@ ; q m 7.z.x.T.T.T.T.T.R.W.Q.I.:.:.-.h h f q q h 7.6.>.l.l.W.Q.Q.rXg.JXJXJXGXJXJXJXJXJXJXJXJXJXJXXXPXPXPXPXPXPXPXJXGXFXBXnXvXvXcXzXgXC oXjX#X).|.kXC oXOXk.I E G vXPXHXGXGXGXFX-XA &X=X&X`.S gXGXJXJXJXxXH H F F H H Y U #XnXbXzXgX.-.s e 8 ; & O o s s O O X o X X ; W.eXQ.Q.E.U.1.:.g g g e e e e e 8 . . o O $ & w e g e 7 $ O X . O : |.JXoX+.oX,X>XyXyX2XeXrXrXuXiXsXiX3Xc.9 O O o $ h ;.g s e e d f 4.6.>.;.:.<.r.r.1.1.1.1.r.U.E.W.Q.Q.rXuXpXrXuXrXo & q h q.l.l.l.l.l.l.I.Y.W.Q.y.r.r.<.1.r.l.l.T.1X3X6.l.l.I.W.Q.Q.v.NXJXJXJXJXJXJXJXJXJXJXJXJXJXJX|.PXPXPXPXPXPXPXJXGXGXFXBXvXvXcXkXjXS OX/.].hXhX`.].cXoX[.Y D 4 h.PXHXGXGXGXFXBXkX[.[.].%X%XZ vXBXBXGXKXK H F F F F H Y D _.cXhX.g g y 7 - & <.U.r.% + + X o X o e.W.Y.E.U.t.,.-.g e 8 8 8 8 -.-.e o . . O o $ 8 e s s 8 o . . . o + kXJXoXu k }..X;X;X1XQ.eX2XeXrXuXuX;Xc.f o $ o h 4.;.h g g g -.g s g m ;.-.-.,.<.<.<.<.w.y.y.U.W.Q.Q.Q.uXuXpXuXuX& o 9 h >.l.l.l.<.l.w.r.I.W.W.U.U.U.E.U.Y.Y.W.Q.rXuX9.r.l.Y.T.W.x.nXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJX|.PXPXPXPXPXPXPXPXPXGXFXnXnXcXzXkXzX/.%.].].hX,XA {.*Xv. .F D 4 4 -XPXFXGXGXFXFXnXcXhXgX%X#X%.S cXnXBXPX%XD F F H F Y Y F Y ..%XkXgXkXcXBXGXPXFXBXcXzXgX%XgXXXPXPXPXPXPXPXPXPXPXkXkXkXkXzXnXBXFXGXPXJXGXk JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXGX].PXGXFXFXJXPXPXPXGXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXPXPXPXPXPXPXPXPXPXPXPXPXPXJXV oXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX%XN.C.C.C.C.$.C.C.$.A.C.$.$.C.$.$.$.#.#.o.@.$.........U | U ..| | | | | | | ....| ..| o.#.#.&X$.@.L @.M.N.$.@...{.FXHXPXHXHXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXnXM } K K p p $...@.3 a a - 2 K U N.m.m.a.[ [ { { { ' ' { p.p.p.s.B.B.B.X.I o.k.k.k.k.[.}.`.x + l v hXJXJX`.: t } X.n.n.V.F.J.L.P.4X7X7X7X7X8X7X7X7X7X7X8XH.cXJXJXC @ = 2 5 y K f.Z.P.6XaXSXIXUXUXxX#XJXJXJXJXJXJXJXJXJXJXzXR.Q.Q.Q.rXrXQ.^.eXQ.Q.Q.Q.R.I.m ; $ O * , 9 f W.Q.Q.Q.Q.Q.Q.Q.tXuXeXQ.l.:.g s 8 e <.t.U.r.; , * + + + . ; I.U.t.r.<.,.g e 8 7 7 $ 7 e -.g & . o o o o $ 8 8 8 & . . o . . o 1 n q q q 7 9 B R.T.Q.Q.Q.Q.Q.eXeXR.T.4.o $ ; ;.4.;.-.-.g -.-.-.e e e 5 & & g -.:.:.<.1.1.y.U.Y.Q.Q.rXrXuXuXdXuX* o $ y f ;.>.>.>.>.w.r.I.Y.Y.W.Y.E.E.E.E.Q.Q.Q.rXpXj.>.<.r.u.T.zXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXXXPXPXPXPXPXPXPXPXGXGXFXnXBXnXvXFXPXPXKXcX].-X{.tXqXqXqX5XD D D H p vXGXGXGXGXFXBXvXzXhX%XXXx %.#XkXGXPXPX{.F Y Y H Y Y F F Y J hXcXnXFXFXGXPXFXvXzXhX.<.<.:.u y , ; * % . $ 6.,.1.<.:.g g & . . . o $ 8 e e 8 & o . . o & & ; o o o o . . . 9 q q 7 7 ; ; ; q T.W.W.Q.Q.Q.Q.W.c.4.O O y ;.;.4.;.h g g g e e 8 7 ; & & & e g :.<.w.y.u.U.W.W.Q.Q.tXuXsXsX3X. o o O s d f h ;.:.<.q.I.Y.W.E.E.W.E.E.E.Q.Q.Q.tXuX4.s :.1.u.XXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXoXPXPXPXPXPXPXPXPXPXFXPXPXPXPXPXPXPXPXBX$X%.{.aXqXqXtXqX5XF F D D D K {.gXBXGXGXGXnXvXhX$Xx #XPXC FXPXPXPXPX+XG H H F H H F F Y -XFXFXGXGXPXFXBXcXkXXQ.uXrXrXQ.Q.Q.rXrXQ.R.T.l.h 8 & & $ . 3XiXuXQ.Q.Q.T.Y.I.Q.rXeXeXQ.W.y.1.<.:.<.<.1.l.>.h 0 u < , % o & e 1.1.<.,.-.g 7 $ $ o & 7 8 8 e 8 & o . $ $ . & 8 q q q & & ; 7 7 8 7 7 ; ; q T.W.W.W.Q.Q.Q.W.l.;.O $ q h ;.;.h g s e e 8 8 8 8 7 & & $ 8 g <.r.y.Y.Y.Y.W.Q.eXrXpXsXdXuXd . . . o - g h h h ;.>.r.I.T.W.W.W.E.Q.E.E.E.Q.Q.eXuXy g >.y.U.I..<.l.Y.W.W.E.W.E.E.E.Y.W.Q.eX7.e -.<.y.U.W.z.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXhXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXJXcX|.A qXH.+.{..XH.f.T / / / / ( W W W W W E L hXvXkX].GXGXS FXPXPXPXLXxX-Xf.] T R ) / ^ ( W Z.PXHXGXGXFXnXzXhXgX].).%.FXPXPXGXGXGXFXFXnXvXvXnXFXFXFXGXGXPXPXPXPXPXGXGX`.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXGX#X%XJXXXFXnXoXhXcXcXkXcX = 2 i a I ..f.Z.H.5XmXKXUXUXUX$XnXJXJXJXJXJXJXJXJXJXGX_.sXdXsXuXrXeXQ.rXQ.eXQ.T.w.>.h e 8 ; & & 5 eXrXQ.W.l.w.:.l.Q.eXeXQ.Q.Q.Y.u.u.U.E.W.Q.Q.Q.I.<.* 1 $ $ & 8 e t.u.u.t.1.,.,.-.g g g g -.-.,.-.e . o o o -.y.U.l.z.c.c.}.;X>X}.M 0 ; 7 7 q ;XR.W.W.W.E.W.W.I.q.;.o o 9 h -.f s e 8 7 & & & & & 7 ; y yXZXiXeX1XR.R.Q.Q.Q.2XrXuXdXdXuXu X X . $ ; q h g s g ;.<.l.T.W.Q.Q.E.U.U.y.U.T.Q.Q.s g -.<.1.U.W.T.hXJXJXJXJXJXJXJXJXJXJXJXJXJXcX].kXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXFXcX#XZ H.O.A Z JXKXOXT / / / / / / ^ ^ ^ W W W R [.kX#X|.GXcXXXPXPXPX.X] E ( ( ( / / / ` ( W W OXPXFXBXnXBXcXkX#XC ].oX%.GXGXGXGXFXFXFXBXvXvXcXnXBXFXFXFXGXFXGXGXGXGXGXGXXXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX%X].FXhX].%.XXXXGXgXcXcXkXkXcX).x nXPXPXPXPXPXPXPXGXFXFXFXFXBXnXnXnXvXcXnXBXFXFXFXFXGXGXPXPXGXGXPXGXPXPXPXcXhXgXkXzXnXnXFXbXoXPXPXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX&XA.C.C.A.C.$.C.$.C.$.$.$.$.$.C.U [ [ $.[ [ [ [ [ $.$.L a | +.%.bXFXFXKXFXFXFXkX#X].]._.%.o...o.| U 2 4 D F H T Y F p $.$.C.X.x ] { s.{ { { [ ~ L g.JXJXJXJXJXJXJXJXJXJXHXJX).| K @ A.f.v 6 v .v c < i 6 2 O.JXA n.B.d.d.d.d.d.d.d.B.d.d.M.d.B.B.S.S.B.M.m.n.n.X.I v l c vXJXJXJXS < > + 5 v f.k.Z.H.=X6XqXqXqX8X8X8X8XqXaXVXSXKXKXoXk = = 5 i I I ..X.b.H.*XwXCXIXUXUXPX+XJXJXJXJXJXJXJXJXJXzX}.SXAXsXuXuXrXrXrXeX!.Q.T.q.h s e 8 7 7 ; ; R.R.T.l.r.>.;.r.Q.Q.Q.Q.Q.Q.W.Y.Y.Y.W.Q.Q.Q.Q.W.I.e $ & 7 7 8 ,.u.u.u.t.t.1.,.,.-.-.-.,.,.<.<.,.g 7 . o o O 8 u.u.r.T.;XyXyX|.g. X@X}.Z < 7 ; e.;XQ.Q.W.W.W.W.E.I.6.h o . 7 h h s e 8 7 & & $ $ & & & ; HXUXUXIXCXiXeXeXeXeX1XuXsXZXAXAXuX9 o o o . * 8 g h g g g ;.<.l.W.Q.Q.E.E.y.1.g s ;.4.f s -.:.<.y.U.W.2XoXJXJXJXJXJXJXJXJXJXJXJXFX`.oXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXFXvX 5 @ < v f.k.H.=X=X6XqX8X6X6X8XtXqXqXaXSXIXUXKXS * = 2 t a } ..f.n.Z.=XwXVXKXIXIXUXoXJXJXJXJXJXJXJXJXJX`.SXSXAXdXpXuXrXrXQ.Q.Q.Q.I.<.g y e 8 8 7 7 ; y l.l.l.>.h >.W.rXeXrXQ.Q.Q.E.Y.Y.W.W.Q.E.Q.W.Y.r.2 & & 7 8 8 -.u.E.u.u.t.t.1.,.-.,.,.1.t.t.t.1.-.8 . . . o O 1.U.I.T.1XuXZXsX>X_.'.$X}./.9.7 9 ;X1XQ.Q.W.Q.W.W.E.Y.w.-.O X O d g s 8 7 & $ o o $ $ $ & O MXIXUXUXIXSXsXuXuXuXiXZXSXSXIXIXAXB + O O $ 8 d h ;.h g h h l.T.Q.Q.Q.E.:.; & ; 7 q q s ;.:.w.y.U.E.Q.eX.XJXJXJXJXJXJXJXJXJXJXJX).BXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXBXgX`._.k.f.h.h.`.GX,X) / ~ X.] L J T R ^ W W E R J zX 2 6 M HXHXjXI m.M.B.M.d.s.M.s.s.s.s.s.d.d.d.B.B.S.F.F.S.C.C.n.I a x JXJXJXkXk 1 > > : > z .k.Z.=X4X6X8X8X6X8X6XqXaXAXAXIXUXUXPXl = 6 p a } ..f.n.A.=X5XaXKXIXIXIXoXJXJXJXJXJXJXJXJXJX`.sXdXsXuXrXeXQ.Q.Q.Q.Q.1XT.e.4.e s e 8 8 8 7 & ; f ;.f s l.eXrXrXQ.W.W.W.W.Y.E.Y.E.Q.W.W.Y.r.>.% & 7 7 8 8 8 t.E.u.u.u.u.t.t.t.t.t.t.u.u.u.t.-.w o o o o & t.:.T.eXiXsXZXsXyX.X'.9X@X.X,X% 9.>X1X2X2XQ.Q.Q.E.W.E.y.>.$ X o ; s 8 ; & $ $ O ; q 9 ; & $ }.ZXIXIXIXIXAXZXsXsXSXIXIXUXUXUXIXyX0 o % ; d h ;.4.;.g ;.;.z.R.eXeXQ.w.; $ $ ; ; 7 9 f >.l.I.Y.W.Q.Q.rX@XJXJXJXJXJXJXJXJXJXJX#XX,XJX].hXBXPXPXPXPXPXPXPXPXPXGXFXcXcXcXkXkXzXgXXX+XPXPXPXPXPXPXPXPXPXXXPXGXhX]. > < @ : , l N f.Z.=X4X6X8X8X6X8XqXaXVXVXSXUXUXUXBX6 5 t K | o.b.Z.Z.K.5XwXVXSXSXUX%XkXJXJXJXJXJXJXJXJX`.uXuXrXeXeXQ.Q.W.W.Q.1X1X}.9.4.e e e e 8 8 7 ; $ $ 7 8 9 uXuXuXrXeXT.Y.T.W.Y.W.W.W.W.W.E.U.,.e $ ; 7 8 8 7 & -.u.E.u.E.u.t.t.u.t.t.u.u.u.u.t.-.7 o O $ $ e ,.T.rXsXsXZXdXZXsXyX9XjXlXMXMXB 0XyXyX1X1X2XQ.Q.Q.Q.E.Y.w.% . X O . $ $ $ & $ 7 h d 9 ; % % b 0XiXMXZXZXZXiXZXZXIXUXUXUXUXUXUXLXyXj.n f h ;.4.6.;.h h ;.l.R.eXsXuXs & $ O $ & ; s ;.w.l.W.W.Q.Q.Q.rX|.JXJXJXJXJXJXJXJXJXPX).PXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXFXvXgX$X$X{.k.h.+.h.O.BXU H i FXHXPXJXGXOX-X{.U F F L gX%X#X%. 1 : > * < z .k.H.=X=X6X4X8XqXqXaXaXAXSXUXUXUXUX'.> 6 a I ..f.Z.D.K.5XwXVXSXSXIXIX`.JXJXJXJXJXJXJXJX|.rXrXeXQ.Q.W.Y.W.W.Q.1XyX.X9.m e q e e q 8 7 7 & O o o 3XsXsXuXrXQ.l.U.Y.Y.Y.Y.W.E.E.E.Y.1.h 7 $ 7 8 7 8 7 & & u.u.u.u.u.u.u.u.E.u.u.u.u.t.,.-.& o o $ $ ,.g 1XAXAXAXAXAXZXZXSXbX,X,X}.9.XX>XyX1XeX1X2XQ.Q.Q.Q.E.Y.w.$ . . o & $ $ $ $ 4.;.s 9 ; & & , 4.}.1X1X1X1X1X1XyXiXMXZXPXUXUXUXIXZX0XMXA 4.6.q.q.4.;.6.6.z.;XuXdXdX; % o o $ % 9 f 6.l.T.Q.Q.eXQ.Q.j.BXJXJXJXJXJXJXJXJXJXGXhXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXFXFXbXjXoX_.{.h.k. . .+.k. XF D 4 _.PXPXPXFXvXFXBXnXjXOX%X%X#X#XS ).|.GXGXFXU W ^ R J k.OX%XlXcXBXBXnX-X*Xg.#X+X+X$X%.gX#XV %.+X).%X%.).+X`.].%.).#XhXkXkXhX > : 1 z .f.K.P.=X4X4X6XqXaXaXVXSXUXUXUXUXUXl 5 d I } f.b.Z.K.=X6XmXVXAXIXSXj.JXJXJXJXJXJXJXJXGX;XeXQ.Q.T.Y.r.Y.W.W.CXCX>Xz.m d e e e e 8 7 ; $ O o , ZXdXsXuX1XQ.Y.I.Y.Y.T.Y.Y.E.W.E.U.<.g $ % & 7 7 7 7 7 e t.u.E.E.u.u.E.u.u.u.u.u.u.1.,.e o o o o & w t.>.;XSXSXAXSXSXZX0Xj.f ; 7 7 7 B }.}.;X1XQ.Q.Q.Q.Q.Q.E.w.o . o O $ o & $ o 7 7.6.d 7 7 & ; 7 ; b 7.e.x.x.c.}.;X;XyXMXCXUXUXIXIXSXMXZXj.5.7.z.l.e.6.7.7.z.;XyXdXSX; $ o o O ; y m l.R.Q.eXrXeXQ.v.HXKXJXJXJXJXJXJXJXJXJXGX < : j x .Z.H.K.=X=X6X8XqXaXVXVXIXUXUXUXUXCX5 6 c .o.Z.Z.H.K.=XaXaXVXSXSXh.DXJXJXJXJXJXJXJXJXCX}.Q.W.U.r.1.y.u.;XIXSX1Xx.4.f s s e e q 9 7 $ o o z AXZXsXrX2XQ.Y.I.U.Y.Y.Y.W.W.E.E.Y.:.q $ O & 7 7 & & & ,.t.E.u.E.E.E.u.u.t.t.u.t.,.,.-.& o O o $ 7 7 1.r.f >XZXZXMXyX0.* & ; ; 7 7 7 7 q m x.R.Q.Q.eXrXQ.Q.W.q.O o O $ O O $ & $ 4.c.z.f , ; 7 7 q q 9 d 7.7.e.z.x.c.}.;X,XxXBXKXVXSXSXIXIXxXm x.x.c.x.l.z.z.c.>X0XAXIXB ;.; X + ; s 7.c.R.2XrXuXQ.9.DXJXJXJXJXJXJXJXJXJXJXJXJX+XPXPXPXPXPXPXPXPXPXPXPXPXGXGXBXNX|.*XqXtX8X8X6X6X=X=X*XH.O.H F D 4 K JXJXGXnXcXzXkXkX.6.s % ; f z.R.eXuXsXsXA PXJXJXJXJXJXJXJXJXJXJXJXJXJXoXPXPXPXHXPXPXPXPXPXPXPXPXFXNXBX wXqX6X*XZ.+.v > z k.k.+. .c = > t l Z S gXJX 1 k x O.h.[.&X*X*X6X6XqXqXaXVXSXUXIXUXIX6XZ.v .h.k.Z.K.P.6X6XqXAXaXtX].JXJXJXJXJXJXJXJXJXJXHXg.I.1.<.<.r.iXAXiX1XI.6.g e e s q q 8 , * O . z ZXsXyX1XQ.W.I.u.U.I.I.Y.Y.W.E.E.l.g 7 O o & 7 7 & & w t.u.E.u.u.u.t.1.,.,.,.-.-.e e o $ $ $ & 7 7 7 7 1.r.r.r.w.-.8 . . o $ $ & & ; 7 7 ; y T.Q.Q.eXrXpXeXR.q.o $ O $ 7 ; O & 9 z.;Xc.9.y 9 q q d e d f v.c.}.}.}.}..XOX.X@XxXxXwXaXVXIXUXA j.z.x.c.c.x.v.x.}.@XwXVXeXI.w.r.r.s , b z.;XuXsXdX@XnXJXJXJXJXJXJXJXJXJXJXJXJXJXJX 6 ..L [ _ [ [ [ [ @. .vXJXJXJXJXJXJXhXX.( ` ` _ _ Q G c v | ..U #.#.#.#.N.N...$.S.S.C.B.V.n.V.n.n.n.n.b.@.X...v ).HXJXJXJXJXJXHX> *XqX6X=XZ.k. .5 < _.[.k.h.N 6 @ 1 1 r x C BX Xg._.| a.B.M.B.M.B.S.F.F.J.L.J.L.J.J.F.C.F.C.V.C.V.A.K.*X.X6 : : < 5 6 1 : 1 r c O.h.[.*X*X=X6X6X6X6XqXVXSXKXSXUXSXqXo.v .f.Z.H.H.4X4XqXqXaX8X'.JXJXJXJXJXJXJXJXJXJXJXJXS R.q.I.Q.AXAXuXeXR.r.;.s e q 7 ; $ % O o + * yXyXeX;X1XR.Y.I.Y.Y.I.I.Y.Y.E.E.U.-.8 ; O o & 7 7 & -.t.E.E.E.u.t.,.-.-.-.-.-.-.e 7 $ $ o & & 7 7 7 & 1.y.U.r.1.e 7 o . o & & ; ; ; 7 7 ; d ;X1XrXuXuXuXuX;Xz.. $ $ q q e q 8 9 z.3X.X9.r q q q q s q j.v..X.X}. X}.+X.X XxXbXmXmXVXVXIXS B 9.j.9.z.7.z.x.x.}.@X3XyXeXQ.W.I.Y.e.* n z.;XpXAXAXZ NXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX].GXFXBXGXPXPXPXPXPXGXnXcXzX].H.O.O. + : > < 6 j : 6 k v +.[.&X*X=X=X5X6X6X8XqXaXVXSXIXIXVX7Xt N .f.k.H.P.4X4X8X8X7X{.JXJXJXJXJXJXJXJXJXJXJXJXN j.Q.rXsXAXdXuXeXQ.I.<.:.g g s 8 $ O o X + + z >X;X}.;XR.Y.I.I.Y.I.I.u.U.Y.E.U.:.q 8 - o O & $ . :.y.U.E.u.t.<.-.-.e -.e 8 8 8 o o $ & 7 7 7 & & & 1.u.I.r.6.s 7 $ o O & 7 ; 7 7 7 7 ; m >XrXiXZXZXZXZX>X}.O % q d f h g e q 9..X}.O.l u 9 9 e s 9 h.v..X.X.X.X{.}.}.0XCXCXCXBXmXaX-X+ n B 9.B B B m 5.z.z.x.R.1XrXeX2XQ.Q.W.u Z `.e.pXSX0Xe.j.|.JXJXJXJXGXJXJXJXJXJXJXPXJXJX`.GXBXFXGXHXJXPXJXGXvXvXzXzXk.k.k.h.+X].).PXPXgXOX&XH.H / / / / / / ^ W W W E T F #X : : 1 S HXS _.].|.%.a n.B.C.S.C.F.J.F.F.J.J.J.L.L.J.J.F.C.B.C.C.D.J.P.H.+.# + + @ : 5 6 : k x S h.{.*X*X-X=X=X4X4X6XtXqXaXSXIXIXaXv x N O.o.f.K.P.4X8X7XtXH.vXJXJXJXJXJXJXJXJXJX.;.g s q O + + + % + x.}.c.T.T.I.I.T.I.l.l.r.U.Y.Y.y.<.s e 8 & $ 0 u % <.y.u.u.1.<.,.-.e 8 8 w 7 & o $ $ & 7 7 7 7 7 7 $ ,.y.y.r.w.e & & o $ 7 8 7 7 8 8 , , B yXZXZXSXIXIXLXyX}.. u b ;.4.;.h s d b S g.Z z q 7 9 e q + h.{.{.&X X{.'.c.>XMXLXSXSXKXKXmX6 9 : 9 0 0 u u u b 5.j.j.c.;XeXrXrXeXeX2X7., 9 q Z AXj.I.Q.yXMXJXJXJXJXJXJXJXJXnXoXoX].).V %XBXBXFXPXPXPXJXBXcXzXzX#XH.k.k.k.|.0.vXPXPXPXPXHXL / / / / ^ W ^ ^ ( W W E T D .:.g q & + + + + : , j.j.x.v.l.l.I.I.l.U.U.E.E.Y.U.<.g s q 7 $ ; b & :.r.y.t.,.,.-.e e 8 8 8 8 w e 8 8 8 8 7 7 & 7 7 $ w.y.I.e.e.>.q ; o $ 7 7 7 8 q q 0 9 j.yXsXAXSXAXSXmX@Xj. m 4.5.7.6.4.;.f f B A Z b 0 9 9 q 9 % < +.h.h._._.}.>XZXAXIXIXIXIXSXVX, y d 9 : 1 0 0 l B 9.j.x.}.;XyXuXuXuXuXuXeX8 ;.>.6.4.6.R.eXZX`.JXJXJXJXJXJXJXJXS JXPXPXPXPXPXPXHXPXPXPXPXJXnXcXzXhXXX*Xk.k.k.h.0.FXPXPXPXPX{.( / E ] f.-X+.D D F T W R Y O..>.;.<.T.W.W.W.W.Q.E.E.l.-.f s 8 ; O , < g <.<.<.:.-.e w e e 8 e e -.,.,.-.-.8 8 7 7 & & q y.T.W.T.T.l.;.8 ; o o $ ; e b 5.B b v.5XqXaXaXaXpX5Xk.t . B B 7.e.e.q.4.m m B B Z n 0 0 < 9 % % @ N +.h. X>XlXZXLXIXIXIXUXUXSXAXv u u * < < 0 0 z B 9.x.}.;X1XyXiXsXsXZXZXZXq ;.6.e.T.T.1XiXCXO.JXJXJXJXJXJXJXGXS PXPXPXPXPXPXPXPXPXPXPXPXGXvXcXkXhX+X&Xk.k.k.h.).JXPXPXPXKXT R k.xXPXPXPX@X| G Y D F Y D -XgXgX).BXPXPX{.*XGXFX].J ( / / / / / / / / F 4 Y K k. ._.%X#XV XXhXvXFXFXGX{.R R W ^ ^ W ^ ^ / ^ ^ ) X.%XBXnXBXvX].GX#XoXzXcXgX:X}.|.#XcX 6 : x A _.[.{.&X&XH.H.D.K.P.4X8XtXpXdXAXaXv.r c v v h.Z.P.^.^.7X7Xv.GXJXJXJXJXJXJXJXoX$XSXpXeXQ.eXQ.Q.Q.uXeXQ.R.Y.I.1.<.<.:.g 7 + # + + + + @ 4.4.h d s T.Q.Q.Q.Q.Q.Q.E.W.I.:.d s e q & $ l 8 :.-.-.-.g 8 7 e -.-.-.-.:.-.-.-.g 8 8 & & & & 1.I.Q.Q.;X;XT.e.m q O O q m 9.}.].S K.4X8X8XtX8X4XH.k.* + B 5.9.9.e.7.7.4.4.5.B M B B n 6 k 6 6 f.*X5X0XxXCXLXIXIXIXIXUXIXSXaX8X5Xq , = < < 1 6 x Z 9.}.;X>XyXiXiXZXAXSXIXIX0 6.6.r.T.;XeXZXOXnXJXJXJXJXJXJXJXnX|.PXPXPXPXPXPXPXPXPXPXPXPXFXvXzXkXkX 6 : M +._.[.k.k.Z.Z.Z.D.P.^.7X7X8XtXaXtX8X5 z c v o.k.P.^.4X4X7XH. < k x S g.oX,XyXiXZXAXSXIXIXUXPXd w.r.T.R.2XuXZXkXJXJXJXJXJXJXJXJXFX+XPXPXPXPXPXPXPXPXPXPXPXJXBXvXzXkXkXgXk.O.O.k.k.k.oXnXFXFXo.D D zXPXPXPXPXxX-X#XzX#X{. XgX b.G.F.] 3 . . .N | v v l 1 1 S JXJX].{. X[.k.+. .+._._.C r V.J.J.J.D.V.K.^.^.^.^.^.^.^.~.L.J.G.F.F.C.C.V.X.v 6 @ @ : > 5 < C h.h.k.k.Z.k.Z.Z.Z.P.^.7X7X8XtX8X7Xk.6 c v } k.K.P.^.^.7X7X_.JXJXJXJXJXGXJXJXhX>XuXQ.Q.E.Q.Q.Q.rXQ.Q.R.Y.U.r.r.r.l.l.h ; @ # + # @ + h h f h 3XuXpXQ.rXQ.Q.Q.Q.W.U.,.s s f f 8 $ 0 l * 7 8 7 & & & 8 e -.g -.,.<.<.w.,.g 8 7 & $ >.T.1XeXuXsXsXiX>X}.e.m o , 5.c.9XxX$X_. .n.D.L.P.L.F.f.- $ O ; A 9.j.x.z.z.7.7.9.9.5.Z C N M O.c A.P.4XqXVXVXSXIXIXSXSXSXAXaX7XL.L.v.u * 5 < : < 6 Z +.{..XlXZXLXIXIXIXIXUXUX.Xq.l.T.Q.2XuXsX,XJXJXJXJXJXJXJXJXJXJX#XPXPXPXPXPXPXPXPXPXPXPXJXGXcXkXjXzXkX0.K.H.f. .h.+.#XvXcXL 4 D v GXPXPXPXJX-X&XzXhXgXgXgX k.k.N.&X+.k.| o.o.k.#.k.&Xf.Z.d n.S.D.n.X.U I I X.n.V.n.A.D.H.K.*X&X[.+.C nXJXGXg.6 y F.F.n.i N . . . .Z N z r 0 k hXJXvX+. X{.h.k.+.+.].`.Z z a D.K.J.J.D.V.~.^.7X^.7X^.7X^.^.~.L.L.L.L.P.P.J.L.K.X.5 : < 6 6 < Z h.h.k.f.f.f.f.Z.A.P.^.^.7X7X7X7X^.t c c N o.Z.P.~.^.^.7Xg.GXJXJXJXJXJXJXGXGX,XtXrXQ.Q.Q.rXrXrXrXQ.W.T.I.r.y.I.I.T.4.9 + * # @ # = - h f 7.uXpXuXuXQ.Q.Q.Q.W.E.U.,.g e s e & % n z < ; $ o $ $ & 7 e e 8 1.R.R.I.l.l.>.8 & & 7 l.R.eXuXAXSXSXSXiX;Xc.9.o O B ;X0X9X XA O = U @.n.m.X.9 g 7 $ O $ 0 B 9.z.z.j.9.j.9.0.N M c v +.c b.P.=X6XqXVXAXAXSXAXaXaXpXtX^.d.^.N f < 3 = = > k .k.*X0XxXLXIXIXIXUXUXLX9Xc.x.T.R.2XrXiXOXGXJXJXJXJXJXJXJXJXJXJX$XPXPXPXPXPXPXPXPXPXPXPXGXBXvX9XOX.X.Xk.5X=XH.*XZ.o.Z oXzXI D D D .JXPXJXnX{.*X{.{.#X = < d s .XyXiXrX1XQ.R.W.W.W.Y.y.<.g e q 7 $ r N c r * & $ $ $ & & 8 w d ;XyXpX0X;XR.r.-.& ; q T.1XyXdXSXIXIXUXCXyX.Xx.O X 1 .X@X Xx * $ $ * 2 p G 7 g g q ; ; ; ; , , 0 B 5.9.9.j.0.Z z c O.+.N a A.L.P.8XtXtXaXAXaXqXtX8X^.L.p.N b b < 2 = = 5 t .Z.*X6XVXKXUXUXIXBXg.n z.c.c.;X1XiXiX XJXJXJXJXJXJXJXJXJXJXJXJX#XPXPXPXPXPXPXPXPXPXPXHXGXzX.X5X5X*X.XP.4X=X=X=X=XH.k. .XX&XF D D D | bXjX5XwXwXwXwX[.$X#X#X$XkXFXFXBXnXhXk.'.cXU H D D ..#XbX%Xo.o.+.+.o.%.].oX+X#X#X#X#X#X#X%X].%.#X#X#X#X].4 F F F Y Y @.PXPXGXGXFXBXS %X%X#X0.6.;.6.9.`.7.r.u.Y.E.Y.E.Y.Y.Y.u.Y.7.S PXPXPXPXPXPXPXPXPXPXPXPXPXPXGXS oX].zXFXGXkXS S ).%.).|.BXFXBXnXcXkX).C %.].hXcXkXgXhX = 5 5 k l 9 -XxXyX1XR.W.T.W.Y.Y.U.t.,.-.e 7 % ; .N c r $ $ o o $ & 7 7 & z.0XKXSXaXyX1XT.q.8 & g T.3XMXSXIXUXUXUXPXMX>X}.% , 0 '.{.: o o $ & & ; & ; g -.g q 7 7 9 0 b V r X * z B 0.j.O.c c O.O.O.t X.F.P.^.7X8XtXaXVXVXwXwX5Xf.a B m n zXM 5 = - 3 I b.J.8XVXKXKXHXmXz 9.z.}.}.;XyXMXZX}.JXJXJXJXJXJXJXJXJXJXJXJXJXXXPXPXPXPXPXPXPXPXPXHXbX-X*X5X.X,XgX#XH.4X=X=XH.=XH.H.H.[.nXG F F F D 4 |.&XwXwXwX6X&XzXzXcXcX > 5 5 z kX|., A g.A 7.T.I.I.I.U.I.U.y.<.,.-.-.e y 9 * > 5 % $ o o & & 7 7 & ).0XIXKXmXyX;Xq.g 7 o o m c.lXCXVXSXKXKXKXMX>XA k l 1 h.h.= $ $ $ ; ; ; 7 q g g g 8 7 9 q d 5.9.Z 0 % ; < l +.g.6 Z O.O.O.v t b.J.P.4X6X8XwXmXmXxXZ u b B B b -XJXGX).a 2 4 U D.L.4XqXVXwXmXwXZ z |.@X>X,XLXZX1X0.GXJXJXJXJXJXJXJXJXJXJXJXJXXX].PXPXPXPXPXPXGXjX@X5X5X.XgXnXcXkXoXH.5X5XK.*XH.*X=X=X.XLX} D H T R ^ E E T L Z.wX-X-XFXPXPXV V 1 ).`.=XH.=XK.=XP R Y Y Y Y ..kXO.o.Z.h. < t c x .C Z S O.%.h.g.A B b u u < 9 1 k |.].`.O.O.OXoX].0.Z M M a K.D.D.Z.Z.H.4X7X8X8X8X7X7X4X4X^.^.L.~.P.^.^.^.^.^.^.P.X.y x 1 a } @.f.f.b.n.f.b.@.V.D.J.L.L.~.~.L.n.5 I ..n.C.F.L.L.L.~..XJXJXJXJXJXJXJXJXJXGXoXiXdXdXsXrXQ.Q.T.T.I.I.l.<.6.7.h 9 % > 5 t g.BXJXBXA wXpXiX>Xx.x.I.r.l.y.U.U.t.t.t.1.1.1.<.<.-.9 % $ o & 7 7 7 7 & B XKXCXyX3XT.;.7 O o O b .XxXwXqXaXVXBX0X+X1 0.n < v v < O & 7 q s q q 8 e g g q 8 8 e h 5.j.9.0 + 0 r 1 1 z c Z A Z Z I a y f.A.P.=X5XwX XM u n B B B b M oXJXJXGXoXt K ] B.F.P.6X5XqXqX*XH.k.Z $XcXMXrX1XuX}.JXJXJXJXJXJXJXJXJXJXJXJXJX).vXPXPXPXPXPXPX-XwX5X@XzXGXBXnXvXkX+XS A k.=XK.H.H.=X[.9Xf.E / / / / / / ^ W ( F 5XwX{.FXGXgX%.oX#XXXf.=X4X6X6X6XZ.R R Y R R R L o.&Xk.S S %.V %.V oXgXhXkXL Y ..{.kXcXcXcXcXzXhX} F D D H nXGXBXnXnXoXS %X#X#X5.6.6.q.e.9.kXzXzXcXnX|.7.y.Y.w.XXcX%.BXBXFXPXPXPXPXPXPXPXPXPXPXPXnX].zXzXXXkXkXzXcXzXzXkXzXkXcXkXkXkXgXoX.7 $ $ & 7 8 8 7 7 u g.-X0X0X;Xq.7 o . . . o o u .X-X=X=XwX0X-X).oXz 0 X : 5 @ $ ; y d h m d q e g g e 8 8 s ;.7.x.b o.*X*X-XOXoXO.n z M M v a v K = a .k.{.x M 0.g.9.B B N z g.h.FXJXJXJXA J [ s.d.G.P.4X4X4X=X=X6X5Xh.c.T.T.1XuX@XgXJXJXJXJXJXJXJXJXJXJXBX`.BXPXPXPXPXPXPXPXkXkXFXGXGXFXBXnXcXhX).oX#X#Xg.k.H.*Xk.h.Q / / / / / / / ^ ^ W E Y -X5X*XzXbX].%X$X#Xh.6X4X6X8X8X8X8X! R R R R R E J k.].gXgXhXkXkXzXcXcXcX..Y R E E T ..[.OX-XkXjXhXG D H ] nXnXvXvXzX%.gXhX 5 z c z x C S _.).S B n d u 0 9 > : j x /.O.Z x B ).'.g.g.O.O.O.a ..Z.b.f.f.H.6X8XtX8XtX7X7X4X^.^.^.L.L.L.~.~.G.G.~.~.G.p k 2 a I U U b.X.n.@.n.n.V.C.G.G.L.L.L.L.G.p I U n.B.F.F.F.G.Z.zXJXJXJXJXJXJXJXJXJXoXIXIXZXiXrX1XR.T.l.I.I.l.6.h e 9 O 6 a t NXJXJXGXk.aXSXSXSXZXZXuXrXeXT.r.y.y.u.u.u.u.u.u.U.I.Y.y.;.$ $ 7 7 8 8 8 7 , Z X-X@Xc.9 o o . . . . . 0 X-X*X*X*Xx + k , . . @ 2 o * q d 4.7.7.4.s 8 s g 8 e e g 4.7.5.a J.P.=X=X-XOX|.j.B M x c a I , , * 5 A _.C _.].'.j.0.B u A A h. XGXJXJXFX+.U { a.n.D.P.P.^.P.4X4X7X6XN l.R.1XiX.XlXJXJXJXJXJXJXJXJXJXJX].PXPXPXPXPXPXPXPXPXPXGXJXGXFXFXBXnXzXhXS $X#X#X$XS *Xv.9XP / / / / / ^ / / ^ ^ W R L 5X-X-X-XzX|.gX$X#X[.4X6X6XtXtX8X7XZ.Y Y R Y Y R E K kXkXkXzXcXvXnXnXnX{.Y Y E E E E E ^ ( ( R ) T T E W +.zXzXzXkXXXS kXkXgX + p I I U f.] n.U n.n.n.N.S.G.G.G.G.L.G.F.i U a.B.F.F.S.F.F.|.HXHXJXJXJXJXJXJXJX].IXIXAXiXeX1XQ.T.T.T.I.v.q.h y ; o } N $XJXJXJX+X5XAXSXAXAXAXZXsXuXyX1XI.r.y.y.U.U.U.U.E.Y.I.I.T.:.$ $ & 7 8 8 8 8 8 9 B '.x.6.& . o o . . o & & & x {.k.v 7 ; $ . o o o o = o 7 d 4.5.z.c.q.s 8 e e e 8 e h ;.7.4.K K.P.4X6X5X-X-Xh.g.v.h.g.v + O $ .k.&X*X+.g.|.}.}.9.B z Z Z g._.JXJXJXJXJX Xt a X.Z.J.P.P.P.P.^.4X6X6XN ;XeXZX|.JXJXJXJXJXJXJXJXJXJXJX].PXPXPXPXPXPXPXPXPXGXPXGXFXFXFXFXnXkXgXS $X#X#X#X).PXJXOX/ / / / / W ( ^ ^ ^ ^ W R I -XwX-XOXvX].gX%X#X`. . .k.6X8X8X8X4XU H F F H Y Y T [.cXzXcXnXBXFXFXnXF Y R E E E E ( W ( / / / / W W U 6 j t N +.+.S S A B b d u l k k + k 1 : k C ).0.z l b O.h.h.h.k.h.g.O.x l .k.4X8X8X8X7X7X^.^.~.L.G.G.G.S.G.G.G.G.G.G.m.o 2 a I U U X.X.n.U ] n.N.C.S.S.G.G.G.G.G.B.i n.m.B.B.C.S.S.h.HXHXHXJXJXJXJXJXJX%XjXLXZXiXyXeX1XT.T.T.T.Y.l.4.5.n > < FXJXJXJXLX[.qXIXSXSXAXAXsXuXuXuXeX;XI.y.I.y.u.E.W.Q.eX1X}.T.q.& & & 7 8 e e e e s g g :.-.& $ o o o $ & 7 7 & ; u q s s 8 & o o O $ . @ ; q h 6.l.c.R.l.g 8 8 8 8 8 s g ;.6.5.v A.P.P.4X5X5X*X&XH.Z.k.H.&XH.Z.f.K.*X=X=X*XS ].}.`.9.k B C Z O.k.cXJXJXJXJXS - a ..f.V.J.J.J.P.^.^.4X6X=Xz.iX>XhXJXJXJXJXJXJXJXJXJXPXGX|.PXPXPXPXPXPXPXPXGXGXPXGXGXGXGXGXnXkX#X%.$X#X#X#X%.FXGXk./ / ] k.-XjXjXOXa D D Y Y k.5X*X*XOXvXx gX.;.m ;.4.6.}.vXvXcXkX).k zXGXDXPXGXPXPXHXGXGXGXJXHXFXcXhXkXkXzXzXvXcX%. = @ 5 1 k c . .A S A Z b b d z u r # < + : * x S _.S n l Z h.v.h.[.h._.g.g.S z c k.7X8X7X7X7X^.^.L.L.G.F.S.S.G.S.G.G.S.S.S.I - a K I L U U X.] ] n.m.N.B.B.S.F.G.G.G.G.B.i a.S.B.B.d.S.f.cXJXJXJXJXJXJXJXJXJX'.SXMXyX;X1X1XR.c.T.T.x.R.yXmX@Xg.V gXJXJXJXJXh.aXIXIXSXAXZXsXsXuXuXyX1XT.I.u.Y.Y.W.2XrXuXdXsX3X}.; & 7 8 e e e g g g -.-.,.g & & $ $ $ $ & 7 7 7 q d h ;.;.s ; $ $ & & & & 8 s h q.x.T.R.l.h ; 7 7 7 q e g ;.7.7.p D.J.P.P.P.K.P.^.^.L.G.C.Z.K.A.K.H.K.K.=X*X{.O.j.9.z x B Z Z S *XXXJXJXJXkXj 5 p ..b.n.D.G.J.P.~.~.^.^.^.!.dX'.JXJXJXJXJXJXJXJXJXJXJXcX#XPXPXPXPXPXGXPXGXGXGXGXGXGXGXGXGXBXkX%.+X#X#X#X$X%.vXnX] ^ k.FXGXJXPXHXGXPXjX{.o.| wX5X-X-X{.mXk |. 6 6 6 .+. . .Z Z Z B N b d u 0 # : : : : 1 N g._.S x S |.[.v.[.[.'._.).S S M 6 H.7X8X7X7X7X^.L.L.F.F.S.S.S.S.S.S.S.S.S.d.- t p K K U U U X.] ] a.M.B.B.B.S.S.S.S.G.S.n.p d.B.B.B.S.D.|.JXJXJXJXJXJXJXJXJXzX>XyX>X;X}.;XT.R.R.c.R.yXCXmX9X].C ).JXJXJXBXN VXUXIXSXAXZXsXuXsXuXuXeX1XT.T.R.W.Q.eXuXdXAXSXSX9Xs % 7 7 8 e g e g -.-.-.-.g 7 $ $ $ & & 7 7 8 y f ;.6.q.7.h ; $ & 7 & 7 7 8 s ;.q.l.c.l.l.h 7 ; 7 7 8 e e f 6.9.u f.A.K.K.J.D.K.^.^.~.~.G.D.K.A.A.A.K.P.P.K.K.&XO.z , B B C A h..XvXJXJXnX< @ a I f.b.n.V.S.F.F.G.L.~.~.L.v. XNXJXJXJXJXJXJXJXJXJXJXJXzXgXPXPXPXPXPXGXFXGXGXGXGXFXGXGXPXGXcXgX%.$X#X#X$X$X/.vXvXR F [.HXGXPXGXPXPXPXPXPXPX-XOX{.&XjXvXzXS k S %.].$X).h.k.h. .| K ^ / / / ^ / ^ ^ ! FXGXGXFXFXnXhX%X%X%.D D D F Y R W W W W T o.#XgXgXhXhXkXkX9.u.u.u.u.u.E.u.E.E.E.E.E.E.w.:.8.hXkX%X).nXFXPXPXPXPXPXPXJXPXPXJXPXPXPXJXBXvXvXcXcXcXS $X$X$X$X$X%XS oXvXvXnXFXFXGXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXFXBX].gXJXJXJXJXJXPXGXGXGXPXGXGXJXJXJXJXJXS cXBXFXFXvXcXnXPXPXGXoXJXJXJXJXJX", -"JXJX].p.p.{ p.{ { { Q ! ! ! L L J L L L ! _ { [ s.s.M.s.M.B.S.S.C.F.C.F.C.V.n.X.I v o.k.a b.~.L.G.J.L.G.L.G.G.G.L.G.L.L.L.J.L.P.=X=X*X&X.Xk.k.k.H.f.I c c v c c c k 5 c | O.PXGX X-XwXVXwXmXmX-X-X*XOX&X&X&X*X=X*X*X{._.O.v 6 < > > 6 6 6 .+.o.O.N Z C Z B B m l 0 0 k : # # # l Z A O.M A }.'.'.'.'.'._.).+.S Z V r K.7X7X7X^.^.~.L.F.S.S.S.B.d.d.d.d.d.S.d.[ * 2 i K L U ] ] U ] a.a.M.d.d.B.d.S.S.G.S.S.U L B.B.d.B.d.h.JXJXJXJXJXJXJXJXJXJXoXyX;X}..X;X;X;X;X;XyXKXCXmX9X XA C oXFXHXHX%X.XSXSXSXZXsXsXiXuXuXuXrXeX1XR.1X1X1XrXZXSXSXSXmXz.;.; ; 7 8 8 e e g -.-.:.:.-.e 7 ; 7 7 8 8 e g h 6.z.r.l.e.h & $ & & 7 & 7 e g g >.l.l.l.7.6.s 7 ; 7 q 9 % 9 b B 0 = b.D.K.J.K.V.D.G.L.G.A.D.J.J.L.J.J.L.P.P.P.K.H.k.r u A 9.)..X+XJXJX#Xk 5 3 K I ..b.N.C.F.B.S.S.F.G.S.a.9.,XJXJXJXJXJXJXJXJXJXJXJXJXcXkXGXGXGXPXPXGXGXGXFXFXFXBXBXFXGXFXkX].].$X#X#X#X#X).cXX;X>X;X3XyXyXCXSXKXVXxX-X{.S x z x zXHXHXoX,XyXZXZXsXiXuXiXiXiXZXiXeX1X1XrXrXiXZXIXVXVX@X4.>.s & & 7 8 e e e -.-.,.:.:.-.e e e e d -.:.q.l.l.l.l.l.6.g & & & 7 & 7 7 e -.-.>.q.e.l.l.q.h d q 9 7 q % , ; : ; * 5 Z.K.J.K.K.A.J.F.J.J.J.L.G.G.G.G.L.L.L.P.P.J.D.V.f.a n '.Z JX#XV 5 2 6 K I U U n.V.F.C.B.d.d.d.d.i.I S FXJXJXJXJXJXJXJXJXJXJXJXJXBXhXFXFXFXGXGXGXFXGXGXFXBXvXvXnXFXvXhXV %X$X$X$X#XS gXvX{.F 4 D O.GXPXGXPXPXPXPXPXPXHX-X*XoX#XoX#X 1 t t l 6 . . .+.h.+.g.A B y a u f u r V C 0 # # : , : # 9.}.`.j.`.`.`.].`.).+.A N x z a K.^.^.^.L.G.G.S.d.d.p.p.p.p.p.p.p.p.i.! z M M l K G L ! ! ! [ { s.s.s.d.d.d.S.d.d.p.~ = s.s.s.d.S.'.JXJXJXJXJXJXJXLXGX C zXHX).yXSXLXZXZXiXiXZXZXZXNXZXyXiXiXZXZXHXSXVX0X9.6.e.6.7 & & 7 8 8 e g g :.:.>.:.;.-.h h h 6.e.T.T.T.T.l.l.>.g % & & & & & - s ;.;.>.6.6.l.l.l.>.>.m b u q & 9 9 7 , ; % a n.K.J.D.J.L.J.J.L.J.G.G.G.G.F.F.G.G.G.S.G.S.B.V.C.M.K +XZ @ @ 2 4 K K ] #.m.m.V.C.C.d.d.p.i.' ` v h.h.k.GXJXJXJXJXJXJXJXJXXX`.%X#XFXFXnXFXGXFXGXGXFXFXBXcXzXzXzXgX%.].%X$X%X%X#X%.zXzX{.F D D D [.GXGXJXPXPXPXPXJXvX{.[.OX%X|.|.oXgXhXhXcXo.E I BX[.&Xk.j.R / / W ( W Y OXnXnXvXvXcX%XV +X#X#X#X#X#XO.D D F F Y Y +.`.).`.oX#X%X%X].;.6.4.4.,X jX'.VXVXmXMXmXMXiXMXZXZXLXLXDXMXNXNXNXCXVXwXv.;.l.q.6.7 & & 7 7 7 8 e ;.;.,.>.q.6.7.6.q.q.l.T.R.R.R.T.l.6.s $ & $ $ $ o $ 7 g :.>.6.>.q.l.l.l.l.z.9.A 9.b , 9 , , * * * * U V.V.F.J.J.P.P.L.L.L.L.G.G.G.G.G.S.F.F.S.S.S.F.S.M.[.gX5 - 3 4 G L ] [ s.d.S.B.B.s.s.p.' ` / a *X=XK.v.JXJXJXJXJXJXJXJXJXoXPX#X`.FXGXFXFXFXFXFXGXGXFXvXzXhXgXgX].`.%X%X%X.>.>.0.gXhXlXhX$X}.e.y.E.E.e.].#X$X%XX+X'.9.x 0 , + X @ S {.pXwXVXmXmXxX9X0XyXMXZXLXZXZXMXMXyXMXwX3XN m e.s 7 7 & & & & $ & 7 ;.6.w.l.T.T.T.I.T.c.T.Q.;XR.c.l.f & . O O O o o o & e g :.>.q.6.l.q.l.l.l.z.x.|.XX`.l ; ; % ; , ; , y K m.B.S.G.G.L.^.4X4X6XP.P.F.J.G.G.G.S.S.S.G.G.F.f.xXk 3 3 4 D T [ { p.s.d.M.s.s.p.' ' / ) I O.wX6X[.nXJXJXJXJXJXJXJXJXJX#XPXPXPXGXGXGXPXGXGXFXFXFXBXcXhXgX%X%.). > z A O.g.g.g.g.g.m ..L.D.a 1 l j 1 , + : 1 1 , 0 9.}.;X}.}.{. X.X{.k.o. . . .v v a 9 n.F.S.d.d.p.i.' ` ` / ' ` ' i.` ( p Z Z C XHX].3 D J ~ ) ' ' { i.i.i.i.i.i.` / ) ] p.s.p.s.d.].JXJXJXJXJXJXJXJX,XK.7XaXVXVXVXCXaXsXmXyX0X>X@X].9.b 0 = + @ @ 6 6XqXqXaXaXVXqX*X*X0XMXMXZXZXZXZXMX0XyX3Xj.h f m & $ $ & $ $ $ O $ 7 h 6.l.T.Q.eX2XQ.Q.Q.Q.;XR.T.;.* o o o . o o o o & 8 s g h ;.6.<.<.<.l.l.c.c.;X>XlX.0.zXkXkXgX%X$X+X%.XX#X#X$X%X + < z Z S 0./.+.0.5.v P.P.A.t 0 x k k 6 # : 1 : # B }..X.X.X.X&X.X&XZ... . .N v a I v 2 n.M.d.p.{ { ' ` / / ` ` ` i.i.` G V S Z %.JXJXS 3 F Y R _ _ _ _ _ ' ' ' ` ` / / [ a.{ p.p.d.[.JXJXJXJXJXJXJXJXJX@X6XqXwXxXMXyXyXyXyX>X;X;X.X}.9.b 9 * + @ = } 7XtXtXtXtX^.7X^.J.m.Z.yXiXZXZXiXiXyX>Xj.0 q d u O $ O $ $ $ O o O 7 s 6.x.Q.eXeXQ.eXQ.eX1X;Xl.u O O + + % + o o O 7 8 8 e q s g ;.>.6.q.w.l.c.;XyXxXBXNXhX% ; 9 9 u m 5.9.}.;X}.}.}.`.x.z.9.d 3 G L n.n.V.V.B.B.d.p.d.U +.jXjX .3 F Y E _ ( / / ) i 5 6 6 t | X.H.qX{.9XVX_.GXHXJXJXJXJXJXJXJXJXFXcXPXPXPXPXPXPXPXPXPXPXPXPXPXPXFXoXk ].].S oXhXnXGXJX].XXkXGXJXk.R / / / / / / / / / E I oX%XC H.8X6X=X=X=X=X=X=XF Y Y H Y Y Y G oX > r r 0 6 v M Z A 0.GXLXGX%.Z -X-XgXgXgXgX-X-X-X-X_.O.c c l r r , + + < z 9.9.j.j.9.5.a ^.P.J.n.6 0 M z k t 6 : # : : N }..X{..X*X&XZ.k.j.f.I } I I a v a 5 ] a.{ { ' _ ` / / / / / / ` ` E t S Z S JXJXHXv 4 F T R W ( ( _ _ _ ` ` ` / ` [ [ { { { s.k.JXJXJXJXJXJXJXJXJXhX5XwX0X9X9X0X0X0X>X;X;X.X;X.X9.b 0 ; O @ = Z.^.^.^.^.^.^.^.~.F.s.T 0XyXiXiXiXiXyX>Xx.B d f m 0 o o $ & $ $ o $ 7 u 7.T.2XeXeXeXQ.2XQ.Q.c.q o O O O * % * O ; q q e q q s s g h >.6.q.l.l.R.1XyXyXMXMX`.% , 9 b B 9.x.e.e.5.5.5.4.4.4.5.6.4.3 G ~ a.m.N.a.p.` _ U y `.$XhXwX*X> h.a 4 Y Y G 3 < x x x V .f.H.6X0XiXCXKX'.JXJXJXJXJXJXJXJXJXJXXXPXPXPXPXPXPXPXPXPXPXPXPXPXPXJXBXkXS FXvXGXPXJXJXJXJXS V %XGXo./ / ` / / / / ` / / ^ R | gX%X%.h.*X6X=X=X=XK.=X=X} Y Y Y Y Y Y T L {.jXgXhXzXzXgXK T R E E E E E E W W W T ! @.Z.+.F Y Y ].XX].,X$X'.z.9.5.h e ;.;.;.4.5.hXgX v v 6 J.L.P.4X4X8XaXAXVXSXVXAXSXSXIXIXUXUXUXPXPXBXmX9X-X[.h.t M S Z b 1 1 l x x Z S BXGX%.Z &X-XgXgX-X-XOXOX*X[.+. .Z C x l 5 1 k o % 0 n 5.7.5.5.5.f ^.P.P.J.b.a 1 x c l k j 5 # + : 9. X X{.{.k.k.f.f.I I I N v a a a p 6 L ] _ _ ( ( W / / ` / / ` ` / 6 O.S C DXJXHXGXC D F R E W W ( W ( ( ( / / ( ] { { { { s.H.NXHXJXJXJXJXJXJXJXlX*X5XpXlXyX>XyXyXfX>X;X;X>XXX9.b 0 ; > A $XO.^.^.^.^.~.~.~.G.G.d._ 3XyXMXiXZXiXMXyX;X}.z.6.7.e.z 0 O $ $ $ $ & - s 7.R.Q.eXeX1XQ.Q.R.T.r O o X X X + % O 7 s h f h f d s h f h ;.>.w.r.l.T.;X1XyXyX>X, , 9 d 4.z.c.l.b j : # # 9 9 d h h 4.y J [ [ p.[ p.i.i.K m u @X-X-X5Xh.cXoXx . + , 1 k z x V C A o.Z.*X@X>XyXCXKX].HXJXJXJXJXJXJXJXJX#X#XPXPXGXGXPXPXPXPXPXPXPXJXJXJXFXnXzXXXGXJXJXGXPXJXzX].oXGX+X..^ / / ^ ^ / / / ` / / ^ T {.hX%XS S #X[.k.H.=X*X=X=X&XG Y Y Y F Y Y Y Y X.#XkXkXhX#XF Y R E E E E E W W W ^ W W ^ W W W R I -X%X%X`.:.1.1.r.U.E.u.>.-.e 4.6.9.gXX;X.X}.g.b < * 1 ).).gXv.^.^.^.~.~.~.G.S.d.' .X>XyXiXiXiXyXiXyX;X.X;Xx.c.c.j # o $ $ $ ; 8 f e.T.Q.Q.1XQ.R.R.x.9 % o . X o + o + % s m 4.5.7.5.4.4.;.>.;.;.>.w.r.l.T.Q.1X1X;Xy * 9 u ;.7.c.x.4.k x 0 , : , 0 e f m ;.h 2 ( _ ) G 2 ) G y B b 9X-X-X5X].Z = = = = @ > : k x Z A g.[.k.>X;X>X>XNXPX].HXJXJXJXJXJXJXJXgX).PXPXPXGXGXGXPXPXPXPXPXGXGXGXFXBXcXhX$XGXJXJXJXGXXX%XPXPXPXgXR ^ / / ) Q ~ Y Y H Y R W L zXgX%X%.C +X$XC |.N o.k.K.*XZ.F Y Y Y H H Y Y T L hXzXhX#XL Y R E E E E E E W W ^ ^ ^ W W W R I oX#X#XZ <.<.t.t.t.u.u.u.u.u.u.,.-.h 9.oX].nXnXnXvXnXvXvXnXvXhX].oXzXgXC kXzXhX].5.q.r.r.u.u.Y.E.4.;XXX|.q.e.e.w.e.9.S .I K p a a p K p K I @ 3 L J H H ( / / / / / / / G A O.S #XJXJXJXJXGXS D F Y R R W W ^ ^ ^ ^ ^ P [ { { { d.F.L.k.@XJXJXJXJXJXJX].BXSXZX0XyXyXyXyXeX;X;X}.}.`.0.b > + > = * x }.K.~.~.~.G.G.S.d.p._ v.>X0XyXyXiXyXsXiXyX9X>X;X;X;XB k $ $ $ & 7 s h q.T.Q.2XR.R.T.e.* % O X X o O X O X 9 f 5.z.c.T.x.l.e.q.6.6.:.:.6.q.r.T.T.R.R.5.$ , q d 4.z.x.7.n j , : # , 9 q d f f h m d 3 H 4 y B , 0 b B B {.*X=Xk.S @ = 2 2 3 4 i a 6 x C O._.}. X;X;X>X>XyXHX].JXJXzX|.].hXJXoXoXJXPXPXPXFXGXGXGXGXPXPXPXGXFXnXnXvXzXhXoXJXJXJXGX`.NXPXPXPXPXk./ T o.-XzXFXHXbX[.J T H T h.jXhX$X).%X1 1 gXGXgXk.&XZ.+.jXjXU H Y Y Y Y Y H R OXzXhX$X#X%.D H E E E W W W W W W W R R T o.BXS oXC :.<.1.t.t.u.u.u.u.u.u.u.u.y.r.:.`.vXBXnXnXvXvXvXvXvXhX`.$X+X}.}.}.z.}.}.7.7.6.q.r.I.Y.u.Y.T.}.+X,X6.6.q.e.e.e.S X>X;X+X.Xj.Z c < * > : @ @ 9Xh.D.G.G.S.F.d.p.' [ +X.X>XyXMXiXMXyXsXiXMXlX0X0X>X0.% $ & & 8 e f 6.l.R.2XQ.Q.R.T.y O % O O O O + O O o q m j.v.c.;X;XR.x.l.6.4.:.4.:.6.e.l.T.;XT., ; 9 9 d m 5.e.4.f 1 , , , 9 q b e f b m h h d u b B 5.b , u b 9.O.*X[.zXV @ 2 3 p K K L K I 5 C Z S g.}.@X>X0XyXyXCXnXoXGXJXPXJX$XS oXPXPXPXPXPXGXGXPXPXGXGXGXGXFXFXnXvXcXhXgXS GXJXJXC GXKXPXPXPXPX] Y '.cXFXHXPXJXPXHXFX{.k.{.kXkXhX%X).kXx $XDXcX{.=X*X*X{.GXKXPXo.F T R Y Y W R -XvXgX%.oX#X%.G 4 D D F Y Y T T P U o.OXcXPXPXBXV -.<.<.t.t.u.u.u.u.E.u.u.u.u.u.u.y.8.nXnXvXvXcXcXcXcXzX).|.R.;X}.T.}.}.x.}.7.4.h w.y.u.Y.Y.e.yXr.w.`.4.8.4.6.r.e.V %XzXJX : @ @ `.LX@X'. .v v a c .X>X.X.X>X0XpXmXwXtX8X8XyXbXMXlXyX9.% & 7 8 e s ;.e.I.Q.Q.eXQ.R.l.$ O O O X + % + $ % o u 5.z.c.;X;X1X;XR.l.6.:.4.;.6.7.e.z.c.R.6.% , 9 q u b 4.7.5.f 9 , 9 9 9 u f b f h ;.m h b b b n B x b : l 9.k +XGXGX6 = 2 D G ! ] ] ] ] K 6 C C g.'.>X9XyXyXMXSXUXoX].PXJXPXPXPXPXPXPXPXPXGXPXGXPXPXGXGXFXFXFXFXnXcXkXhX c x O.4X6X8XqXqXVXVXVXSXSXSXIXIXVXVXVXaX6X6X=X=X=X=XK.H.H.k.h.B u + # + : , , k M 9X-X).V 1 > 1 c v +.{.{.{. Xz l B b 7 0.JXJXJX|.b N .X.X}.c 4X4X4X7X4X4X4XP.=Xk.O.: 6 6 j k k x n y ..f.f.X...X...X.X.U I L I L K l k k x v t D E / / / / / / / c +.S JX%XJXJXJXJXJXGXoXK F R W W W W W E R W ^ T G s.M.B.S.F.L.L.g.JXJX @ S JXJXJXg.>X}.7.b < $X-X-X3XwXmX6X8X7X7X4X4XwXCXMXlX7.& 8 8 e e g >.e.T.R.1XQ.R.x.m + o X O O O $ $ O O O f 7.}..X;X;X1X1XR.l.7.4.4.5.5.9.9.9.j.z.9 , , 9 0 d f 4.6.7.4.h 9 0 9 u q f f m m m m b m b b b n B C x r M `.JXJX$Xk 2 4 D D ! ~ ! ~ Q [ ] 6 M A ].$X0XMXMXMXIXUXUX.X[.#XPXPXPXPXPXPXGXGXPXPXPXPXPXGXGXFXFXFXBXvXcXhXX(.1.u.E.E.E.E.9.zXzXzXkXkXkXhXhX l x v =X=X=X=X=XaXaXVXSXSXSXSXAXaXqXqX8X6X6X6X4X=XP.P.A.f.k.0.z ; + % : > : : n >X>X0.k , < k l c O.]. XOX Xk * N d 9 O.JXJXJXJX0.5.OX.X}.5.k.^.4X4X7X7X7X7X=XK.k.z < j j k k x z r } f.f.n.X.f.@.@.X.U U I U I L N 1 r l V 6 Y W ^ / / / / / / v +.Z GXGXJXJXJXJXJXJXJXZ F R W W W W W W E ^ / / Y ] s.B.C.F.L.L.o.g.h.*XtXtXpXaXVXVXKXKXVXqX6XP.P.J.J.n.b.I a * + : # @ C GXJXGXC OX}.5.z * g.9X-X5X=X=X=XP.P.L.P.P.P.mXnXlXb 7 7 8 e e g >.l.T.R.1X;XT.7., X o O O O O O O o o 9 m 9.v.}.;X;X;X;XT.l.e.7.7.9.z.9.9.9.9.e.* ; , q l d f 4.5.7.5.4.e q q u d f h m ;.b m m b b b n n B Z S C M @XJXLX0.5 2 4 D J ~ ) ) ) _ { { 6 M S {.-XmXmXKXHXKXUXUXaX6X8X_.PXPXPXPXPXPXPXPXGXPXPXGXFXFXFXFXFXnXcXkXgXX@XPXPX].hXhXzXcXzX).].].#XhX k x x {.h. .O.[.5XaXAXSXSXSXAXaXqXqX6X4X4X7X7XP.=XP.P.Z.f.j.A u + : : < 1 # 9.>X}.x 1 : < 1 k x O._. XoXoXg.* } ..< C JXJXJXJX).'..X}.R.c.v K.P.=X7X7X8X7X4X4X&X+.1 r 6 1 k u l 0 a I f.b.n.b.n.n.n.n.U U U L P +.g.j l V D E W / / / / / / / a +.v GXGXJXJXJXJXJXJXHX].D R E W ^ W ^ W ^ ^ / / / J s.M.B.S.F.J.b.4X^.7X^.tX8XtXaXaXaXaX6X7X^.P.J.J.V.b.X.} c ; % + + @ r oXJXJX|._.'.A l 9 N 0X*X=XP.J.G.G.G.G.L.4X=XMX,Xj.7 7 7 8 8 e f 6.v.;XR.R.T.7.u . O O X O O o % % % f 5.6.e.z.x.x.c.;XT.e.e.e.x.x.}.}..X.X}.}.7.d : 9 q q d f m 6.e.7.5.m l d d f b f d b f b b b b b n u x n x x ).HXJX9Xt 3 3 D F T Q _ _ ' ' ! 2 k v h.*X-XmXVXKXSXIXUXSXqX6X6X1 PXPXPXPXPXPXPXPXPXPXGXGXFXFXFXFXBXvXzXhXX;Xl : : 1 1 k c Z _.]. X|.g.r 6 Z.v 1 X>X3X0X-X*X}.7.; 9 0 e b b m 6.7.7.e.5.b m b d b d u b m d b u l b 0 n x B A C FXHXoXz 3 p D D H T _ _ ` _ G * 5 z .k.*XwXVXKXSXSXSXSXVX8X4X7Xj PXPXPXPXPXPXPXPXPXPXPXPXFXFXnXnXvXcXhXX.X>X Xm m 4.m e.x.zX S JXJXJXJXhX[.AXSXAXAXaXaX8X7X4XP.=XP.4XP.P.L.L.J.V.b. .g.n 1 * : : 1 ;X;X>Xg.0 j : 1 6 l V O.].'.}.j.B , .Z.r 6 kXJXJX0.v.x.x.z.l.e.7.v Z.H.^.4X4X4X4X4XH.k.r < 0 0 0 q u 5 } f.b.n.n.D.V.V.m.a.n.U U P ] _.kXx v 4 W ^ / / / / / / ( I o.K n._.JXJXJXJXGXGXPXHX_.F E W ^ ^ ^ ^ E H G G ! p.{ M.d.B.S.F.G.f.^.^.^.^.^.^.^.^.^.^.~.L.L.L.F.V.f.f.| N 0 * , 7 , , < < 1 S vXLX`.).Z M r A.s.' ' i.i.i.p.p.p.K.0X}.q e e q 7 8 q b j.v.3XqX=X=Xz.q 7 & o O X o * q b 4.7.l.r.l.l.w.6.6.6.6.6.5.7.c.>X0XyXwXsXaXwX5XK.z.4., q b q d b 4.4.7.7.5.m m f u 0 u w u d b d l b b n n V 0.C zX+XC # a p K L F R R _ { { J # > 6 z | Z.=XwXVXVXVXSXSXAXpX7XP.K.#XPXPXPXPXPXPXPXPXPXPXPXPXGXFXnXcXcXhXgX%X%XC ].$X).V cXPXPXPXPXPXPXk.) H / / / / ^ W ^ E ! XhX{.6X6X6X=X=X+.].OXOX#XL W E F I hXjXzXzXcXcXcXzXXXD Y R R R E T K oXGXPXPXKXO.4 F K ].|.k oXBX_.oXFXNX;.h g h ;.;.vXPXPXPXPXS ].%.%.+X#Xx .6.;.4.4.z.}.3XMXZXZXaXaXtX7X=Xj.7.q 9 q b b f ;.m 4.7.7.n b b u 0 9 k u u u l b b n l V S ).oX#X1 : 6 K K I U ] [ [ [ { s.X.t 5 6 c o.K.6XqXVXVXKXVXaXaX4XP.J.3XPXPXPXPXPXPXPXPXPXPXPXPXPXPXJXBXzXkXgXXyXyXiXiXpX3X5X3Xz.z.7.; q q d d d d m 4.8.4.b b d u l x b b u 0 b b 9.Z GXJXJXJXS < > a I K U U $.[ m.M.M.B.b.@.X...| Z.=XqXmXmXVXVXaX6XL.J.N.-X].PXPXPXPXPXPXPXPXPXPXPXPXPXPXGXBXcXhX.6.q.7.7.b < K.P.4X^.7X^.P.P.f.t 9 0 l z b 5 I f.n.D.D.V.V.V.n.] U U U [ I GX#Xv x 2 W / / / / / / ` N o.+.Z.N.M.+.GXGXJXJXJXJXJXJX_.# = 3 3 p i G L ~ ~ { { p.s.d.d.B.B.f.NXv b.S.~.~.~.L.L.L.G.G.F.C.V.n.k.f.M z r 0 u 0 u u 0 q l x V C `.JXJXJXJXg.V.d.M.C.V.V.D.H..X;X;Xq.d . ; s d h B h..XwX6XC.A.N ; e s s % & s N z.x.T.R.T.I.l.r.w.w.e.6.5.7.T.R.eXyXyXrXeX3X3X3X;X7.e.z.0 9 q 9 9 7 , b m 5.4.m b b n B 9.B V V 1 b 9.[.$XJXJXJXGXC : 5 a I ..U ] n.n.m.M.s.M.m.] ] ] [ K.K.*X-X[.+.k.P.J.A.k.9XHX#XcXPXPXPXPXPXPXPXPXPXPXPXGXGXFXnXzXhX$XS %X%XS GX|.PXPXPXPXPXPXPXHX0X) -XPXPX&XT Y H / / ^ ^ W T H.+XFX].k $X$X$X$X`.+.F F D F Y F [.zXhX%X#X).S K F Y R R R R R R R R R R R Y o.FXnXFXFXhXgXgX`.;.<.y.t.u.u.u.1.-.e ;.9.PXJX+Xk V ].hXkXoX$XzXcXvX%X.XuXuXuXuXuX;XdXyXpXdXdXdXdXdXdXdXsX;XT.m ;.+XgX u z b n 1 a X.b.b.D.n.n.n.n.@.@.] ! ~ 4 v k c x x 4 ^ / / / ` / / K Z.o.&XZ.A.N.|.JXJXJXJXJXJXJXJX].a 3 6 4 G G J ! ~ [ { { p.d.B.d.d...JXLX.Xj.D.G.~.L.L.G.G.F.C.A.V.Z.k.+.Z n b l l b d l b l b V V n `.JXJXJXJXNXk.V.V.Z.H.*X*X*X3X;XR.m f o ; q d f B g.{.*X*XA.H.9.; e e s 8 . ; y b 7.x.c.T.T.l.I.r.r.w.q.6.q.e.T.R.1X1XeX1X1XeX1X3Xc.q.z.z.4.& , , : # + & q 0 b b b m B 9.0.9.`.). .r }.].JXJXJXJXJXM # t I U X.U b.n.m.m.a.a.a.[ ] [ [ _ $.v H.K.K.P.=X=Xk. XJXJXJXGX].PXPXPXPXPXPXPXPXPXGXGXGXFXBXvXzX S FXJXJXJXZ c =XwXqXqXqXqX8X6X=X=XH.K.P.P.^.P.J.Z.f.k.k..X.X.X.Xc.c.z.5.y r t * : 0 r l l x V x x r 6XqXqXqX=Xc + ; f h h ;.>.4.6.7.5.B r K.P.L.^.7X^.^.K.Z...< x M < X a } b.b.n.b.n.b.] ] ] ~ ~ D D J J 6 v x x 2 W ^ / / / / G o.+.{.&XV.$.+.GXPXPXGXHXPXGXJXGXc t 3 K G G L L ! Q [ [ [ $.d.d.d.U FXPXJXJX#Xh.H.G.G.F.S.C.F.D.Z.Z.f.j.O.Z Z n n b n b n M v V x x ).HXJXJXJXJX9Xk.H.H.*X-X-X>X3X;XT.6.s 7 o ; 7 9 q b A h.*X*X&X.XA ; e s e q $ $ 9 d B z.x.c.l.l.l.1.q.q.6.6.e.e.T.T.1X;X1XR.Q.1X1X1Xx.e.z.z.9.* % + + + , : , 9 u b m 5.9.0.0.`.}.{.k.M A GXJXJXJXJXJXn * a } ..@.b.n.m.m.m.a.[ [ { [ _ { _ K k.H.K.=XP.k.].BXJXJXJXJXJX%XhXPXPXPXPXPXPXPXGXFXFXBXBXvXcXkX#X%.$X%X$X%.kX#XPXPXPXPXPXPXPXPX-XR jXPXPXPXPXFXH.J R ^ ^ T vXOX&XBXkX).$X#X%X%X%X a } ..X.U U U U U ] ! G J R T R 4 z x 5 D R ^ ^ / / / J o.+.+.*XH.N.N.oXGXHXPXHXGXGXJXJX%.4 4 p 4 G G G ! ! _ [ { { d.s.s.X.cXJXJXJXJXJX-Xj.n.d.B.B.B.M.m.b.f.f.h.h.g.A N Z M M M C C C x k %.HXJXJXJXJXJX].&X-X-X-X0X3XeX;XT.R.z.h q & $ & ; y m j.{.OX*X.Xj.9 e q e e $ . ; 9 d 4.e.l.e.1.<.q.>.6.>.5.e.e.e.T.T.R.W.R.R.R.1X;XT.x.}.c.9.9 . % 0 B B Z V q b m B B 9.9.9.9.'. X.Xg.cXHXJXJXJXJXDX1 5 v } X.@.m.N.M.m.] $.[ [ { _ _ _ _ K Z.H.P.H._.nXJXJXJXJXJXJXJXJX].PXPXPXPXPXPXGXFXBXnXnXcXcXhXgX].%.#X%X$X%.JXXXPXPXPXPXPXPXPXPXX3XdX9.u.nXJXGXXXcXcXcXkXzXkX).S %.zXnXBXBXcX].oX > 1 1 k j -XwXwXaXaXwX*X> * 9 q h ;.6.5.j.5.9.B l a J.J.L.^.P.P.J.D.n.@ % # + + O * 5 p I I L K J i # K Y R Y R i x c 3 Y E W ^ / / / G o.O.+._.&X$.$.+.GXPXGXHXHXPXHXGX_.i 4 p 4 G G G L Q _ [ { M.M.s.p.n..4.;.N 9.9.e.z.I.T.T.T.T.T.R.;XT.T.}..X}.0 O * b 5.0.0.`.V m f m 8.5.4.5.9.`. XOX[.].JXJXJXJXJXJX: l | o.f.n.m.M.$.$.$.[ [ _ _ _ _ ' ` K k.H.J.[.HXJXJXJXJXJXJXJXJXGX`.PXPXPXPXPXGXGXFXBXnXcXkXgX%X%X%XS oX$X#X].JX].PXPXPXPXPXPXPXPX-X) jXPXPXPXPXPXPXPXPXvXnXPXPXGX*X XS $X%XgXgXgXgX 5 j k O.wXVXwXVXqXwXk.* ; 0 h 5.5.7.z.j.g.9.n l 5 A.J.L.P.L.J.J.V...X + : + * * # + = y t v M O.h.a F Y F Y i v x 4 E W W W / ` / 3 .O.O.+.{.Z.N.o.kXGXGXPXHXGXPXPX).p p 4 p G G G J ! _ [ { { s.p.s.a. XJXJXJXJXJXJXJXJXh.i.i.' p.s.[ b.b.b.k.k.f.h.+.N c l t c c j 1 %.PXJXJXJXJXGX< >XhX9XyXyXyXeXeX2X1XeX;X>X>Xm . ; s 6.j. X-X9X9X_.7 q q 8 $ . O 9 u f 4.>.6.6.>.;.;.m M 9.j.z.e.l.I.I.I.I.T.T.T.T.T.;X>X>Xz O 7 e 9.9.}.}.}.b f m m m m B 9.x.|.@XoXZ JXJXJXJXJXJXj c .f.b.V.N.M.$.$.[ ] ] [ _ ( ( _ ` | Z.H.+.BXGXJXJXJXJXJXJXGXGXPX%XPXPXPXPXGXFXBXBXnXcXhXgX%X%X%X%X#XS %X%.FXGXnX].PXPXPXPXPXPXPXOXR cXPXPXPXPXPXPXPXPXPXPXPXPXPXOX[.`.%X 1 6 l l 0XwXaXaXaXwX=X .% q B 6.z.z.z.x./.g.0.B , y ..F.J.L.L.J.C.@.r z > : # : 1 1 1 1 x C %.+.).Z .5 6 2 @ t z F ^ ^ ^ / / / J a .O.Z O.+.{.$.$.g.GXPXGXPXGXHXGX].a p 4 4 4 G G G ! Q _ ' { { p.i.p.h.HXJXJXJXJXJXJXJXbXF.' ` ' { [ ] b.b.f.f.f.f. .v i 2 = 2 2 6 : /.GXJXJXJXJXBX0 }.hXlXMXyX1X1XeXiXyXyXyXMXCX>X8 7 ;.6.z..X,XjXxX.X9 8 8 8 $ . O 7 9 d h 4.6.;.h f n V Z 9.x.x.x.r.y.e.l.l.l.x.T.x.;X>X0XM % 7 f 5.z.;X;X+X4.q m m m m 4.7.x..X%XOXZ JXJXJXJXJXJXl c .f.b.N.a.$.$.[ [ [ [ [ _ _ ` ` ) .Z.Z.k.vXJXJXJXJXJXJXJXJXGX+XGXPXPXPXPXGXFXBXnXzXkXhXgXgX < l b n V C C x x x %.6 F R E Y 2 J ^ / / / / ~ 6 v O.A C .+.[.| $.| GXJXJXGXPXPXGX].v 3 4 G p 4 G J ! [ _ ' ' { { i.p...HXJXJXJXJXJXJXJX Xs.' ( ` _ ) ] ] f.f.f.f.f.o.I y = @ @ < : + x FXJXJXJXJXhXb l ;X>X>X;X1X1XrXiXiXiXZXZXLXyX5.8 h 6.q.l..X0XlX0X@Xu 8 8 7 $ o . o o & 7 q h h g y n B 0.0.`.}.}.}.;X}.T.T.c.7.z.9.9.}.,XMXC % q f 7.z.}..X>X9.l e b m m 5.9.}..X#X XZ JXJXJXJXJXGXr c ...n.a.a.[ [ { [ Q Q Q _ _ ` ` { Z.Z.V.V._.JXJXJXJXJXJXJX].).GXPXPXPXPXPXGXFXnXnXzXkXhXgXgXgXgXgX%X%X%.].JXJX].kXBX).#XPXPXPXPXZ.T JXPXPXPXPXJXJXPXPXPXJXGXnXcXgX*X{.gXhXjXOXT ^ ^ W ^ / ^ ^ / W F E T J h.#X%X_.].FXGXo.F G G F _..>.4.x.5.7.z.m x.kXBX4.z.;XR.c.c.;XeXc.$XFXGXHXPXJXGXnXkX).V V S $X%XcXvXcX|..X;XuXuXsXsXdXsXdXdXAX3X+XPXPXXXy.0.|.`.+XkX%.FXJXJXJXGXPXGXGXGXPXPXnXS $XkXnXBXFXFXGXPXPXPXPXPXPXPXPXPXPXPXPXPX].GXGXJXJXGXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXvX .d.d.d.d.S.S.S.F.F.F.F.F.J.J.J.V.b.X.} K M ].JXJXJXJXJXJXJXJXcX: c v a f.Z.K.P.4X7X4X=X4X6X-XmXmXnXBXcX0X>X>X[.g.V l > j x k k k j wXqXqXqX6X5X=XH.H.H.H.K.8XqXaX5X3X;X}.x.x.c.T.c.c.z.v qX8X5X*Xt + @ : : > < r 1 OX-XwXwXqX6X5XH.N b 9.j.}.}.}. X X'.0.0 b b 9.M } N.N.U t '.'.O.C x c x < x n M M V z x x 2 R W W ^ / E E / / / ^ ) * > 6 t C C Z O.%.| #.K HXJXJXPXGXGXPX).c 4 4 3 4 4 G L ! Q _ ' { { ' ' p.] gXJXJXJXJXJXJXBX} { { ' ( E ~ [ ] n.f.U b.X.} a 5 @ @ @ 1 : + x JXJXJXJXJXgXd 9 x.;X;X;XR.1XrXiXZXZXLXIXLXKXz.>.,.w.l.I.T.>XyXlX@Xu q e 7 O o o . $ & y u y m 9.0.`.}.|.oX;X;X;X.X;X;X.Xx.j.9.5.9.+XhXx * q h 7.e.}.;X>X;Xb q b m m 5.9.x.oX#XoXA JXJXJXJXJXFXk c | ..b.a.[ [ _ _ Q Q Q Q _ ` ` _ p.m.N.N.M.X.vXJXJXJXJXJXoX].PXPXPXPXPXPXPXGXFXBXnXcXkXkXhXgXgXhXgX k k k k k .qXqX6X=X=X&XH.k.k.k.Z.4XqXVXVX0X>X}.c.l.x.c.T.c.c.j.qXqXwX*X*X: # : : : > 1 r v -X-X6XqX8X6X=X&Xj.g.}.}.|.;X.X}.h.O.r m B B 0.9.v I l x.`.).).O.C Z O.O.r l M n x x x x D R W ^ / / / / / ^ ^ Q i % 5 K a M C C C +._.I U cXJXJXGXGXGXKX%.6 2 D H 3 G G ! Q Q _ ' _ ' { { { p.h.JXJXJXJXJXJXS Q ' ' ' ( ) [ [ ] ] ] X.] X.I a a 3 = > k : + j JXJXJXJXJXcX0 q 9 x.T.T.T.;XuXZXLXIXPXIXKXCXz.6.>.r.r.x.R.;X3X9X>Xb q d q $ . . o . . o $ 7 d 4.5.z.x..X;X>X>X0X,X>X;X+X;X>X;X}.j.B 9.`.|.# ; s m 6.e.x.;X;X;X7.b e m B 4.9.z..X@X XS JXJXJXJXJXJX1 a v U U [ ) _ _ Q Q Q Q Q _ ( ( _ ' M.M.s.{ { '.JXJXJXJXJX%XPXPXPXPXPXPXPXGXFXFXBXnXnXcXkXhXhXgXhXgXgXgX.-.-.;.:.-.+XPXPXPXPXPXPXFXFXzXx OXv /.fXhX7.e.4.m w.7.z.j.z.x.R.6.U.w.4.m c.R.c.v.c.x.z.x.9. k k l &X5X5X*X&X&XZ.k.h.k.k.Z.qXVXKXmX3X.Xc.z.z.c.}.}.z.H.qXqXqX5X-Xl @ : : * * < 0 0 g.*X5X4X6X6X=X&X*X X|.|.}..X@X.Xv.O.r B b B A B B B 9.9.`.`.`.`.+.).g.h.o.x l x b x x n 2 T W W ^ ^ ^ ^ W E G a x @ t K K x C C O.S | @.U jXPXGXPXGXGXGXx 3 R E D 3 G J ! Q _ _ _ ' { ' p.{ p.o.LXJXJXJXJXJXZ ^ / ( ( ( ( _ ) [ ] ] ] U U K a t 5 = l r > # l JXJXJXJXhXDX1 9 4.T.T.R.R.1XMXZXZXIXLXLXZX0X7.e.<.<.w.l.I.T.;X;X;Xj.d f d % . . o o % m 7.7.z.c.}.;X>X;X0XyXfXyX0X>X0XfX3X>X@X.XN 0 % & 7 s 4.7.x.T.;X1X;Xz.5.f m B 5.9.}.OX@X}.C |._.FXJXJXJXM c a I ] ~ _ _ Q _ Q Q Q Q Q ( _ ' ' s.s.s.{ | FXJXJXJXJXJX#XPXPXPXPXPXJXGXGXFXFXBXnXnXvXzXkXhXhXhXhXgXgXgXgXS GXoXcXzXkXX}.9.z k 0 1 : # : 1 l .*X*X&X[.[.k.h.+.+.o.=XVXSXCX0X;Xv.x.z.c.c.}.9.=X6XqXqXwX*Xg.+ > : : % , 0 9 < {.-X6X6X6X=XH.&X-X X]. XOX@X*Xk.h.t B b b m n b b N 5.j.j.'.}.].[.[.h.k.+.k l x n x x c 3 R W ^ ^ ^ ^ D 6 v v t 6 a } K x C O.O.O.v #...FXGXPXPXFXPXkX@ F Y E 2 G G J T Q _ _ ' { ' { ' { p.h.JXJXJXJXJXJXFXn./ / ^ ( ( W E Q ~ ! P K p 6 3 6 t t t 6 > + C JXJXJXS 9 b z d I.T.R.1X1XeXuXiXZXZXLXiX>X}.>.q.>.<.<.w.e.x.c.R.c.x.m u s & . . X o O B 7.7.z.c..X.X;X>XyXyXyXyXiXMXyX5X3X3X5X*X*Xk.* & 7 q f 4.e.x.R.;X;X;Xc.x.B 4.5.9.j.{..X*Xg.0 l j /.JXJXJX).a p L ! ~ ) _ Q Q Q Q Q Q Q _ _ ' { s.p.{ [ -XPXJXJXJXJXJX%XgXPXPXPXPXGXGXGXFXBXBXnXnXnXcXzXzXkXhXhXhXgXhXgX#X).#XzXkXhX#X].GXGXGXGXGXPXPXPXPXPXFXnXkXgXhXkXgXoX]..,.:.#XvXvXnXBXBXnXnXgXg B 5.7.c.e.I.I.T.hXGXPXPX].X}.j.B k 0 u 0 < % + + 1 1 c v M Z O.O.A Z O.+.wXVXKXxX>X}.x.x.}.;X.Xj.P.8XqXqXqX5X_.: < , : , , , % , r -X5X8X8X4X*X&X&X X[.{.-X*X3X*Xh.r m z u u u d n b B 5.9.z.|. X X.X{.{.h.+.r n V V z l k 4 R W W ^ 2 6 c c c 5 6 I ..| k C O.O.O.K #.o.GXGXPXGXPXPXx 3 4 D E D G F J ! Q _ _ ' ' ' ' ' p.{ [.JXJXJXJXJXJXJX#XJ / ^ ( W ( E R Y L K p 6 5 2 5 6 t a 6 > : |.JXJX].u d d f 6.x.T.1X1XeXuXuXiXiXiXyX>X}.7.g <.,.>.<.w.q.e.l.T.x.x.e.u 9 & . o $ O o X y 7.e.z.x.c.H.H.*X0X0XiXMXZXCXqX6XP.P.J.J.A.A.A.X.- q s h 4.z.T.;X;X1X;Xc.}.c.j.}.}.v..X&X{.h.0 r k k ].JXJXoXt K G ! Q Q Q Q Q Q Q Q Q Q _ ' ' ' p.[ o.9XJXJXJXJXJXJXJXJX`.PXPXPXPXPXJXGXFXBXnXnXnXnXvXcXzXkXhXhXhXhXhXhXhX%.#XkXzXhXS FXGXGXFXGXPXPXPXPXPXPXFXBXnXkXzX#XZ ].%X.1.u.u.E.E.E.u.t.,.-.e e ;.%XJXnXcXV 0 8.X Xj.9.b k u l k 0 , + + 5 k + x 6 > : @ k N .k.VXKXBX9X;Xc.c.}..X;Xg.4X8XtXqXtX8X6Xl < < , , < , d q % O.5X8X6X4X=X*X*X&X{.{.-X-X5X*X .r b u 9 0 u N 5.5.m m 5.9.}. XoXOX{.{.H.+.r M x V l k x N a J R i | c z c x 5 6 } ..} t Z O.O.O.@.#.+.PXGXGXPXGXBX> 3 D F Y T J ! T T Q _ _ ' ' ' p.{ { p.[.JXJXJXJXJXJXJXJXzXO.P ( ( W W Q ! G G 3 2 2 = 5 6 i t 5 = 1 BXJX+Xz b m h h e.x.;X>XeXeXrXuXiXiXyX>XR.z.;.e -.-.>.<.<.<.6.q.e.r.e.e.4., $ $ ; % O . % 6.7.e.z.c..X>X0X=X-X9XlXCXCXqX4XP.F.B.M.d.M.s.M.m.3 y s h 6.l.R.;X1X;X;XT.R..X@X>X-X&X&X&XH.{.z u l l k XXJXBXz p L ! ~ Q Q Q Q Q Q Q _ _ _ ' ' { v '.HXJXJXJXJXJXJXJXJXJX S %.XXXX).FXhX+XXX|.XX%X : : t C O.*XCXCXxX>X;X}.}.;X>Xj.4X8X8XqX8X8X8Xt : < 9 1 % u s q 7 < *X5X8X6X6X=X*X*X*X{.{.*X{.o.r d u 0 9 0 z B j.j.9.5.m 5.j.|.|. X X.Xk.N z V x x k k n Z o.f.K } X.t c v 6 6 a | ..| x O. .o.&X#.#.k.GXPXGXGXKX#Xa 3 D Y Q E Q Q Q Q _ _ _ ' ' ' ' p.{ p..XJXJXJXJXJXJXJXJXJXJXzX+.~ ( W E T J G 2 2 2 2 3 6 i i 5 @ A JXjXB 5.4.4.4.6.x.T.1XeXeXeXuXuXuXyX>X;Xx.6.q q e -.:.:.:.;.>.>.q.w.l.l.q.f $ $ $ o o y 6.l.e.x.;X>XlXxXwX6X*X-XxX0X1X3X!.^.G.d.s.p.s.s.s.m.5 s g m 7.l.R.;XeX;XT.x.c.}..X0X.X&X{.Z.Z.k.u b b b l x %XGX%.G G ! Y ! Q ! Q ! ~ Q Q _ _ ' ] O.vXJXJXJXJXJXJXJXJXJXJXJXJX].PXPXPXPXJXFXFXFXBXBXnXvXcXhXhXhXzXkXzXkXgXhX).PXGXJX].# FXPXPXPXPXPXPXPXPXPXPXPXPXGXFXBXnX).oX$X$X%X$X$X > + z .+.-XCXFXxX0X;X.X+X>X0.^.8XtXtX8X8X6XO.: , < : , 0 q 9 7 % O.=X8XqXqXqXwX=X-X&X+.v 6 r b b l 0 9 0 b 9.c.x.z.5.B m 7.j.}.|.}.{.k.z M n x x z x v .o.k.f.f.| r c c 6 t a ..| K v | O.o.o.&X#.h.PXPXGXGXPX|.a 4 F T E _ E E E Q _ _ _ _ ' ' { ' { ] kXJXJXJXJXJXJXJXJXJXJXGXJX X] W E R H G 2 2 4 i G G i i 2 6 gXnXg.z.7.6.4.7.z.T.R.1X1X2XeXrXuXuX1XR.T.q.s & ; e -.-.-.h g h B .k.o.l.6.6.;.f h h 6.7.e.l.T.;X>XxXFXCXwXqX6X-X0X1X;XeXyX5XL.S.p.p.p.s.p.m.9 s f ;.e.T.R.1X1X;Xx.z.x.}.;X.X-X.Xk.k.f.k.u b n n n z V hXhXa G J ! T ~ ! ! ! ! ~ Q Q _ V.gXJXJXJXJXJXJXJXJXJXJXJXJXJXJX$XkXPXPXJXFXFXFXBXBXnXnXcXzXhXX@XBXBX)./.$X%X%XXX;.-.x.1XuXuXsXuXuX3X.X.X|.s g 4.eX.XzXzXcXzXkXkXkXzXcXvX%.].%X$X%X > = X Z O.O.-XmXmXlX+X;X>X9X@Xk.7XtX8X8X8X4XH.0 : : , u u q 9 7 ; r -XwXaXVXVXaXwX=X{.< k * , r b u u 9 u m 9.}.}.x.z.5.4.B 5.j.'.'.[.+.l n b x z x x v O.f.Z.Z.f.t c c 6 t t a v K a v | +.&X#.o.#.+.GXGXGXGXGX].t 4 F T R E Q E _ W _ _ _ _ ' ' ' { { ] JXJXJXJXJXJXJXJXJXJXJXJXJXJXvXZ.W R Y F I c K D G G G D 4 Z GX).z.z.e.e.x.;XR.;XR.1X2XeXeXrXrX1X;XT.e.h $ $ ; 8 e g g g h 7.x.;XH.Z.Z.6.6.>.6.>.4.>.q.l.x.;X>XlXBXPXmXVXaXqXwX3X;XR.eXyXyX5XG.p.' i.p.p.U 8 g h >.l.T.;X1XyX;Xl.z.z.x.}..X{.[.k.k.f.} b m B B C x x C zX%.K J J T ! | [.{._.L ] [ @.vXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJX+XPXPXGXBXnXvXnXvXcXcXzXhX%X$X%X @ j O.+.+.OXFXMX0X9X0XlXxXh.7XtXtX7X8X4XK.z z k u l d u q 9 7 < -XwXVXSXSXVXaX6X{.1 GXk * 0 z r 5 9 b m z.}.;X;Xz.7.B 4.5.9.j.h.[.+.r b z k k z v Z +.k.k.f.o.z N c 5 6 v ..o.| c | +.+.o.&X#.#.h.PXGXPXPXGX#X6 4 F Y T Q E Q E ( W ( _ _ ' _ ' ' p.f.JXJXJXJXJXJXJXJXJXJXJXJXJXJXPXGXo.W Y v oXBXgXS | T H L v bX].x.c.c.c.;X0X>X>X1X1X1X1X1X1X2X2XQ.T.e.;.; o o & 7 e e e h 7.;X1X3X5X3X5Xv.;.-.-.;.:.q.q.l.c.;X>X0XmXKXKXVXVXaXqX;XR.1XeXyXyXyX4XJ.d.B.S.d.y s g ;.>.l.T.R.eXeX;Xe.7.e.e.c.}.v._.k.o.f.v m m B 5.Z C V x S %XC L ! Q v FXGXGXbX| L K kXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXX}.r.1.u.u.y.XX_.7.5.;.6.w.w.r.r.7.;XT.x.m b 4.4.4.b M j.z.;Xx.c.5.oXPXJXPXJXJXFXhX%XnXcX%.$X%.$X%X%X%XhXj.1XrXuXuXsXsXdXdXsXdXdXdXdXdXOXnXvXnXvXcXcXcXnXBXBXFXPX). x z : a 5 5 5 < + A 0.`.g.9XmXxXxXmXnXbX].=X6X7X7X7X4XP.c A x z l l d q 9 7 , XmXKXIXSXSXVXqX*Xz DXX0X0XyX1X1XR.1X1X2XQ.Q.R.I.l.>.7 . O & 7 8 h 6.c.;XyXiXpXaXwX8Xv.-.-.;.;.6.q.z.}.*X5X5XwXwXVXVXqXqXqX;XQ.1XrXrXyX;X3X6X=X=XJ.a q g ;.:.6.l.R.1X1XeXT.e.7.z.7.z.v.h.[.{.&XZ.N m 5.7.9.0.9.Z n r l K ! Q Q | JXJXJXJXGXoX$XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXkXGXPXFXBXkXgXgXgXgXgXgXoXXX].%.#X%X$XXX%XJXJXJXJXJXJXoXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXGX).x +X#X$X$X%X%X t 6 6 6 % n 9.).).g.$XmXmXFXmXmXxXv =X7X7X4X^.P.v _.S M x b u q 0 7 ; n jXVXSXSXSXVXVX*X, Z JXx , b k 9 9 d B 7.x.R.;X;XR.c.x.x.c.}.}..Xv. .k l j j z Z [.{.*XH.o.a _.k y a .@.o.Z.o.c O. .+.+.Z.Z.#.).PXGXPXJXJXGXx 2 D F Y T R R _ ( W W _ _ _ ' ' ' { OXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXGXJXJXJXJXJX| ~ K 6 5 9.}.XX.X;X>XyXyX1XyX1X>X;X;X1X1XR.R.Y.I.r.w.-.O . O 7 -.6.l.T.1XiXZXCXAXaXqX6X7.g h >.6.9.g..XH.P.L.^.8XqXqXqX6X=XR.Q.1X1XeXR.4.5.j. . .y 8 g h :.6.e.x.R.1X1XR.z.6.7.5.5.9.B j.[.&Xk.Z.7.m 5.9.9.9.0.O.N c t G L Q _ U vXJXJXJXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFX%XJXFXcXkXgX k r c c < t a t = z Z 9.0.9.).jXKXKXmXmXbXZ | ^.^.^.^.L.I [.[.O.Z n b b q 9 , : OXxXSXIXSXSXVXqX% < S S , l B N d d m 7.z.;X;X3X1X;X}.}.;X;X.X.X.Xk.c l k j x A [.&X*XH.+.| l c a } f.@.Z.#.o.a .+.o.o.Z.Z.A.%.JXGXPXJXJXGXO.2 D F ! Y T Q E W _ _ _ ' _ ' ' ' p. XHXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXnX..@.o.v C .X>X*X3X0XMXMXyXeX1X;X;X;X1X1X;XR.l.l.w.6.:.h 7 o & s 6.6.q.T.R.1XMXZXIXIXSXqX7X*X4.g 4.4.9.'.H.P.P.G.G.L.L.J.=X7XR.T.T.R.R.l.9 O ; 8 s g -.s g -.:.q.e.x.R.1X1Xc.l.6.4.5.4.N @ 5 g.{.H.f.5.B 4.7.9.9.9.g.N a K G J Q _ { |.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX%.FXBXcXhX t a 5 k B B Z M B g.jXKXCXmXmXxXO. .L.~.~.J.I {..X{.j.9.B b d q 7 , 1 -XmXSXSXVXaXqXr % , : , 9 b B b d h 4.z.c.;X1X3X;X;X;X1X1X>X9X9X5X*Xt k j l Z _..X*XH.k.| c 6 | ..o.o.o.Z.#.t | +.+.k.k.o.&X+.JXGXGXJXGXPXoX> 4 G F Y Y Q E _ W W E ( ' ` ' ' p.].JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXjX..V.o.N }.0X=X5XqXVXJXMXeX>X>X>XyXyXyX3XR.T.l.r.l.l.l.l.T.x.x.z.z.l.l.T.R.1XZXIXIXUXSXaXtX7XH.B B 9.S H.P.~.L.G.G.S.S.S.J.Z.e.x.R.R.1Xd $ 7 s s g ;.>.;.g ;.6.q.l.T.;X3X;Xx.4.4.6.5.B y @ @ l [..Xk.B m m 5.9.9.0.j. . .I K L Q { +.BXJXJXJXJXJXJXJXJXJXJXJXHXJXJXJXJXJXJXJXJXJXJXJXJXJX|.XX].XX+XkXzXkXgXgXgXhXhX.0.%.#X+XoX].JXcXw.r.I.w.m 5.7.5.7.x.nXcXkXnXPXPXJXJXPXPXPXPXPXPX#XkXkXhXgXgXzXvXBXGXPXPXPXPXGXPXPXPXPXPXPXPXFX].gXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXg.4X^.^.^.L.L.L.~.G.J.F.A.A.Z.k.f.k.k.k.h.N z z `.JXJXJX].#X%.O.M v v c 6 OXVXIXUXIXSXaXdXaXqXwX-X-XoXoXOXOXOX{.[.O.).0X|.1 z v M 6 a > k Z Z B n b b S mXKXmXmXwX-X3XO.A.F.F.} .X*X.X'.j.B m b u y 9 o S 0XmXVXaX8X8XN % : * * , u m m d f 5.z.x.;X;XeXyX1X1XyXyXyX0X0X0X5Xo.r r l M g.{..X{.Z.o. . .} .f.o.Z.@.o.K k +.o.k.k.Z.Z.k.HXHXHXPXGXGXGXx 4 G F J T T Q Q E E _ ( ( ' ' ' ' '.HXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX Xb.k.g.;X0X=X6XwXKXKXNX0X>XMXZXLXZXyXeX1XR.I.T.T.R.R.R.R.;X>XyX>Xc.T.T.1XiXLXSXPXIXSXaXtX7X5X&X&X{.[.*X^.^.~.~.G.G.F.G.Z.g q.c.;X;XeXc.s h h >.>.6.q.q.f ;.4.q.l.R.;X>X;Xl.4.5.5.7.7.b @ @ c v.{.{.j.m m B 5.5.9.9. . .+...@.$.k.nXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFX].zXzXzXkXhXhXgXX5.6.6.6.6.f V hXgXgXB 5.4.5.5.5.|.'.z.5.B m 7.5.`.C JXPXPXGXBX.X;XR.}.R.c.c.;Xc.x.$XPXPXHXC d 7.Z +X#X$X/._.%X7.y.I.U.>.B 7.7.j.c.gXkXBXPXPXPXPXPXPXPXPXPXnX].%XhXkXhXX9.5 v N 6 c > l C Z C B k : < _.mXmXxX-X-X0X5Xh.X.C.U k.-X*Xv.j.A B B m u 0 + + g.OXqXqX7X^.f.; , * + 7 u d h h d 4.z.x.c.;X;XyX>XyXrXiXMXMXmXxXwX*X6 r l M 0.].{.{.k.k.o.} } } } o.o.X...} 5 | +.k.+.Z.Z._.PXPXHXHXGXPXGXO.3 G D J T Q Q _ Q _ Q _ _ _ _ ' ' {.HXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].Z.[.;XpX6X6XwXVXKXMX0XZXLXIXIXZXiXrX1X1XW.Q.R.Q.1X2X1XeXyXiXCXCX0X;XyXZXZXLXIXIXSXaXtX7X4X6X=X*X=X=X7X^.^.^.~.G.G.G.y f 6.x. X>X0X3X6.>.>.7.l.l.x.l.f g 4.7.z.}.;X>X}.z.5.7.l.e.7.7.2 @ 9.}.}.v.v.m f m B B 5.A j.j.k.o.n.H.#XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXvX).nXcXzXkXgX r C A B C 0 * < : mXmXxX-X-X-XwX5X[...] k.-X*X{.h.j.5.m b f d , < % Z *X7X7X^.f.7 ; ; $ < q u d f d m 7.z.x.}.1XeXyXyXuXyXiXMXmXNXbXwXk.< l M 0.'. X.Xk.f.h. . .} } ..o...} } t a o.+.&XZ.&X+.PXHXHXHXPXGXGXoX2 D G J ! ! [ Q Q Q Q _ _ _ _ _ [ .XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX0.}.;XiX5X=X5XmXCXbXCXIXIXIXSXZXuXuX2X2XQ.2XQ.Q.Q.1XrXuXZXIXVXqXqXiXiXZXZXIXIXSXAXaXtX7X7X^.4X7X7X7X7X7X^.^.^.L.G.I e g 4.j.}.OX-X0XR.l.z.z.x.c.R.R.f h 4.7.T.}.;X.Xx.z.z.z.7.z.z.7.y - j.x.c.}.`.B d f m B B A g.h.k.Z.*X{.HXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXBX%.BXnXcXkXgX$X).#XGXPXPXGXPXGXJXXX.6.6.6.4.].|.7.B f x.uXsXuXuXuXeX1X1X;Xc.d oXPXPXPXhX@X>X.X3X3XyX3X3X0XuXeXnXPXPXkX/.C 6.9.).oXgXhXhX#X$XhXr..XFX0.m 5.j.kXJXPXPXPXnXXX#Xx S ].%X%X%XgXgXhX > > ].mX-X-X-X-X-X5X*Xk.K +.wX-X-XoX[.9.5.B h f 0 : , @ O.H.4X~.f.& & * % ; 9 q q y d f 7.j.x.}.;X;XyXyXuXyXyXyXMXMXmXxX5Xa l M 9.`.]. Xk.h.o.f. .} ...o...o.} } c 6 c o.Z.H.+.GXGXPXHXGXPXPXFXx 3 D D J J ! ] ! Q Q Q ) _ _ [ +.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXBX).;XyXMX=X*X-X-XxXHXIXLXIXLXZXsXiXrX2X2XQ.2XQ.1X1XeXrXsXIXIXVX8X7XpXZXLXSXLXSXSXAXtX8X7X^.P.P.^.^.^.^.7X^.^.^.~.f.8 e s m 9.'.-X0XmX3Xl.x.R.R.R.;X;X7.m 4.7.}.>X>Xj.z.l.7.7.z.7.z.z.a 3 2 v 7.j.x.j.b q b b b B 5.h.h.{.&X-XXdXdXdXdXdXdXdXdXdXsX3XFXPXPXJX: 5.4.4.7.9.OXkXzXcXcXnXe.r.BX+Xb x..XJXPXPXPXPX%.GX`.+X+X#X%X j C M M > 6 6 5 x jX-XOXOX{.*X-X*X*Xh.+.wXwX-X-X#X}.j.5.B m b + , , * 0 .D.b.; % & & % 9 7 9 9 s d 9.z.c..X;X>XyXeXyXeXyXyXyXyX0XbXwX=X5 x A g.`.].[.k.o.k.o.| ..} .} f.o.f...o.o.| +.&X .bXGXHXGXPXGXGXGX|.3 4 G G J ! ! ~ Q Q Q ~ Q ] _.PXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX`.0XyXMXyX5X0X{.9.9XIXIXSXIXAXsXuXuXrXQ.eXrXQ.rXeXeXeXsXSXIXSXVXqX7XqXZXZXLXSXSXVXqX8X4X^.^.L.L.~.~.~.~.^.^.^.^.K.- 7 8 s B j.{.-XwXaXaXR.R.;X1X;X1XyXe.m 5.9.}.>X9.m 4.m m 9.z.z.9.7.a G i i p a t A j.u 0 u l b M A g.[.*X-X'.nXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFX%.FXBXcXzXS ].vXGX$XoX].].X0X0XxXxX5Xo.k B 9.g.`.'.h.o. .o.f.} } } } ..f.f.f.f.f.@.o. .O.oXHXHXPXGXGXPXPXGXM 3 4 D L L ! ~ Q ! ~ ~ U _.GXGXHXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX+X3XMXCXiXyX3X.Xg.5 VXSXSXSXZXsXuXuXrXrXQ.eXQ.Q.uXrXuXsXAXIXIXSXAXqX7XqXmXLXIXLXKXdXqX7XL.L.G.G.G.G.G.G.~.^.7X4XqXy O ; 8 f ;.j..X5XaXaXaXyX;X1XeXeXyXyXc.h 5.z.;X|.9 u q u 4.9.j.z.7.5.I J L I I a v N M 0 9 0 k b n B g.[.*X5X5X_.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFXoXFXBXzXXGXPXPXPXPX%.$Xk #X%X%XgXgXhXgXkXkXhXzXcXnXGXPXPXPXPXPXPXPXPXPXcXkXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXg.K.~.L.G.S.S.G.S.G.L.J.L.P.=X=X=X*X5X*X=X=X6X6X5X*X[.M 6 . .a t t l a 6 j @XwXaXqX7X8X8X8X8XqXaXaXVXKXVXVXVXKXCXVXmX-X{.+.6 @ 6 a a t 5 a p t 6 5 > # # > Z _.{.{.{.{. XOX-X*X-X-XOX Xx.5.4.m b d b B M M l $ , ; , ; % $ , 7 ; , 9 9.}.}..X}.;X;X>X1X3XeX3X3X0X0X0XmXwX=Xa n A 0.).`.h.h.+.| } | I } } o.o.f.b.Z.Z.b.X. .v O.cXHXPXGXGXPXGXJXFXz 3 4 G G J J L F L K #XGXHXGXHXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXBX_.MXZXyX0X;X.X0.N 3XtXdXAXZXZXiXuXrXeXQ.eXeXrXuXuXiXZXSXUXIXSXAXaXtX8X8XCXLXIXPXKXaXqX^.G.S.F.S.S.F.G.G.L.~.^.pXiXo . ; q d 5.v.*XwXqXqXaXAXuXuXiXiXiXyXR.m 4.9.}.0 O % , d 5.j.x.j.9.m I P ] U o.f.k.{.&X'.x 1 5 u b n 9._.*X0XwX*X$XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].FXcXkXhXzXnXnXnXnXBXnXnXvXcXcXzXvXBXFXGXGXGXGXGXGXPXPXPXJXHXGXvX = K p a K a a a 6 > : : + r O._.]. X X X{. X{.=X=X*X*X}.z.j.5.4.b m B 5.9.j.0., 7 ; ; ; % % ; ; * 9 9..X@X>X>X>X>X>X3X>X3X3X3X-X0X-XjXxX5XH.u Z 9.0.O.+.O. .} } } } .o.| f.f.k.Z.b.b.@.o. .+.O.oXGXGXPXGXJXJXJXJX].C c c v p D a v BXPXGXPXPXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].mXCXMX>X;X}.}.9.N tXpXAXAXIXZXiXiXuXrXuXuXuXuXpXpXAXSXIXUXUXIXSXSXaXtXVXMXZXZXsXpX8X7X^.L.L.G.G.G.G.G.L.L.^.7XAXVX, O ; 8 f j.{.wXaXaXaXAXsXiXiXuXiXiXiX;X4.4.9.`.X + + ; 0 B 9.`.h.5.m f ] f.f.f.k..X-XxX0X9X-X+.r b b A _.OX-XqXqX'.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].FXcXvXFXFXFXBXBXBXBXBXnXvXvXvXnXnXBXFXGXGXPXGXGXPXPXPXPXPXPXHXGXgX#X%X%XhXcXnXFXPXPXGXQ &XnXkXgXx V +X#X#X#X#XoXK L L J J +.#XgXS S #X#X+X#X+X,.,.-.e -.kXBXFXFXFXfX}.e.u.E.t.-.5.5.7.9.%XZ 7.W.W.e.1Xx.e.}.zXkXkXhXgXgXgXhX|..XrXg.vX.XyX+XFX0XyX3X3X3X3X;X;Xv.$XPXPXgXk #X].M c.1XeXrXuXuXsXsXsXdXdXZXdXdX#XGXPXPXPXGXS +X$XkXBXFXGXFXGXPXFXnXFXFXBXFXGXPXPXPXPXPXPXPXPXPXBXcXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXoXa L.G.G.S.G.S.G.L.L.G.L.P.P.=X=X5X5X5X6XqXqXaXqX6X.XN < = a t t t t a a 6 N =X=XP.4X^.7X7X7X7X8XqXqXaXVXwXVXwXaXqX6X=X*Xk.o.v k > p K p a a t 6 5 > : # r B 9._.].|.|.}.'.[.*X4X6X*XOX}.x.z.9.4.m 5.9.9.}.+X9.7 7 ; ; & % * ; ; < 9.+X>X>X9X>X0X3X3X>X3X*X=X-X-X-X-XxX-X*X .n B A A O. .| N I } f.f.f.f. .f.f.f.b.b.@.@.o.O.O.+._.].oXcXGXFXGXFXPXGXPXGXGX+X).kXJXJXJXJXHXGXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX'.CXMXyX>X;X;X`.0.t tXdXdXSXIXUXSXSXZXsXsXZXdXZXAXAXIXUXUXUXUXUXUXIXSXVXCXrXeXeXyXpX3XH.k.o.f.A.J.J.P.P.=X7X7XdXaXdXN & 7 d m z.@X0XVXSXSXAXiXuXiXsXiXiXiX1X7.4.7.B : + + ; q B 9.x.`.5.m d } f.f.k.k.OX9XmXmXxX-X-Xh.r b Z g.{.-X5XqX*XhXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXGXPXJXGXGXPX`.BXnXFXPXGXGXFXFXFXFXFXFXFXFXFXBXBXGXGXGXPXPXPXPXPXPXPXPXPXPXJXJXkX#X#XXBXBXPXPXPXoX).#X%XcXGXPXPXPXPXPXPXPXPXGXGXPXPXPXPXPXPXPXPXPXPXPXhXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXHXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXlXO.D.G.G.G.G.G.L.G.G.L.P.=X6X=X5X5XwX6XqXqXwXVXwX5Xv.l < : t t k 6 6 z l t N H.K.P.P.^.^.4X7X7X8X6X6XqXqXqXqX6X6X6X=X*XH.k. .v l 5 K p p a t 6 5 5 > * 0 z m A ).}.}.'.}.h.h.=X7X7X-X-X.Xc.z.9.7.7.j.c.;X>X>X0 9 7 * % % % % * 9 g.+X,X9X9X0X0X>X.X3X*X*X*X*X*X-X*X-X-X-XH.c B B C N c a a a I .} j.f.f.f.f.f.b.b.n.@.@. .| v v c c c c O.h.oXFXPXPXGXJXJXHXPXJXJXJXJXHXPXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXoX-XVXMX0X;X>X|.g.M < 8XdXAXIXUXUXUXIXIXIXSXIXSXSXSXIXUXUXUXUXUXUXUXUXUXSX1XT.4.q * X X o + ; y O..X5X=X6XqXtXaXaXpX4X, q d 5.c.>XbXIXIXSXZXuXiXiXsXZXsXiXR.l.5.5.B : O + % 0 m 9.x.j.5.f u a f.k.h.{.-XmXmXbXmXmXjX-X[.l B O.'.*X=X8XqX].JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXGXJXJXPX K K p p t 6 6 5 # 1 u b m B 0.j.z.x.g.g.k.K.P.4X*X-X}.x.x.x.x.c.R.1X0X>X0 9 7 * & % * + % 1 ).+X$X9X9X0X-X-X*X*X*X*X=XK.*X=X*X*X-X-X*Xk.k x x z l r y t v v } I .o.f.f.f.f.@.b.#.#.o.| v v v | v v a a } | -XGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXA 6XwX3X;X;X+X'.g.b 1 h.AXSXIXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXUXPXR.w.7 o X o o X * 9 9 m v.0XmXaXpXqXpXpXtXP.t s h 6.c.>XyXCXCXiX3XuXiXZXsXsXiXiX;XT.e.e.9.+ + O % 9 m 9.9.9.4.b q q .k.h.{.9XmXmXmXmXxXwX9X-Xh.t A h.{.=X6X8X{.BXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXGXFXoX].gXGXGXGXGXPXPXPXPXPXPXPXPXPXGXPXPXGXPXPXPXPXPXPXPXPXPXPXPXcXZ.@.! Q J ].#X$XgXcXcXnXFXGXFXBXL D Q _ _ _ _ ( E Q Q E Q Q Q Q T x gXkXcXzXzXkXhXkXkXkX}.,.:.e -.:.e 6.q.e.w.6.0.XXkXoXe.e.7.6.7.7.hXhXk gXcXhX;X}.cXcXzXhXgX 1 1 u b B 5.9.j.z.`.j.O.h.Z.K.-X0X.X}.x.c.R.R.;X1X>X,Xj 7 , ; % & % ; < l ].OXOX-X0X9X5X*X-X-X=XK.=X=X=XP.=X=X*X3X-X&Xv l k k 6 6 6 a N o.f.j.f.h.o. .o.o.X.@.b.] X.o.o.| v K | K } | K I ..].PXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXO.4X3X3X>X@X*Xk.f.v 5 5 pXSXIXUXUXUXUXUXUXUXUXUXIXIXUXUXIXUXUXUXUXUXLX1XT.T.< o . . o o o o < 0 0 Z }.jXVXaXaXaXaXtX7XZ.d 7.l.e.6.x.}.;X;Xx.R.yXpXdXdXsXpXsX2X;XR.e.x.0 + % * 9 B 7.9.7.m g q q 7 z j.}.-XxXmXwXwXwX-X-X*X&X+.5 j..X-XwXqX8X].JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXGX#X].FXPXPXPXPXPXPXPXGXGXPXPXPXPXGXGXPXPXGXPXGXPXPXPXPXPXPXPXPXPXPX{.W W W ^ H ..gXzXcXcXnXnXFXFXnXcXK Y { ' _ _ W ( _ _ E _ E Q Q Q L %XkXcXcXcXcXzX#X}.9.7.8.-.-.-.-.:.:.e q.e.r.y.y.w.7.).7.e.e.8.5.5.#XhX%.S zXcX.X;X#XkXzXzXgX%X#XC S %XBXBXDX+XgXnXnXnXBXGXJXkX8.I.I.Y.I.u.u.I.u.E.Y.E.W.e.cXvX 6 t 6 6 6 6 6 > 5 I C.J.L.L.~.^.^.^.^.4X4X7X4X4X4XP.K.H.k.f. . .a k n ...K p a 6 6 : j 5 b m B B 5.9.j.`.'._.+.&XjXwX-X;X.X;X;X;X1XeX>XA 1 7 , ; & % * & : x ].OX-X-XwX-X-X-X=X*X=X=XP.=X=X=X6X6X=X5X-X*X&Xx k 6 1 1 l N O.h.k.&X&X.XZ.+.o.o...U b.] @...o.o.} | I | I } I U ....{.PXGXPXGXPXPXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX XK.H.*X3X0X0X=XZ.k. .l > N SXSXIXUXUXUXUXUXUXUXUXIXSXSXSXAXAXAXSXUXNX1X1X1XR.B . . . o o o . < y z j..XxXCXVXAXVXaXaX5XB h e.R.I.q & $ O * s x.3XtXtXtXpXpXtXyX1X;XT.x.z.* % : u m 5.7.7.4.d q q 9 7 9.c..X0XwXwXqX5X=X*XH.Z.Z...1 A 3XwXqX6Xk.BXJXJXJXJXJXJXJXJXJXJXJXGXPXGXPXGXGXPXnX%.kXPXPXPXPXPXPXPXPXGXFXFXPXPXPXPXPXPXFXGXGXFXPXPXPXPXPXPXPXPXPXPXJX*X/ / ^ ^ P cXnXBXnXnXnXBXFXFXvX|.U Y ' { _ _ E E Q _ E E Q Q E ! `.zXcXvXnXBXnXoX6.u.u.E.u.E.t.,.-.g -.-.-.q.e.y.e.y.y.y.8.m 8.5.4.4.0.1 |.].|.cXgX>X}.hXkXzXzXgX).x _.%XBXnX|.z.|.nXBXnXnXBXGXPX$X4.w.u.Y.U.Y.Y.Y.E.W.W.y.hXcXcXvX 1 k k j 6 5 > > # t C.G.L.L.~.P.^.^.^.^.4X7X4X4XP.P.K.Z.b.f.} a y j nX+.} K p p a = z k M m m B 5.9.g.`.|.].{.-XwXmX0X0X3X;X;X>X1XyXyXN : 7 , ; * * & % # x [.*X*X5X-X5X5X*X*X&XH.K.=X=X6X6X6X6XwX5X5X-X*X+.k j 1 r x A h.k.{.-X-X-X*Xk.o. ...X.U U U U ......} } } } ..X.X.U ] ..OXGXGXPXGXGXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXh.K.5XwXwXqX=XP.A.Z.k.v r : -XSXSXUXUXUXUXUXUXUXUXIXSXAXAXdXdXpXaX;X;XyX>X1X;X`.+ O + % O . . y c A '.,XBXKXKXIXSXAXSXlXz.7.z.R.e.; $ . % h T.!.5X!.4X8X8XyXeX;XR.c.z.n ; ; u m 4.7.6.;.f q q q 0 4.x.@XjXwX=X=X=X&Xn.m.[ [ m.f.A g.-X5X6X=X XHXJXJXJXJXJXJXJXJXJXJXPXGXGXHXGXPXzXC GXPXPXPXGXPXFXFXGXGXFXFXFXPXPXPXFXFXFXFXFXFXFXGXGXPXPXPXPXPXPXPXGXBX9X^ / / / / k.BXFXBXBXBXFXGXFXBX%.L H _ ' _ _ _ _ _ E _ Q Q Q Q +.zXcXnXBXBXFXgX:.U.E.E.E.E.E.E.E.E.1.-.e g ;.w.w.r.y.T.u.W.T.r.6.5.4.%XGX|.C 1 kXcX.XyX XhXkXzXC nX+X).zXhXz.T.T.I.}.DXDXBXBXFXJXJX7.4.6.r.I.Y.E.W.W.Y.x.hXcXcXcXvXnX,Xj.z.7.9.x.vXcXkXgXgXhXkXkXzXzXzXcXFXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXHXoXC GXGXPXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX).4X~.L.~.~.~.~.^.^.4X8XqXqXqX6X4XP.K.Z.b.| t 6 < 5 > : k k 5 > > : = = a V.J.G.L.L.L.^.^.^.4X4X^.4X=XP.K.K.Z.f.f.I t l ].JX+Xa c p a > j C V b B m B 5.0.`.}.{.{.OXwXwXwXmXyXyXyXyXyXyXyX0Xx 7 ; ; * ; & % # c [.*X*X-X=X5X0X5X*X&XH.=X=X6XwXmXwXwX6X6X5X5X=X*XN k 6 0 V 0.`.v..X,X9XwX-X*XZ.o.o.X.U U U U X.............X.@.X.U ] ] o.X{.> * , ; @ o . t ._. XjXFXPXUXIXIXIXPXCX;X;X;X1X6.; & $ . y 5.c.!.K.P.4X4X8XyX1X3X;Xz.5.u 7 q h 4.7.4.;.g q q q d 4.z..X0XwX6X=XK.m.[ Q ) [ s.M.b.O.+.=X=XP.+.HXJXJXJXJXJXJXJXJXJXJXGXPXPXPXFX].oXPXPXGXGXGXGXFXFXBXnXnXcXzXzXPXPXPXPXPXPXPXPXPXFXGXPXPXPXPXPXPXPXFXGXBXzX) / / / / Q OXFXFXFXFXFXGXnXnX%.F K G G J ! T Q Q _ _ Q Q ! k.nXvXnXnXFXFXFXe.y.U.E.E.E.E.E.E.E.E.E.E.u.-.e q.e.y.u.u.W.u.W.W.Y.Y.6.vXPXHXFX%.V cXgX;X}.zXcX%XoXPXPXPXBX9.y.T.y.T.e.XhXvXcXzXzXcXnXBXFX+Xz.9.7.c.vXnXcXhXhXkXkXzXcXcXcXnXnXFXGXPXPXPXPXPXPXPXPXPXPXPXPXPXnXx /.GXJXGXGXHXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXj.7X^.L.~.~.~.P.^.4X8X8X8X6X4XP.P.K.A.b.f.I t 5 5 < > # 1 6 5 > : : > = p C.F.G.L.L.L.L.^.^.^.4X^.^.^.P.K.A.Z.b.o.} a l DXJX].t 6 6 a p k Z b m N B A 0.g._._.[.&X-XwXmXVXZXyXyX0XyXMXiX0Xx ; ; , ; ; : ; % c k.&X*X5X5X*X5X*X*X=XA.=X5XwXVXmXKXmXwXwX=X=X-X=Xh.k 0 0 z 9.`..X;X>X0XjX0X=X*Xf.o.o...U U U U X.X.X.o...X.X.@.@.#.] ] [ | hXGXGXGXPXGXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXo.C.J.4X8XqX6XP.P.P.H.H.o.c 6 N VXAXSXIXIXUXUXUXUXIXSXAXaXtX6Xj.c .v.v.3X3XwX0XN * 7 9 9 ; O o O t h.&X0XaXVXKXIXIXUXIXCXyX;X1XyX4.7 ; $ o . . $ m x.D.F.P.J.L.qXuXyXyX1XT.7.B 9 q f ;.4.4.h s s u s f 4.z..X;X0XwX5XZ.$.] Q Q _ { s.M.@.v k.H.P.K. XJXJXJXJXJXJXJXJXJXJXGXGXGXoXoXGXPXGXGXGXGXGXGXFXBXnXvXkXoX_.kXPXPXPXPXPXPXPXPXPXPXFXGXGXGXPXPXFXGXFXBXnXvXX./ / / / W T #XFXFXGXFX#XD +.I D +X+Xo.! L L G K G G | kXBXFXBXnXnXBXFXDX}.u.u.t.U.E.E.E.E.E.E.E.E.E.E.E.y.5.y.y.T.W.W.W.Y.W.Y.e.gXPXPXHXFXBX+X#XgX.XyX+XvX%.FXPXPXPXoXT.I.8.e.T.I.`.FXPXJXJXJXPXvX6.7.e.q.`.zX`.9.XXkXzXkXzXcXnXBXFXJX.X5.5.v.JXFXnXcXhXkXzXcXvXvXvXnXBXFXFXGXGXPXPXPXPXPXPXPXPXPX%XC V hXJXJXJXHXPXPXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX`.5X7XP.~.^.^.^.7X7X7X7X7X^.P.L.J.D.n.b...K t 5 2 5 = + : 5 > > = = > @ p N.S.F.F.J.L.L.^.^.7X^.4XP.P.P.K.K.A.Z.f.} | h.oX%.K a 6 6 K _.C z b b N B A S +.+.+.{.-XwXVXKXmXdXMXxXyXmXiX0Xz * ; * * ; & * O c k.&X*X5X*X*X=X=X*X*X*X*X5XwXmXBXKXmXwX5X6X=X*X=Xk.0 0 9 l B z.}.;X>X0X0X0X0X5XZ.o.o.....U I U L U X.X.X.X.b.@.#.] #.$.[ [ +.nXGXPXGXPXGXPXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX#Xn.B.L.7X8X8X8X^.P.J.J.K.k. .v k.aXaXVXSXUXUXUXLXCXZXIX9Xx * * f N j.v.H.!.6X5X5X< 9 y u u y ; O o O 6 k.*XwXVXKXIXIXIXSXVXaX0XyXMX6.7 7 & $ o o o d j.D.d.S.S.S.qXZXiXiXyX;Xl.5.u q s h ;.;.g s s s d 4.6.l.}.;X9X0X3Xn.] ! R Q ) { { s.M.@.> o.Z.J.+.GXJXJXJXJXJXJXJXJXJXJXcX/.nXPXPXPXJXGXGXFXFXBXBXvXcXzX].PXPXPXPXPXPXPXPXPXPXPXPXPXPXFXFXGXPXGXFXBXvXzXhX > = @ > > > > = > = t N.C.C.C.F.L.P.^.^.4X^.^.^.=XP.P.K.A.A.V.Z.b.f.o.a 6 p t p %.V u z b b M M Z N Z O.+.*X-XmXVXVXVXCXCXMXmX0X-Xc * ; ; & * * ; % a +.*X*X5X=X=X*X-X*X*X*X-XwXwXmXmXnXmXmX5X6X=X=X-X0X, 0 9 0 B j.}.;X>XyXMXMX0X3X=XZ.o...U U U P ! ! ! X.X.@.@.#.@.] ] [ [ Q [ | cXGXPXGXGXGXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXj.d.S.L.^.7X7X7X^.^.L.J.J.Z.A.Z.K.6X8XaXVXVXAXVXmX*X[., , , < u v O.f.Z.H.G.L.=Xv.9 u u b f d 9 & O O O X > ].-XmXKXIXSXAXaXqX6XCXCX4.7 7 ; & O o o 9 } m.i.i.p.p.4XSXZXZXZX1XT.z.b q d h h h f g f g g ;.q.l.T..X;X>X{.X.] T R R _ _ { p.s.M.I 5 ..N.N. XJXJXJXJXJXJXJXJXJXhX].PXPXPXPXPXUXPXPXGXGXBXnXzXkX].%XPXPXPXPXPXPXPXPXPXPXPXPXPXPXFXFXBXBXFXFXnXOXoX$X%X%XK ( ` / ( / / R o.#XX.R R Y W F X > = > = > = v n.m.m.n.J.L.P.^.4X^.4X4X^.^.P.J.K.D.D.A.A.A.A.A.b.a 3 1 k 1 k u z n x v v c v .+.[.-XmXVXKXKXIXKXCXBXxXxXc * ; ; ; ; & ; * c .&X5X-X*X-X-X-X-X-X-X-XwXwXmXmXmXmXmXwX5XK.=X-X*Xr , , u B 9.c.;X>XyXyXmXnX0X-X*Xf...X.] ] ! ~ ~ T ! X.@.b.#.#.#.$.$.[ ] ] ! +.%..6.l.x.c.}.}.v.o.U T R Q W _ _ ' s.{ M.4 } m.M.[.JXJXJXJXJXJXJXJXvX].PXPXPXPXPXPXPXPXPXHXGXFXnXzXgX%.PXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXGXFXnXbXnXcX_.).#X%XgXY F ( W / / ^ ^ W R R R R Q R Y +.#X+XS %X).K G K G L [.GXFXFXBXnXvXcX<.,.:.:.-.hXcXcXvXmXlXc.r.E.E.t.,.BXJXFXcXS gX%XoX#X%X`.FXJXPXJXJXGXFXvXcX}.}.gXyX X`.JXPXPXPXPXXX7.8.4.W.6.4.PXPX = > = = = z N X.X.] n.F.P.^.4X4X4X4X^.4XP.L.K.K.K.K.J.J.J.J.K.A.} = K 5 k l z x M v c c c v O._.*XwXmXKXIXIXIXKXFXmX-Xl * ; * * * ; ; * v k.*X*X*X-X-X-X-XOXOX-X-X-X5XwXwXwXwXxX5X*XK.H.{.O.< 7 ; 0 m 9.x.;XyXyXyXMXBXHXwX-XH.f.b.@.#.] ] Q ~ ! ] X.@.@.#.$.$.[ $.] ] ! ! [ L v #XGXPXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXf.p.S.G.~.7X7X^.7X7X^.P.P.L.P.P.L.~.4X7XtXtXaXaXVXwXwXh.l , * M h.{.=XP.^.L.K.a u B N B Z 5.5.d 9 * ; $ O % 9.'.+XxXVXaXaXaXaXaXSX.X8 e q 8 7 7 & $ $ a C.d.S.S.4XdXZXIXIXLXyX;Xx.m q s g g g g h h h ;.6.e.e.l.z.x.x.j.j.U P R E E W _ ' { { p.[ K B.M.oXJXJXJXJXJXJXJXHX].PXPXPXPXPXPXPXPXPXPXPXGXFXnXkX 5 2 > = c #XZ o.X.U N.J.^.4X7X6X7X4X4XP.P.K.K.P.K.P.L.P.J.L.A.V...2 5 r l x v C N c a t c Z +.&X-XmXKXIXUXUXKXmXmX-Xl : * * * * ; ; * o.k.&X-X-X-X-X$X#X#X-X*X*X=X=X6X6X5X=X=X=XH.Z.V.O.9 9 9 ; y m 9.j.;X;XyXiXMXCXHXmXxX*X*XZ.A.n.#.[ [ ] ] ! U X.@.@.#.#.[ [ ] ] ] ] Q [ _ U O. = = = = 2 t gX9XA o.f.@.A.P.6X8X8X8X7X^.P.P.K.P.P.P.=XP.P.P.P.J.A.n.} * r z x x v N c t 6 6 v +.[.OXwXmXKXUXUXKXmXmX-Xt : # * % % * % < k.v.*X*X-X-X#X@XOXOX&X&X&X&X=X=X=X=X=XJ.A.N.m.m.] < 9 7 ; r b B 9.}.;XyXuXMXZXFXKXmX0X=X=XK.A.A.n.$.#.[ ] ] ] U @.b.#.#.#.] ] ] ] ] ] [ { { X.{.FXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJX'.' p.S.G.~.7X7X^.tX7XtX8X7X7X^.^.~.^.^.^.7X7X8X7X4XP.H.h.; 9 9 > a I a y < 0 u M j.k.f.h.v.9.b u 0 q , % X N X9XxXxXbXxXjXXMXSXIXZXyXR.m s g h g f s f f m 4.9.j.z.4.9 ; 0 q d q K T R E W / ( / / / ` ` ! o.JXJXJXJXJXJXJXJX$XvXPXPXPXPXPXPXPXPXPXPXPXGXBXvXhX c c c a a a t 6 5 c S _.{.-XmXKXIXUXUXmXmX-X1 * + + + % % X t h.k.{.*X@X>X@XOXoXOX&X&XH.A.N.A.A.F.C.V.M.C.M.[ [ ! 2 7 ; 0 d B 9.x.;X1XyXiXiXCXKXmXmX-X5X*XH.Z.V.n.#.#.] ] P P U #.@.@.U @.U X.] ] ] [ { { { { #.-XKXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXMXU p.d.S.~.^.7XtXtXtXpXqX8X7X4X^.^.^.^.^.7X7X4X^.~.L.A.h.; , 9 , 7 , , ; 9 q u M h.v.Z.k.v.g.b u b d u * $ c h.-XwX0XjX$X`.5.0. XMXCX9Xg.C z 0 q 7 u l q % ; f 5.c.!.3XwXVXVXyX;X5.s f ;.h f f f m B Z j.h.j.5.* 0 u d f b d L R R W ^ / / / / ` ` K OXJXJXJXJXJXJXJXJX`.FXPXPXPXPXPXPXPXPXPXPXPXGXBXcXhX%XgXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXGXnXvXnXo.Y vXnXnXBXnXnXvXnXBXBXcXk.{ { ~ ! ! U L L L ! ! Q _ Q OXNXx.t.u.E.E.E.E.E.u.,.e g -.XXNXcXcXvXBXJXDX5.5.`.gX N h.k..X.X@X+X@X X{.{.{.&XZ.A.A.C.V.C.N.C.C.C.N.s._ R H * * , u B 7.z.;X;XyXyXiXMXCXKXmXxX-X*XH.Z.Z.b.#.@.@.] U P P P ] I K U U U U U L L L ! { { { [ *XHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLX5.a.S.G.G.^.^.^.tXpXaXaXqX8X7X7X^.^.^.^.^.7X4X^.L.L.H. .I * * 9 9 9 7 9 q 0 u v +.&X*Xk.k.j.M x n u 0 , : # > M '.OX}.0.z.c.}.>X0XBXzX Xg.0.g.N z 0 C d , 7 B x.;X3X!.P.4XqXtX3Xc.f h ;.;.m f f b N ..b.o.9.B ; 0 u b b m d v T R W / / / / / ` ' r LXJXJXJXJXJXJXJXJXx GXPXPXPXPXPXPXPXPXPXPXPXJXBXzXgX%XnXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXBXnX! ! FXFXFXGXGXGXBXBXnXBXcXX.{ { _ ' ' _ _ Q Q _ _ [ Q ! t i y 5 2 > 5 5 t V S _.{.-XmXKXIXUXKXmX-X1 < * % % + + 6 O.h.[..X.XOXOX X X].[.k.f.#.A.C.C.C.B.C.C.C.F.B.s.' ^ E 3 $ * y m 7.z.T.;X3XyXyXiXmXFXmXjX-X-X&XZ.b.b.] b.U ] P L L J L J D G D 4 D D D T R R D { M.{ { k.FXHXHXHXJXJXJXJXJXJXJXJXJXJXJX$XK d.S.G.~.~.^.7X7XpXVXVXaXqX7X7X7X^.^.7X^.^.^.~.L.Z.f.X.U 2 @ 2 - q q u u u n O.{.*X*XZ.v.N 0.x d y , < 1 < 0 k g.}.}.}.}.}.;X,XlXlX#XOX.X&XH.Z.o.%.n q 9 5.v.;X~.G.S.S.J.4X6X0Xj.f m m b u t K T ( ) ] A B * 0 u b m m b v U Q ^ / / / / / i.) oXJXJXJXJXJXJXJXJXBXx FXPXPXPXPXPXPXPXPXPXPXPXGXNXcXhXhXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXBXU o.FXGXPXPXPXHXHXFXnXnXoX{ { ' ' ' { { _ _ _ _ _ Q Q k.%.u.u.E.E.E.E.E.E.E.E.E.E.E.1.-.:.BXnXvX]./.A 6.$XgXhXzXcXvXvXnXvXnXnXvX].FXPXPXPXPXPXPXJXGXJX}.e.gXx.W.T.W.T.T.T.Y.9.DXPXPXPXPXPXvX].oXS +X + : % % % X k O.k.[.{.{..X XOX X{.j.f.X.b.V.C.C.S.F.F.F.J.J.S.s.' _ ( R @ * 0 b 5.z.c.;X1X>XyXMXMXmXbX9X-X-X*X&Xk.f.f.b.X.U L K K D F J H T Y R Y T Y R E E Y ] { { { { +.BXJXHXJXJXJXJXJXJXJXJXJXJXJXBXN U d.d.S.G.L.D. .*X5XVXVXVXtX7X7X7X^.7X7X^.~.G.G.V.n.m.[ ~ T Q H - q e d u b A [.*X*XH.h.Z g. .u m 9 0 z x Z C 9.j.9.9.9.7.9.}.+X9XjX0X5X=XP.J.s.K x u 0 A v.H.K.S.p.i.{ F.4XwX.Xh m b y 3 Y / / ^ ^ R L l < 0 u z b B b n | ~ ( / / / ` ` i.U cXJXJXJXJXJXJXJXJX].oXBXPXPXPXPXPXPXPXPXPXPXPXPXPXDXcXDXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXFXFXPXPXPXPXPXPXPXPXJXnXvXk.{ { ' { ' ' _ _ _ _ { { [ o.h.7.-.g `.x.t.E.E.E.E.E.E.E.E.E.u.1.].FXvX/._.7.'.gXgXhXzXvXBXBXBXBXnXnXnXcX%.GXPXPXPXPXPXPXPXPXzXe.8.e.W.R.1XW.W.x.+X$X`.).].].XX].].hX%.oX = = * = 5 6 v V C O._.*XwXVXVXVXVXmXOXx l k k : + O : +._.h.k.[.{.].[.k.+. .I ] n.m.C.F.G.J.G.L.L.P.P.P.F.B.p.p.{ = , u M 5.x.c.;XyXyXvXBXxXxX-X-X-X*X&XZ.b.b.f.b.U K G i D J Y T T R R R R R R R R R Q Q Q ( J L { c BXJXJXJXJXJXJXJXJXJXJXJXJXv.G.a.i.i.p.U v N v =X6XqXqXqX8XtX7X7X^.~.G.G.G.b.U m.[ { ) W 4 , 9 9 u u z B O.k.&XH.Z.N `._.A Z B 5.j x Z 9.0.0.9.`.9.j.j.j.|.+X9X*X=XP.P.L.B.M.+.BXM b d j.,X5XF.d.p.^.6XaXVX[.5.A A N p R ^ ^ ^ W R o., 5 r y z N .c N X.n.{ ' ` ` i.` i.j.JXJXJXJXJXJXJXJX%XgXnXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXnXbXbX].I L P ! ! T ! ! L I jXcXcX:.<.:.-.4.vXNXNXFX+Xt.u.E.E.E.E.E.1.`.9.e.y.y.e.l.y.I.T.9.oXnXkX].k ).].C oXcXcX/.].PXPXPXPXPXPXPXPXPXMXW.T.XX(.DXnXvXcXzXzXzXzXhX|.).V X0XmXBXbXxX0X0X*X*X=XH.Z.Z.n.f.f.] U i p D J Y Y R R R R R Y R R R R R E E W ^ Y J ] `.JXJXJXJXJXJXJXJXJXJXJXJXXXV.P i.{ ] ....} X.K.4X7X8XtX7X7X7X^.^.~.~.D.f.p I ] ' ' ( 4 : , , < 0 k b N O.k.k.Z.k.v cX].h.j.A n 6 z C Z 0.9.0.`.`.j.`.].oXOX*X=XK.P.P.L.F.J.].JXS B f 7.;XjXwX=XaXaXAXKXmX.Xv.h.k.h..._ ( ^ ( W ) c 6 < 6 t v .j.t } n.V.d.i.i.i.i.` p.'.DXJXJXJXJXJXJXJX].vX#XPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXBXcXcXvXvX-Xo.] ] $.] ] ] P *X%X#X1.1.,.,.-.0XnXBXFXGXiX.Xr.E.E.E.t.:.e.z.|.B 6.XXhXhX%X|.x.y. : * : : 1 k z N O.h.k.f.b.Z GXBXZ '.`.Z l l C B S 0.0.j.`.'.].{.oX*X*XH.J.J.L.L.P.Z.OXJX).B b 5.c.>XiXIXIXIXIXUXKXxX-X*X*Xb.n.{ / ( W ^ G 6 6 5 < y I ..I p I n.S.S.S.i.i.i.` f.cXLXJXJXJXJXJXJXJX].S PXPXPXPXPXnX|.PXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXBXcXcXvXnXnXnX-Xo.$.[ ] P >.t.U.u.,.-.-.,.:.}.nXBXFXFXGXJXcXx.u.1.r.z.$XvXBXA e.oXkXkXzXcX k t z c | a I U ] ] m.B.B.M.B.B.4XqXaXwXqXqX6X4XL.G.B.@.> l n N g. X-XwXwXwX*X*X=XH.K.K.A.D.n.n.n.n.n.U K G K G J T T R R R R Y E R W ^ ^ ^ / / / / / T 5 DXJXJXJXJXJXJXJXJXJXJXJXLXg.K _ i.p.d.s.m.N.S.G.L.L.^.^.^.^.^.^.H.k.f.i p G ~ ) ^ 4 : O + # > 1 k z v .f.f.f.X.O.%XJXZ [. XS M l v A 9.j.`.`.v.'.[.{.&X&XH.A.J.J.L.J.L.N GX].Z M B 7..X0XiXSXSXSXIXIXKXwX5X6XP.V.n.[ p.{ T D t l a a i K X...i K ] M.B.S.S.S.d.i.U #XJXJXJXJXJXJXJXJXJX).`.PXPXFXnXzXkXgXzXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXPXGXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXBXcXcXvXnXBXFXFXFXk.$.K 1.E.E.E.E.E.E.,.g -.4.nXFXFXFXNXJXJXJX6.w.}.vXnXnXvXS e.8.%XzXzXvXhXy.}.kX ] p.d.B.B.S.S.G.G.L.G.~.~.^.~.~.Z.n.n.n.P ! _ ( ^ D + @ = 5 6 6 l c v .o.....X.U o.N l v &XZ 6 > l O.g.j.`.'.k.v.k.k.Z.A.A.J.F.F.C.J.A.1 x < 6 z A j.;X0XaXKXVXKXSXIXVXwX6X=Xo.5 = = > = 5 k t c I } X.A...4 G ! s.d.d.d.d.N.v j.zXJXJXJXJXJXJXJXJXJXJX|.x PXPXPXBXvXzXkXvXGXPXPXPXPXPXPXPXPXPXPXPXUXPXPXGXFXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXBXzXcXvXvXvXnXBXFXcXN u.E.E.E.E.E.E.E.E.E.,.e ,XFXGXFXjXBXFXz.r.|.BXNXnXnX#X].].e.e.9.}.|.9.Y.XXhXgXgXgX < t M 0.'.@XmXmXVXSXSXSXaX8X6XH.o.t 5 5 6 6 t 6 t a I | Z.a 4 H H T _ ' ` n.).nXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXGX%.HXPXPXFXFXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXBX 2 3 a K ..N.A.A.b.K L ~ T L h.lXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXGXPXGXoX#XPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXkXgXgXgXgXgXkXkXkXcXBXGXGXPXGXGX%X/.#XGXPXPXPXcX&X..k.vXPXPXPXPXHXBXnXGXPXPXR.E.u.t.,.! @.PXmXc.E.E.E.E.E.E.E.E.R.>XY.Y.u.u.}.FXFXFXbX-X`.$XXX$X%XgXzXcXnXvXzXzXzXkXkXzXzXzXzXzXzXzXzX%.PXPXPXPXPXPXPXPXPXPXPXPXPXPX/.cXcXBXkX+XGXPXGXJXhX%XPXPXPXPXPXPXPXPXPXPXPXPX@X>XGXJXC cXvXcX).PXPX|.].FXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLX9Xv.^.7X7X^.7X^.^.P.L.P.J.D.V.V.n.b...I K @ 2 @ @ v GXJXJXJXJXJXJXJX#XX./ / / / / / / / ( ' i.d.S.S.F.S.S.S.F.G.J.J.V.I = = $ 2 v } .f.Z.K.P.=X4X=X=X=XZ.| S O.).).A r o . : : : = L T Q Q ( ^ ^ ^ ^ ^ / / ` d.^.^.P.P.P.L.L.P.^.4XaXaXwXwX-X X X*XH.K.Z.b.b.b.X.n.n.n.n.n.b.f.] b.X.X...U P ! T R E E E E W E T Y Y R ^ / / / / ` I JXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXLXlXj.- f a.p.p.i.d.d.p.p.' ` / ^ ^ ^ T 3 3 G P U ] n.] b.n.U b.] U U P ! ! Q Q W H 6 | p ] M.A..X*Xf.f.U U m.s.d.B.d.d.s.p.i.G p p p K | f.{.*X-XmXqX6X8X7X4X^.P.Z.} I K K G D 4 3 a K ] M.C.J.J.G.f.A `.vXGXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXGXPXHXFX/.PXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXBXzX).S gXhXkXzXcXnXBXFXGXPXPXGXFX%.+X#X]._.GX-X! ! #.~ L XPXPXPXPXPXJXPXPXLXcX}.u.K ] { k.PXPXJX|.r.E.E.E.E.E.E.@X>XU.U.Y.Y.e.FXGXFXcX/.#X#X|.C %.%XkXcXvXcXkXkXkXkXkXkXzXzXzXzXcXzXzXS cXPXGXFXPXPXPXPXPXPXPXPXPXPXcX%.%.oXcXGXPXGXJXJXGX].GXPXPXPXPXPXPXPXPXPXPXPXJXGXJX).oXnXvXnX].vX].cX/.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX,Xv.~.^.7X^.^.^.~.L.L.L.J.F.V.V.N.#.@.K K @ 2 2 @ A JXHXHXJXJXJXJXJXoX! ^ / / / / / / / ` i.i.d.S.S.S.S.F.S.G.G.J.V.Z.a @ O = v o.f.Z.Z.D.P.P.P.=X4XP.A.f.Z S O.%.Z x : # < * 3 J Q ) W W W ^ W ^ ^ ^ ( ' B.P.L.L.L.L.L.L.^.^.8XVXVXVXVXmX0XOX-X*X*X*Xb...} } X.X.n.n.n.X.X.f.@.X.X.X.U P ~ T E E ( ( _ Q J J J G Y R W ^ ^ ^ ` U lXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXoXO.I s.p.i.i.i.` / / E T J Y L L L ] ] n.n.n.n.n.a.n.] ] ] ] ! ~ Q Q E D K A.A...K _ M.3XH.X.K ! [ s.s.s.d.d.p.i.' ~ p K K } o.f.Z.*X3XwXwX6X4X4XP.P.J.A.n.] P J J F F J G K U M.B.V.k.'.zXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXfX$XPXPXPXPXJXPXJXPXJXPXJXPXPXJXPXJXPXJXPXJXBX$X:X%.kXcXcXvXnXFXGXJXJXGXGXGXnXS +X+XOXoXM ! ] hXPX + D Y T R W W W W W ^ W W W [ s.C.S.C.S.S.S.S.S.G.L.8XtXVXSXUXUXUXUXKXKXmX0X0X*X&Xk.a a I f.b.n.n.b.f.X.X.f.X.U ] [ ( ` _ { [ ] L P J G D D F Y W ^ ^ / / ~ HXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHX_.) / ( / ( ( ( ) ) [ [ ] [ [ [ a.[ p.[ { _ _ ) R Q T ! N s.M.N.N.N.N.C.J.F.I ] ) i.i.p.p.p.p.i.` K v J L L U U n.m.V.J.=X6X=XP.L.J.C.C.B.s.{ { { { ' ' _ +.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXJXJXJXJXJXJXDXJXGXPXGXJXJXJXPXJXJXJXJXJXJXJXPXJXJXJXJXJXJXPXPXPXGXGXPXGXHXHXHXJXJXvXXX].%X$X%XoXU ! O.].%XXBXnXkXkXzXzXzXcXvXnXnXBXBXXXFXJXJXJXJXPXGXGX C gXJXJXJXJXJXJXJXJXJXJX+X .{ ' _ _ ( ' { p.s.d.s.M.s.s.d.s.p.p.{ { { { [ ) [ ' _ ^ ^ / / ^ / / / / / ^ / ^ ^ ^ / / / / / / / p.C.C.C.F.=XJXJXJXHXJXJXJXJXGXJXJXJXJXJXJXJXJXJXmXwXJ.S.J.K.H.Z.Z.X.] ] [ ` ( ^ ^ / G 4 p K vXGXPXGXGXGXPXGXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXBXU ^ / ^ / ^ / / / N.JXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXJXJXJXJXGXHXHXPXJXJXJXJXJXJXJXJXGXGXJXJXJXDX,X/.2.2.3.3./.fXDXJXPXJXJXJXGXFXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXPXPX#X$X$X$X$X$X%XgXgXhXkXzXnXFXJXJXJXJXPXPXJX3.2.2.fXPXJXJXJXPXPXPXPXPXPXPXPXBX$X).kXzXcXvXnXBXGXzXT.Y.e.XXBXnXBXnXBXnXnXzXzXcXvX#Xe.E.e.hXGXGXJXPXGXGXFXBXnXzXzXzXzXcXvXnXBXBXFXnX].JXJXJXJXJXGXPXXr.u.$XFXFXBXBXBXBXcXcXcX_.r.y.}.FXGXJXGXPXJXFXFXBXFXBXcXzXzXcXcXnXnXBXFXBX$X$XGXJXJXJXJXJXnX`.XXS $XkXzXkXkXcXkXcXcXnXFXFXFXnXvXkX].kXkXkXzXzXcX$X|.oXhXhXXX|.k S JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNXj.i.i.i.i.' ` ( ^ ( ^ ^ ^ / W R T H D 3 3 3 3 3 2 2 5 2 2 2 5 2 V FXJXJXJXJXJXJXJXJXJXh.N.s.{ ' _ { p.s.s.s.s.s.s.s.p.{ { _ ( _ _ W ( W W ^ ^ ^ / / / / / / / / / / / ^ ^ ^ ^ / / / / / _ s.C.C.J.6XJXJXHX+XS %.%.].oX+X%XkXvXBXJXJXJXJXJXJXJXLXJXmXJ.M.s.s.a.[ _ _ ( / ^ 4 K K G -XJXJXBX%XoX`.).S V x x k j k 1 1 : # 1 FXJXJXJXJXJXJXJXJXJXJXJXJXJXGXXPXGXPXPXPXJXvXhXgXgX%X#X#X#XS zXDXPX.XE.,XPXPXPXPXBXcXcXvXnXFXFXnXvXnXBXnXvXvXvXcXcXcXcXkXnXvXnXnXnXnXBXzXhXhXgXgX+XJXJXGX).hXkXvXBXFXGXGXPXPXPXGXGXPXGXGXPXFXBXzXXPXPXPXPXGXnXcXvXzXC %.#X HXJX[.] X.b.[ ( ( ( W ^ ^ ^ ( ( _ _ ( ( ( ^ ^ / ^ ^ ^ ^ ^ ^ / / / / / / / / ` { G * # * @ @ = 4 L ! ) ( ^ ^ / / ( ' J.GXPXGX].. X %.JXPXGXA.W E =XPXPXGXGXx Z JXJXJXJ.( ( _ W ( Q Q Q XJXJXJX%. # zXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].X S JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXgX. . 1 JXJXJXJXJXJXJXJXJXJXJXJXJXJXGXx X X V fX/.3.3.(.NXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX`.+ X `.JXJXJXJXJXJXJXJXJXJXJXJXFX1 . 1 %.: . : gXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXC . 1 FXJXJXJXPXPXPXPXPXPXPXGXPXGXGXFXBXFXFXGXGXFX#X%X/. > * @ + X @ i K ] [ J.JXJXJX].. X %.JXJXJXA.E N.GXPXPXGXoX: x JXJXJXwX{ ' ' ' ` ` ` _ ` C.JXGXJX%.. # cXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJX].X %.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXkXX . k PXJXJXJXJXJXJXJXJXJXJXJXDXx . . . /.nXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXV . . V GXJXJXJXJXJXJXJXJXJXJXcX: 1 BXGXGXJX|.# . j cXJXJXJXJXJXJXJXJXJXJXJXJXJXJXx . k JXJXJXJXPXPXPXPXPXPXPXPXPXPXPXJXGXGXGXgXV hXGX).GXJXJXJXDX3.2.&.&.2.2.DXJXJXGXFXGXGXFXnXcXgXgX%X > = : > > = * @ + @ * K ! ] =XJXJXJX].. X /.JXJXJXA.$.GXGXGXHXcXx X # gXJXJXJXF.{ p.p.' ' ' _ ( _ A.JXJXJX%.. # cXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPX].X %.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXzX. . k JXJXJXJXJXJXJXJXJXJXGXPXXX: . # nXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX`.X 1 JXJXJXJXJXJXJXJXJXJXJXcX: . . 1 BXPXGXGXGX|.# X k vXJXJXJXJXJXJXJXJXJXJXJXJXJXk . x JXJXJXPXPXPXPXPXPXPXPXPXPXPXPXPXGXFX#X).PXPXGX%XJXJXJXJX(.2.&.&.&.2.8.JXJXJXGXGXGXPXGXGXnXkX/.x gX#XS GXPXPXPXPXPXcXl.Y.FXBXcXXX%X%XgXkXcXvXvXvXcXzXkXnXBXvXzXkXkXnXnXkXkXzXzXcXcXvXcXcXkX 5 = = @ @ @ = L ] &XGXGXPX|.. X %.KXGXGX5XGXPXGXGXGXS # X S JXJXJXbX{ { p.p.i.' ' ' ( _ A.PXJXJX%.X # cXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].X ).JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXzX. . j JXJXJXJXJXJXJXJXJXJXGX:XV . C JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXGXGX$XX # GXJXJXJXJXJXJXJXJXJXJXkX: . . 1 BXGXPXJXJXJX].# X k nXJXJXJXJXJXJXJXJXJXGXPXGXk . x JXJXJXJXPXPXPXUXPXPXPXPXPXPXPXPXGXnX`.PXPXGXJXGXPXJXGXfX2.&.&.&.&.2.:XJXJXJXGXGXJXJXPXPXPXFXV ).kXgX#XcXJXPXPXPXJXcXr.I.GXBXcXgX%XgXkXcXcXvXvXcXzXkXkXFXFXnXvXzXhXkXnXkXkXkXcXcXcXcXcXcXkXgXXJXPXPXPXPXDXzXhXkXkXcXcXcXkXzXkXkXhXhXgXhXvXnXFXPXGXPXGXGXGX$XXXhXkXzXcXnXFXGXoXXJXJXJXJXPXPXPXPXPX].oXXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX|.BXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXFXBXnXgXkXcXcXcXvXBXFXFXnXnXBXvXkXkXcXBXGXPXPXPXPXPXPXPXPXPXoXPXnX].JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX2 T / / / / / / / / / / / / / ^ / / / / / / / / W +.JXJXJX].G D D D F H H R R W W W W W ^ ^ W ^ ^ ^ C.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX3.&.&.(.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXfX/.3.2.&.&.&.&.&.=.2.&.&.&.&.&.&.2.:XJXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX).GXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXPXGXGXvXkXvXFXFXFX%X].].oXXXX|.%.C FXPXPXPXPXPXPXPXPXPXPXPXPXXXhXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXO.@ H / / / / / / / / / / / / / f.kXJXJXJXJXJXJXJXJXJXJX).Y T R W ^ ^ / / / / / / / / / / T .NXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX3.&.&.&.2./.PXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXfX(.3.2.2.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.2./.NXJXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFX|.PXPXPXPXPXPXPXPXPXPXPX%X|.hXJXJXJXJXJXJXHXHXJXJXJXJXJXJXPXgX).|.$XoX#X%XkXBXPXPXPXPX|.kXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX].i 4 G J G H H G I P P J K [.GXJXJXJXJXJXJXJXJXJXJXLXkXG R E W ^ / / / / / / / / / / U v.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX(.2.&.&.&.2.(.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXfX/.3.3.2.&.&.2.&.&.&.&.&.&.&.&.&.&.&.&.&.&.3.(.NXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX|.PXPXPXPXPXPXPXPXPX%X|.kXJXJXJXJXJXJXJXJXGXPXJXJXJXJXJXJXGXGXGXPXPXGXcXgXoX`.%.%.+X].BXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXk.J / / / / _ I gXBXlXkXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJX| T W ^ ^ / / / / / / / / ^ } 9XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXNX2.&.&.&.&.*./.NXJXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXDXMX:X/.3.2.*.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.*.&.2.3.:XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXFX#XXXXX].XXoXoXoXoXvXJXJXJXJXJXJXJXJXJXJXHXGXHXPXJXJXJXJXJXJXJXGXGXGXPXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXxX[.h.h.'.oXFXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGX+.R W ^ ^ / / / / / / / ] [.JXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXPX8.&.&.&.&.&.2.3.:XPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX:X(.3.2.2.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.2.2.2./.fXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXHXPXHXGXJXJXJXJXJXJXJXPXGXPXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX%XF ( ^ / / / / / / { k.vXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX2.&.&.&.&.&.&.2.8.fXPXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXDXfX(.8.3.3.2.2.=.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.2.3.:XNXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXGXJXJXJXJXJXJXGXGXPXGXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXK W / / / / / / n.@XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXXX&.&.&.&.&.2.2.&.2.3.:XGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXPXNXfX/.3.2.2.2.2.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.=./.fXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXGXGXPXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX'.J / / / / / U +XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX/.2.&.&.&.&.&.&.&.&.&.2./.fXDXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXJXJXJXJXJXPXJXJXJXJXJXJXJXJXDXJXJXJXPXJXJXNX>X(.3.2.&.=.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.2.2.2.3.fXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDX- T / / ` U @XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX(.=.&.&.&.&.&.&.&.&.&.=.=.3.3.(.>XNXDXJXPXJXJXJXJXJXDXJXJXJXPXJXJXJXLXJXJXDXDXJXJXJXJXJXJXNXNXfX:X(.8.3.2.=.&.=.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.2.2.8.:XDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLX%XA b.wXlXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX:X2.&.&.&.&.&.&.&.&.&.&.&.&.&.=.2.3.3.8.8.(.:X:XfXfXfXfXfXfXfXfXfXfXfX>XfX:X(././.3.8.3.3.2.2.&.&.&.2.=.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.=.*.3./.fXNXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXPXPXNX3.=.&.&.&.&.&.&.&.&.&.&.&.&.=.=.&.2.2.&.2.2.2.2.2.3.2.2.3.2.2.2.2.2.2.2.2.&.2.2.&.&.&.&.=.=.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.=.2.3.(.lXFXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPX:X3.*.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.2.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.=.=.=.2.3.3.:XNXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXPXJX:X3.2.*.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.=.=.2.2.3./.:XfXJXJXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXJXJXGXfX/.3.2.=.*.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.2.&.&.=.=.2.2.3.3.(.>XNXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXfX/.3.2.2.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.&.*.2.2.2.3./.(.>XNXJXPXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXNX:X(.8.3.2.2.&.&.&.&.=.&.&.&.&.&.2.&.&.=.&.&.2.&.&.&.&.&.=.&.&.=.=.2.3.3.3.8.:XfXfXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXJXDXNXfX:X/.8.3.3.3.2.3.3.2.2.3.2.2.3.2.3.2.3.3.3.3././.:X:XfXMXNXDXJXLXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXJXDXNXNXlXlXfXfXfXfXlXMXNXNXFXGXHXHXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXJXJXJXDXGXJXJXJXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJX", -"JXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXPXGXGXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXHXHXPXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXPXHXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJX+X`.GXJXJXJXJXJXJXJXJXJX GXJXJXJXJXJXkX %.JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXk XXJXcXA kXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX: gXJXJXC /.FXHXHXHX. JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDX . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX#XS DXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJX: hXJXJXJXGXPXJXJXJXJXx ].JXJXJXJXJX1 #XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX%X `.JXJXJXJXJXJXC cXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXx XXJX]. S JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXHXGXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXPXGX: . gXJXJXC /.JXJXJXLX JXJXJXJXJXJXJXJXJXJXJXHXHXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDX . JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXl $XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJX: gXJXJXJXJXGXJXJXJXJXx ].JXJXJXJXJX1 +XJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXV X nXJXJXJXJXJXDX+ x JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXk ].JXFXoXBXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXHXHXGXKXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXKXPXPX: gXJXJXZ O.JXJXJXJX JXJXJXJXJXJXJXJXJXJXGXPXPXJXJXJXJXJXJXJXJXJXJXJXGXJXJXFX . JXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXvX+XJXJXJXJXJXJXJXJXGXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXDXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXLXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJX1 %X%.x j C kXJXJX).j + : 1 V JXS j X : j Z JXnXk S gXC k k S cXJXJXJXJXzXS k j V +XJXJXJXJXJXJXJXJXJXJXBXX x JXJXJXJXJXJXXX +XJXJXgXk ].].k k ).GXJXGXoXx j k Z $XJXJXJXk |.JX#Xk XXJXJXPX . oXJX%X. # nXJXJXJX`. k GXx `.JXJXJXx ].JXJXJXJXJXj +XGXk ).JXJXJXFX1 ].JXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJXJX", -"JXJXJXJXJXJXJXJX: . ).JXGXPXGXx ).JXJXx ].JXJXJXJXJXj +XJXJXJX.,X>X%X%X&X&X:X%X%X%X%X&XY } =.8.U ;.BX7X7XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.. `.7.@.8.p.8.8.p.y.i.i.8.8.i.p.p.8.| l.Q.T +.y.p.y.i.i.i.@.s.7XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVXVX#X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+X] s t s s s s s t t t p x ] X+X+X7XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVX@X X+X+X+X X#X5 e j f p s t t t t s s s s s s s s s s s s s s s s s t t s p j ` +X+X7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X7 *X:XsXeXwXwXqXuXfXxXnXxXdXqX3X2X0XkXnXzXpXpXpXxXzXpXpXpXzXkXkXzXxXgXeXeX3X2X2X3XqXgXsXsX2X3X4XfXsX0X0X0XpX0XkXbXcXlXlXlXlXkXlXcXbXbXbXbXvXMXvXcXcXcXcXcXlXlXlXkXcXbXbXcXbXcXkXkXxXdXuXpXlXkXuXxXxXfXuXpXzXxXfX4X2XkXbXbXcXcXbXcXbXbXbXkX0XkXkXkXkXlXlXcXcXcXcXlXkXkXkXkXlXlXlX{.{.-XX-X2X{.I | t.E t.t.R Y l.7.^ +X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVX(.Z.;.T 3.9.0.i.i.i.i.i.i.i.8.8.i.8.i.i.8.*.3.&.7.&.| &.VX-.| +.+.s.SX@X#X#X#X#X#X#X#X#X#X#X#X#X#XBXSXK.L.K.9.0.R.BXAX#XmX@XBX!.;.s.7.@.@.H.7X#X#X#X#X7XVXs.a.a.@.K.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+X@Xd t t s s s s s s s s s s t t t t t s s i i i p d d d d d d d d d p p i i i s s t t t t t t t t s s s s s s s s s s s s s s s s s s s s s t t t t i f x SX X+X+X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ $XsXqXwX3X3X3XfXxXfXsXwX4X3X0XzXkXnXnXpXkXxXzXkXpXkXlXnXnXkXlXfXeXwXsXsXhXhXgXsXsXwX3X3XlXlXkXzXpXpXpXpXkXcXzXnXnXnXMXMXMXvXlXkXkXcXbXbXbXbXcXbXbXbXvXbXbXbXcXbXcXcXbXbXvXuXeXqX3X3X0XkXkXxXuXzXvXlXxXzX0XuX0XvXvXlXlXlXbXcXvX'.vXvXlXlXlXvXcXlXcXcXcXcXcXbXN.,X,X,Xf.n.b.m.B.m.m.w.w.G I.>X:XdX-X-X:X{.3.5.5.t.t.E E U Z.. #X_.#X#X#X#X#X#X#X#X#X#X#X#X#XBX$Xi.3.U +.8.0.s.i.p.i.i.y.i.y.i.i.i.8.i.8.=.7.3.3.+.3.| A.. ` 0.-.L.VXBX_.% #X#X#X#X#X#X#X#X#X#X#XBXW.9.@.6.p.-.s.p.L.+X+X. +X;.i.8.8.p.i.@.s.@X@X% #X#X+XC.@.G -.y.a.`.VX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X X+Xx s 9 t s s s s s s s s s s s s s s t t t t t t t t t t t t t t t t t t t t t s s s s s s s s s s s s s s s s s s s s s s s s s t t t t s p g v #X+X+X X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XD jXqX4XwX2X2X4XxXfXsXwX3X3XuXnXnXzXuXkXzXnXzXkXkXkXkXkXlXlXcXlXqXeXwXsXgXsXsXfXsXqX3X3XkXlXkXkXlXkXkXpXpXlXlXzXkXlXlXvXMXvXlXlXlXlXcXbXbXcXbXvX'.J.h f.[.vXbXcXcXbXcXbXbXcXeXwX4X3XuXlXkXxXzXzXvXnXnXzXpX4XpXvXvXvXlXlXbXcXvXMXvXlXcXbXcXLXLXbXcXcXbXvX6X,X,X,X,X,Xg.b.b.w.B.m.m.m.w.w.w.Y.L.[ [ [ hX:Xl.+.3.5.5.t.5.U l.(.BX#X#X#X#X#X#X#X#X#X#X#X#XVX#X7X$X8.+.@.7.+.@.i.p.p.p.a.6.6.i.@.8.7.7.i.9.&.7.&.3.| 3.C.+X#X7X7X7X+X@X_.#X#X#X#X#X#X#X#X#X#X#X#XVX`.H.a.8.a.a.s.s.0.9.;.;./ ;.-.a.p.i.9.0.i.8.!.CXVX_.BXP 6.y.s.-.p.y.F.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X@X+X#Xg s t t t s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s t t t t t s p f e SX X+X+X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #XAX_ yXtXwXwXeX2XsXgXsXwX3X3XuXkXxXzX4XeXxXnXzXkXlXkXkXkXkXzXgXxXdXrXwXeXsXsXfXsXsXwX3X2XkXcXkXkXlXkXkXpXpXlXcXvXvXvXcXvXvXnXlXlXcXlXcXbXbXvX'.G.l.v.c.v.=.v.f.'.cXbXbXbXbXbXkXfXuXpXvXvXzXxXuXpXMXMXnXpXpXuXpXcXcXvXlXcXbXcXMXvXlXlXbXbXbXbX<.,.LXbX,X,X,X,X,X,X>X,Xz.n.b.b.m.m.m.w.m.n.m.L.L.C.C.H.[ .Xk.| 7.*.*.3.5.5.O.=.#X@X#X#X#X#X#X#X#X#X#X#XVX` K.L.` K.+.+.+.H.-.y.a.a.6.C._.W.`.S.+.&.*.&.T 7.+.0.(.R.^ +XVX#X#XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXVX+XC.8.s.7.8.9.q.i.9.9.7.*...*.i.p.a.8.0.-.p.7.8.R.+X7X7X-.@.p.0.a.p.p.F.7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmX#X X+XSXg i s 9 t s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s t t t t t s i p f x ` X+X+X X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ D }.mX*X%X%XsXsXwX3X4XkXzXzXpXqX%XdXnXkX0X4XxXpXkXpXiXCX. _ fXpXqXeXsXxXxXsXsX4X3XpXlXvXkXlXpXkXkXpXlXvXMXMX'.MXMXlXcXcXcXbXcXcXcXbXl...j.z.v.f.f.z.d.v.=.'.bXbXbXbXbXvX,X{.vXMXvXkXzX0XpXMXnXnXkXpXuXpXcXcXlXlXcX9XvXvXlXlXbXbXbX9XvX,X,X6X,X,X,X,X,X,X,X,X9Xj.g.g.n.n.m.m.b.b.n.B.C.H.S.S.S.S.[ w.1.t.+.7.&.3.3.5.| Z.CX#X#X#X#X#X#X#X#X#X#XVXL.L.C.H.`.` L.L.P V.8.9.=.3.&.(.. . `.*.3.*.*.&.7.8.` . +XBX#X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX7X7X7XCXm.s.s.8.q.i.9.0.0.a.8.*.E Y u.3.p.a.i.=.i.9.8.8.Y.BX7X9.@.p.i.p.p.y.F.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X X+X].N g i t t t t t s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s s t t t t t t s i p f j a #X X+X+X X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XD D Z =X%XeXsXwX3X3XpXzXxXpX4X%X%X:X:X:X%X:X:X-X%X%X:X=XaX4X4X%XsXfXfXxXsXsXqX3X0XcXkXlXkXkXkXpXpXlXMXMXMXMXMXMXlXlXcX6XbXbXcXbXG.*.z.j.z.d.f.d.G.z.J.J.G.,X,XbXbX,X>X>X>X>XMXMXnXpXpXvXMXnXMXkXpXuXlXcXlXlXlXcXbXcXcXcXbXbXbX9XbXbX,X,X,X,X,X,X,X,X,X,X,Xh.G.v.f.f.z.g.S.m.w.n.B.S.V.B.B.B.B.B.S.g.X.r.r.&.7.*.3.O.;.CX#X#X#X#X#X#X#X#X#XVX_.Y.W F.S.U.. 7XY.5.=.c.u.5...O.:.Y.. 7X=.3.&.*.&.&.q.+XBX_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XBX] m.-.Q n.L.H.q.i.=.i.0.a.i...M.l.l.=.&.8.p.v.T q.n.q.i.=.(.R.0.-.=.0.p.i.y.F.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X+X+X@XN g d i s t 9 t t t t t t s s s s s s s s s s s s s s s s s t t t t t t t t t s i i d f x v ] X+X+X X@XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X< Z &X:XsXsXqXqXuXxXzXuX-X:X-X:X:X:X-X:X:X%X:X:X%X:X:X%X%X%X-XfX0XsXsXsXqX3X4XlXkXlXlXMXnXkXkXlXvXcXvX'.MXMXvXkXcXbXvXbXcXzXJ.d.z.j.z.d.z.G.G.l.{.,X>X>X>X>X>X>X>X>X>X>X>XMXkXkXkXlXvXnXnXkXpXuXvXbXcXcXcXbXcXbXbX[.J.v.G.bXvXvX,X,X,X,X,X,X,X,X,X,XL h.j.c.J.z.G.G.v.G G m.m.S.V.V.B.B.B.m.V.C.S.j.,.r.@.7.| | ' X#X#X#XAX#X#X#X#X#X7XP S.K.L.H.Q ;.*.5.&.=.i.*.3...*.4.{ g.g.*.&.&.7.=.&.&.C.+X7X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX7X7Xb.+.@.y.i.=.b.T =.=.n.p.a.5.d.H.p.i.i.9.0.=.&.9.q.T 9.9.p.B.T 0.s.=.8.8.i.6.Q 7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X@X+X+X X#X` z g f p i i s s t t t t t t t t t t t t t t t t t s s i i d d g j e n ] 7X X+X+X X7X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X< yX%XsXsXwXsXxXxXzXuXwX:X:X-X-X-X:X:X:X:X%X:X:X:X:X%X%X%XsXxX4XxXxXsXqX3X4XkXlXcXlXMXnXkXpXcXvXbXbXvXMXMXvXkXlXbXbXbXcX>Xc.l.G.z.f.f.z.G.f.z.x.j.X.x.,X,X>X>X>X>X>X>X>XpXvXkXkXkXkXMXnXkXpXpXcXcX'.9XbXbXbXvXd.T c.v.c.l.Y z.G.,X,X,X,X,X'.x.j.h.N.h.x.f.v.d.k.X.N.{.dXS.B.C.S.S.S.V.V.B.S.V.C.V.1.$.2.&.-.P @X#X#XBXVX@XVX#X_.#X@X_.H.S.C.H.C.L.V.3.&.7.*.&.7.7.*.*.*.4.} :.5.&.7.7.7.7.8.3.w.+XVX#X#X#X#X#X#X#X#X#X#X#X#X#X_.#XBX. V.3.i.i.0.a.&.b.0.=.8.9.p.p.4.8.o.p.p.p.y.y.i.T =.=.8.9.s.0.7.8.=.7.i.8.8.p.6.F.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX@X X X+X+X X#X8 N v x x x x x x x x x x x x x x x x v n ` _.@X7X+X+X+X X X X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).< =X:XsXsXwXfXxXuXqX%X%X%X:XSX=X-X%X%X:X:X:X:X:X:X:X:X&XsXgXhXxXfXsXqX3X4XzXlXcXlXnXkXkXcXcXMXMXbXbXMXMXlXlXkXcXbXbXcX[.q.v.d.l.f.d.d.v.J.L x.h.L F F {.>X{.>X>X>X>X>X>X>X>X>X>XnXnXnXkXpXpXcX[.l.z.'.{.h *.d.f.c.v.c.f.z.k.l.'.,X,X,XE ..d.d.x.h.L N.j.k.j.J.A .X-X,XJ.o.V.S.S.S.C.S.S.V.B.S.S.d.r.2.2.u . . BX@XW.Z.L.` @XBX+X. DXB.S.H.S.H.K.C.7.3.7.7.7.7.7.7.&.5.5.5.5.*.&.7.7.&.&.7.T | ;.. VXSX#X#X#X#X#X#X#X#X#XmX#XBX7X$XY.0.0.8.p.i.7.i.0.p.i.i.i.8...z.i.y.p.0.0.p.q.c.q.8.q.9.i.s.0.8.8.8.i.i.p.p.6.s.#XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X@X X X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X+X X X7X@X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.mXD < =X2XfXqX0XpXfX:X%X:X%X%X=X=X%X:X:X:X:X:X:X:X:X:X&X&XdXxXgXxXxXsXqX4XqXxXkXcXvXnXkXlXcXvXMXvXcXcXvXMXMXlXkXlXbXbXcX0 q.v.d.d.v.J.f.v.x.h.h.N.L N.1.9X,X>X,X,X>X>X>X>X>X>X>X>X>XnXzXkXpXMXj...d.J.l.v.=.d.z.v.v.f.f.l.d.z.E {.,X,X'.E d.l.J.z.h.N.L <.x./.$X+X+Xg J 1.g.w.m.K.H.V.S.S.S.S.S.C.d.I E R 2.g.A.' R.B.B.B.K.VX(.Y.V.Y.S.S.S.S.S.C.K.9.&.7.i.y.8.&.&.&.&.5.t.4.5.*.&.&.*.&.&.T =.U A.+XAXmX#X#X#X#X#X#X#X#X#X7X!.K.S.+.s.s.i.a.9.=.8.i.p.i.i.8.&.u...p.a.p.9.9.0.s.b.9.9.q.i.p.i.i.p.p.p.p.p.0.i.y.W.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X< D *X:X2X2XtXAX*X:X%X:X%X:X%X:X:X:X:X:X:X:X-X:X:X:X:X&XgXzXxXxXsXqX4X4XzXkXvXMXnXkXkXlXcXcXlXcXcXvXMXMXMXlXkXcXbXcX[.T f.z.z.f.l.n.Y $.F L L N.N.h.'.,X,X,X>X>X>X>X-X>X-X-X>X-XkXkXpXpXj.R z.J.d.f.f.f.z.G.J.c.J.z.z.d.z.z.x.6X8Xj.J.l.d.z.d.x.N.N.N.HX. +X#XCXQ.{ { X.n.C.K.m.w.B.V.S.C.C.B.%.2.4...5.} l.S.B.V.S.V.C.Y.q.3.3.T.Y.S.S.V.S.C.K.p.6.i.8.3.4.2.1.2.r.t.t.4.%.4.t.*.&.&.7.8.8.3.O.A.+X#X#X#X#X#X#X#X#XSXBXW.s.-.s.7.8.y.p.p.8.&.&.i.p.y.p.i.7.=.&.=.p.q.i.p.p.a.a.l.=.8.i.i.p.p.a.p.p.p.p.y.6.P.CX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXD #X*X}.~.D D yX&X:X%X:X:X:X:XrX:X-X-XrX=XtX:X-X:X:XsXxXxXxXsXqX4XpXpXkXvXnXlXkXkXkXlXcXbXbXbXcXMXMXvXlXpXcXbXcX-Xf.l.d.G.d.f.f.{.{.{.x.h.x.N.x.{.,X>X>X>X>X-X-X-X-X-X-X-X-X>XkXkX,X{.k.z.z.J.f.l.z.J.d.G.d.J.J.J.z.z.G.h.>.>.j.z.z.G.G.z.x.N.h.J.@X@X#X#X#X. I.<.v.m.w.b.m.B.B.S.V.b.T.g.z.R r.O.I *.K.K.S.S.S.V.V.V.H.S.Y.H.S.H.H.H.H.K.V.7.8.u.>.#.#.1.#.>.<.#.%.4.4.4.t.*.&.&.&.8.T 7.U T 7X@X#X#X#X#X#X#X#X#XBXK.s.i.&.8.8.p.p.p.i.5...8.i.p.p.s.s.9.9.T 9.8.i.p.p.a.8.t.&.8.i.p.a.a.a.a.a.a.i.@.8.( BXBX_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XD D D _.#X#XD D iX:X:X:X&X:X:X:XrX*X_.D _ Z *X:X%X:XsXxXxXfXuXzXpXuXzXMXvXlXkXkXpXpXcXbXcXbXvXcXvXMXlXkXvXbXbX-Xg.d.v.v.J.z.G.{.-X{.x.x.j.h.9X,X,X>X{.>X>X>X-X-X-X-X-X-X-X{.6X9XN.N.G.z.z.f.f.J.J.z.x.9Xj.z.z.G.j.h.h.<.h.G.j.j.G.k.G.k.1.>.>.I.BXVX#X#X#X. FX>.v.V.b.w.m.V.S.S.m.n.B.Y.C.c.4...z.e.L.C.C.C.V.V.V.S.C.L.H.S.H.H.C.C.C.L.n.3.p.=.4.1.#.>.#.2.1.2.R u.R t.5.3.*.&.=.=.8.7.&.5.( +XSX#X#X#X#X#X#X7XW.B.o.7.8.7.7.i.8.8.5.t.=.q.T 9.p.-.-.y.p.p.i.i.i.p.a.p.3.*.=.8.7.&.7.&.5.8.8.3.&.*.l...c.`.CX+XBXBX@XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXD }.tX=X:X:X=X*XD _ AX#X_.ZX7 `.iX&X:XeXeX:XsXnXxXxXpXkXzXpXpXpXlXlXcXlXcXMXvXcXvXMXlXkXvXbXbX2XX>X>X-X-X-X-X>X{.F #.#.N.<.G.c.d.d.z.J.z.N.$.h.d.k.x.x.A A.X.$.j.j.k.j.j.x.z.M.>.1.w.VXBX_.#X@X@XVX+Xf...m.T.w.T.V.C.K.C.L.L.C.K.C.B.B.I.H.H.S.C.m.w.V.V.S.C.C.C.C.C.C.C.H.C.K.s.s.8.8.8.3.t.t.%.%.4.4.R t.%.4.t.3.*.*.&.=.T 7.&.| n.7XVX#X#X#X#X#X#X+XQ.0.-.7.&.3.7.i.i.=.r.u.c.q.8.7.9.p.p.a.a.p.p.8.8.9.p.i.7.7.7.i.*.l.*.3.5.5.1.1.5.u.t.l.*.w.$XZ.Y.Z.#X7XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XD _ Z 1X$X< < AX_.#X#X#X#X#XD D 1X=X=X&X&X&XqXnXnXzXzXsXuXpXlXcXcXkXlXMXMXvXcXcXMXvXlXkXcXbX3X-X9.b.m.w.J.x.x.k.x.j.j.h.f.b.v.j.%.j.%.G.{.{.[.>X>X>X>XH x.L j.h.8Xj.v.l.z.z.f.G.N.N.x.l.d.k.k.@X. g.X.k.j.k.x.x.j.G.#.{ c.CX+X$XBX. BXVX. . . /.B.S.B.m.S.L.K.K.Y.S.Y.Y.Y.Y.V.T.m.V.C.C.V.m.V.S.S.C.C.K.K.K.K.K.L.L.T.H.-.5.&.9.b.s.p.&.2.2.2.r.4.4.4.4.5.*.5.3.&.=.&.&.*...DX+X#X#X#X#X#X#XBX' 3.7.8.*.8.0.s.s.q.q.9.9.9.9.7.9.0.p.a.y.i.i.8.7.7.8.p.a.i.6.3.m.[ &.8.8.*.r.4.3.5.5.l.f.*.=.=.=.7.m.#X@X#X#X#X#X#X#X#X#X#X#X#X#XSX#XBXBXBX7XAXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX7 < AX_.#X#X#X#X#X#X#X#X#X7 D 1X*X*X*X*XxXnXnXzXsXfX4XlXlXpXpXuXnXvXMXvXcXvXMXkXkXvXcXMX9.b.b.w.B.w.c.z.j.k.j.h.z.n.b.v.j.k.j.j.j...=.....z.k.Y j.j.j.j.j.h.N.G.l.J.z.d.d.h.N.h.d.d.d...Z.( j.j.k.k.j.x.x.G.h.,.2.3.Q . +X@Xl j.h.l Q.. . S.v.w.V.S.C.C.V.V.S.C.C.C.S.Y.C.S.C.K.Y.V.V.V.S.H.K.C.K.K.L.L.K.b.n.c.m.w.c.V.;.;.;.S.0.O.#.2.4.t.t.4.%.t.3.*.*.*.=.7.&.&.| Y.CX#X#X#X#X#X#X7X` 7.@.8.=.0.0.0.9.T q.9.i.i.0.p.8.*.7.8.8.=.=.=.&.7.*.4.3.&.&.u.b.q.7.8.8.7.u.3.*.*.&.&...&.i.9.0.s.7.C.+X#X#X#X#X#X#X#X#X#X#X#X#X#XVX` R.^ ` VX#X#X#X#X#X#X#X#X#X#X#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X).< D ~.OXuXuXzXuXqX4X0XkXuXuXuX0XpXlXlXcXcXvXMXlXkXcXlXMX=.b.b.b.b.w.T.m.d.j.j.z.c.v.c.v.j.z.G.x.x.z.d.z.z.j.k.k.k.j.j.h.x.x.N.j.l.d.z.d.f.h.N.N.d.f.l.f.l.k.k.G.z.z.j.x.x.#.#.#.>.>.... . j.J ,.,.,.<.z.y x.,.{ Y T.P.K.b.V.V.Y.L.C.H.K.K.K.C.C.L.Y.w.T.V.S.C.K.S.S.g.n.n.v.c.b.w.e.K.K.S.K.L.R.C.&.r.4.R 5.t.4.t.t.5.*.*.*.&.7.7.7.U v.VXVX#X#X#X#X#XVX X9.3.7.+.i.p.8.q.9.i.8.p.a.a.i.5...q.=.s.9.=.q.q.0...>.4.c.T *.5.*.8.8.8.*.t.&.7.*.=.*.7.-.0.8.9.s.6.V.7X#X#X#X#X#X#X#X#X#X#X#X#XBXW.8.@.i.i.Q 7X#X#X#X#X_.VXVX7XBXBX7XBX7XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X).AXgXuXuX0X0X0X0XkXnXxXxXuX0X0XlXlXcXcXlXMXkXlXlXMXc.z.g.w.n.g.n.n.m.g.j.z.c.c.v.v.v.j.x.k.j.j.k.f.d.x.G.k.z.d.G.j.h.N.j.N.x.d.d.d.z.v.x.$.N.k.v.l.v.d.d.f.l.d.G.z.X.<.>.#.1.#.>.<.g.J.J #.%.%.X.#.,.,.,.2.M.%.n.L.V.I.V.S.S.S.V.Y.L.C.L.C.K.R.K.b.T.B.S.S.V.m.T.n.z.d.T.T.T.b.V.~ K.S.Y.L.K.Y.0.3.4.4.t.t.4.4.u.5.5...5.*.l.*.7.&.U /.CXmX#X#X#X#X_.+X!.+.7.8.8.9.q.i.8.i.p.a.a.p.7.B.L.S.8.i.8.8.B.9.p.8.z.l.7.7.&.7.7.7.7.&.t.t.7.7.&.=.&.T a.p.i.i.0.@.B.BX#X% #X#X#X#X#X#X#X#X#X#X7XC.s.p.y.6.H.CXCX+XBX7X7X@X`.`.^ C.S.H.`.BXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ iXqXqX0X4X4X4XuXzXxXxXuXpXuX0XkXcXcXcXvXvXlXxXI.b.s.f.d.c.g.g.n.n.n.b.f.V.;.v.v.c.G.h.x.z.k.j.j.z.G.G.x.x.z.k.j.k.x.N.N.8XN.d.d.d.d.f.G.$.$.j.v.f.l.l.f.l.l.d.z.*.E h.#.1.1.1.2.r.<.J >.1.X.1.F $.#.>.%.S.K.H.b.b.Y.H.B.S.S.e.B.C.K.S.S.C.K.K.L.T.m.S.T.V.H.m.S.H.c.c.m.T.b.n.K.C.H.S.S.H.C.Y.B.&.u.t.r.%.r.2.O.t.5.5.5.5.E Y Y &.O.w.. . +X+XVX#X#XmX7X`.$X`.q.8.8.i.p.a.p.a.a.8.=.V.9.&.8.i.8.7.0.s.i.a.=...3.&.8.7.8.&.u.4.4.t.&.7.&.8.T 7.8.i.i.i.9.8.9.#XVX#X#X#X#X#X#X#X#X#XSX7X+Xs.0.9.8.6.L.SX;.S.Y.`.mXB.i.9.8.@.+.+.p.VX7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX#X7XBXBX7X#XmX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX_ rXqXrXeXqXsXsXsXxXxXzXzXuXuX0XzXcXbXcXcXcXbXjX[ c.b.I.z.z.g.n.g.g.n.n.c.Y.ZX] e.X.x.k.k.d.z.x.j.G.G.x.N.h.x.j.G.x.N.N.<.<.$.G.d.z.d.f.k.N.N.h.d.v.f.l.l.f.k.j.u.+.&...X.1.2.2.r.4.1.<.$.#.#.$.<.<.$.1.n.K.C.L.K.V.K.K.V.S.K.L.C.C.H.Y.S.S.K.L.K.S.S.V.b.B.B.S.S.Y.n.c.B.w.T.B.m.V.H.H.S.S.S.S.Y.q.5.*.4.2.r.#.M.&.5.5.u.4.u.u.E E E d.Y.!.R./ @XCX+X#X#X7X. ' 0.8.i.p.a.a.a.a.i.*...5.5.7.8.i.a.8.=.0.i.a.8.&.7.7.8.8.&.5.r.4.R %...7.8.q.8.7.&.&.8.8.8.9.T OX+X#X#X#X#X#X#X#X_.mX+X7X/ q.=.9.p.=.=.=.*.&.7.s.c.3.6.y.i.a.o.0.+.C.CX@XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#XmXVXBXW.L.L.^ 7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXAXhXsXdXeXwXsXqXqXsXxXxXxXuXpXkXeXO vXvXMXvXdXZXS.c.n.T.f.j.J.n.n.n.n.g.c.z.;.. k <.z.z.k.z.k.j.d.v.x.N.N.N.N.h.h.N.N.N.N.$.h.k.d.z.z.f.z.N.x.N.h.k.z.d.l.d.c.A w.| &.3.*.%.1.1.2.r.1.$.#.#.$.#.#.F 2.2.n.S.S.S.Y.K.Y.H.C.K.K.K.K.K.C.C.S.V.S.C.K.K.V.w.b.m.B.S.C.S.c.c.B.m.B.V.V.V.S.S.S.S.C.S.S.m.*.....2.4.1.M.B.5.t.5.t.t.t.E *.&.*.| 5.5.*.c.Y.DX+X+XBX`.s.s.8.8.i.p.a.a.*.4.r.u.E ..E ..&.p.6.=.8.i.p.8.&.7.7.7.3.t.4.r.%.X.#.t.i.q.q.9.8.8.8.i.8.8.9.=.Z.. SX#X#X#X#X#XVX@X. DXm.=.=.=.i.0.&.=.7.=.=.=.9.8.t...p.a.i.[ o.@.7.C.BXVX#X#X#X#X#X#X#X#X#X#X#X#X#X_.VX+XQ 6.a.y.6.` +XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXD dXqXwXwXeXeXwX4XuXfXzXzXzXpXkXjX. AX1X#XZXCXAXn.c.g.b.f.z.d.g.n.g.v.c.c.d.w.A #.j.k.j.z.z.k.G.f.z.N.N.$.x.g.g.x.,.N.h.N.h.L j.z.z.k.l.l.N.h.x.$.N.h.L h.$.1 . CX*.>.#.#.#.1.>.$.$.#.2.2.X.F 1.1.1.>.z.L.C.S.C.m.S.C.Y.C.C.C.K.L.K.H.V.V.B.V.S.T.T.B.S.b.T.V.Y.S.n.v.v.m.V.V.S.Y.C.Y.S.S.H.C.S.B.V.=.t.Y 2.t.O.<.m.K.r.4.5.3.5.3.*.&.&.7.7.&.+.U U *.V.DX+X`.8.8.8.=.8.7.6.5.2.r.u.........5.3.7.7.q.8.i.p.8.5.4.4.X.2.4.4.r.X.%.2.5.i.i.p.p.p.p.i.8.8.i.p.=.w.VX@X#X#X_.7XBXVX#XQ.b.s.7.=.T 8.9.q.9.=.=.&.l.c.9.*.k...y.6.@.i.p.8.+.Z.. BX+XBX7XVXAXSX#X#X#X#X#X#XAX+XR.a.-.-.a.6.s.SX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ aXgXsXeXeXwXsXqX4X0XpXpXpXkXeX_ #XZX~.@X).@X#Xe.v.c.n.f.z.d.J.c.c.v.v.f.f.v.d.d.z.k.j.k.x.x.k.x.x.L N.f.L.P.D.K.h.<.h.h.j.j.j.z.z.k.z.f.x.N.j.N.N.h.x.N.,.e.CX#XN.J <.$.$.#.$.<.<.#.%.%.2.2.1.#.<.>.B.L.C.C.L.b.c.S.Y.S.S.S.C.Y.V.B.m.V.S.S.K.b.v.B.B.V.V.S.H.g.v.v.d.b.H.S.S.C.K.K.S.S.H.Y.S.B.T.I...R M.4.t.{ 1.~ m.>.4.5.*.*.7.7.7.7.7.7.7.8.7.+.U *.b.m.8.8.8.7.7.*...5.3.&.&.*...*.*.u.*.+.S.s.7.i.p.7.4.1.#.2.%.X.2.2.t.3.t.*.p.9.p.p.0.a.i.8.6.p.i.8.5.( CX#XVX+XDXB.s.9.3.8.p.8.b.i.i.9.p.*...b.0.7.=.=.c.d.j...W -.9.0.8.8.q.Q.(.Q.!.`.#X7XVX_.#X#X#X#X#X7XL.6.a.-.6.-.-.@.L.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ dXzXfXfXxXxXqX0XkXpX0X0XkXeX_ _.#X#X#X+X. +Xe.c.q.n.J.d.J.d.J.f.v.v.J.d.J.v.g.f.l.k.N.x.z.G.h.x.h.g.! F.L.U.! I.,.$.x.k.Y j.z.k.k.z.f.z.N.N.$.N.N.x.N.<.XXDXN.J <.$.#.#.<.<.<.<.#.%.2.#.1.#.{ k.n.C.V.S.K.C.T.m.S.Y.Y.S.m.T.S.V.V.V.V.K.H.Y.K.b.T.V.S.S.Y.T.c.l.z.k.b.C.H.H.K.L.L.C.H.H.S.S.B.b.b.v.U ..R t.t.<.v.! r.4.2.2.5.3.&.7.7.7.8.i.8.8.7.7.7.+.&.i.8.8.=.7.&.*.&.i.9.p.=.*.u.4.r.t.*.s.T 7.i.p.&.2.#.1.R R r.4.&.8.8.7.8.0.p.p.0.a.0.7.6.i.i.i.8.5.b.. +X@X$X0.+.6.7.i.i.8.q.0.i.p.p.a.&.*.i.p.8.8.7.9.v.j.X.Y.-.s.-.8.i.8.&.q.T 7.T T ;.+XVX_.#X#XSXBX`.i.p.p.p.y.[ -.@.o.@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ hXuXfXfXxXfXuXkXzXpXpX0XpXfXD ).#X#XCX' ) I.G.J.g.v.G.d.l.f.z.J.c.f.f.d.d.l.f.v.J.x.G.J.j.h.l.d.x.V.! U.K.L.F.K.d.J.d.x.h.h.j.z.z.d.z.z.j.x.h.N.h.h.x.$.L <.^.<.N.$.,.,.<.,.<.$.#.1.r.2.#.$.c.K.S.B.S.K.S.V.S.S.S.C.H.m.w.V.B.H.C.H.V.S.S.H.K.b.T.S.Y.H.T.c.l.l.n.c.b.K.Y.C.K.K.C.V.w.S.S.B.m.b.b.w.d.O.R 4.5.t.2...*...%.2.r.R t.5.5.t.5.&.y.i.i.q.n.=.7.8.y.i.8.8.7.&.0.s.i.i.8.&...u.u...T &.&.8.p.y.1.>.1.2.u.4.4.-.-.8.8.8.a.0.i.p.a.s.8.O.*.8.8.7.=.&...Y.Y.0.9.9.i.i.p.p.a.8.&.7.p.i.a.p.t.3.7.p.p.8.8.8.&.z.j.3.y.i.p.p.p.p.6.0.-.8.7.l.*.Z.7X#X#X#XAX+XC.p.a.a.p.i.-.a.6.-.#XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ jXuXeXfXzXqXzXnXnXzXpXpXpXuX1X_ #XCX/.z.N.x.G.k.J.G.k.d.f.v.z.G.z.J.f.f.d.d.f.c.z.G.j.x.h.g.K.C.m.S.L.L.K.L.L.U.C.S.C.v.h.h.h.k.z.k.k.j.k.k.k.k.k.G.d.N.^.J ,.<.<.<.$.$.,.<.$.$.#.#.#.X.h.z.V.S.B.V.K.F.S.V.V.S.K.C.H.T.b.V.m.S.C.L.V.H.S.S.K.V.V.B.T.n.v.l.v.B.C.S.S.K.K.C.K.Y.b.T.n.n.m.m.b.b.n.b.c.4.l.n.w.b...{ u.u.E E R 4.r.4.5.4.4.O.5.7.=.v.f.l.7.8.7.p.p.i.i.8.i.p.i.7.*.=.=.=...q.H.&.7.i.p.t.<.>.#.1.2.#.t.-.0.7.7.8.-.-.i.p.s.9.&.5.4.5.7.*.&.=.5.O...&.8.9.i.8.i.p.a.&.*.7.i.i.p.5.2...*.8.i.i.y.6.5.4.l.p.y.p.p.y.p.p.i.6.@.8.c.q.q.q.`.7X_.7X. !.i.9.i.i.i.8.7.i.y.-.VXVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ 1XqXuXnXkXzXnXnXxXxXuX0X0XkXrX. . SXz.j.z.k.k.G.J.k.k.d.f.v.G.x.h.x.k.J.c.v.J.G.j.L N.$.J.U.C.C.K.K.C.K.K.L.U.L.C.B.C.C.d.h.N.x.k.j.x.j.k.k.k.k.k.k.z.z.x.$.<.J ,.,.<.$.<.<.<.<.<.<.^.j.z.k.b.V.B.Y.C.S.H.Y.C.K.K.K.V.V.U.w.n.m.S.K.S.S.S.S.K.C.S.g.d.d.d.l.Y.L.B.S.C.C.C.H.C.K.V.B.S.m.n.n.b.n.n.v.c.g.b.w.m.S.c.:.r.t.u.t.4.4.r.%.O.t.E &.&.l.l.d.v.v.*.7.u.*.i.y.i.8.i.i.&.&.q.9.i.i.&...&.=.8.a.5.J #.#.<.$.<.<.5.i.7.=.&.8.p.0.p.p.0.i.=.9.7.4.5.+.*.&.5.t.l.l.T i.i.8.i.7.3.*.*.7.8.i.8.} l.T 4...&.6.i.3.E ..&.p.p.p.p.p.p.p.p.9.i.c.q.i.p.i.W.CX+XSXA.i.7.i.i.8.=.8.8.i.6.-.7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmX_ yXzXkXxXuXnXnXnXnXxXpX0XkXiXCX) f.z.f.f.k.j.d.J.z.z.f.f.v.G.x.x.h.x.j.J.I.d.N.N.$.N.N.g.L.C.V.B.C.C.C.C.K.L.K.V.V.V.V.b.c.k.x.k.k.x.k.k.k.k.k.z.z.k.z.l.d.k.x.h.h.N.$.#.N.h.N.h.j.j.d.J.d.T.V.m.S.Y.K.C.C.K.K.L.C.T.C.Y.v.v.n.T.V.S.Y.B.S.K.S.c.d.d.l.l.n.K.C.m.m.C.K.H.H.C.K.S.V.S.C.n.c.b.n.c.v.v.c.n.n.g.e.n.r.u.t.t.u.4.4.2.2.5.=.s.p.0.9.t.u.f.v...n.c.O.*.*.*.8.p.i.7.=.s.0.8.8.=.*.&.8.i.a.1.,.$.<.<.$.#.$.u.y.8.8.7.7.i.y.p.p.p.i.=.i.9.5.t.&.3.3.u.t.*.&.*.=.8.i.7.t.r.5.&.7.8.8.7.r.H.q.4.5.3.i.i.=.=.9.9.q.i.8.6.8.6.s.s.p.9.p.9.i.i.6.B.BX' T +.8.i.i.i.i.i.i.9.0.@.H.7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ % xXzXxXuXnXnXnXxXzX0X4XS v.G.d.f.v.J.j.z.f.f.J.d.l.f.f.j.x.h.h.h.x.x.k.j.N.$.j.T.Y.K.H.V.T.g.n.K.C.H.K.K.K.Q K.V.V.H.K.H.j.h.x.j.j.k.j.k.k.k.z.d.d.z.z.d.l.d.z.z.j.x.j.G.d.d.l.v.v.c.c.w.B.m.T.L.L.S.C.K.U.K.l.l.l.d.v.c.n.n.T.m.B.B.S.K.B.l.d.l.f.v.T.H.B.V.m.m.H.C.H.C.C.H.S.S.C.T.v.n.n.c.c.v.l.c.b.n.n.v.e.).w.:.5.5.O.v.w.&.8.W s.7.=.%...9.q.=.v.u.4.*.5...7.i.i.8.i.i.8.8.8.8.7.&.8.p.*.1.2.>.<.<.<.#.#.1.7.p.8.8.7.i.p.i.p.p.i.i.i.i.5.t.*.3.5.t.r.&.7.&.*.7.i.7.4.4.5.5.&.7.8.5...q.R E *.o.-.i.9.i.q.q.q.q.&.*.7.8.s.s.i.a.p.a.9.p.a.=.v.&.7.i.i.p.p.i.p.p.p.i.i.0.SX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ Z xXnXfXxXnXnXnXxXuX4X{.E f.f.J.z.d.z.J.f.v.c.v.J.f.f.k.k.x.N.N.h.x.j.j.h.J.K.P.F.Y.B.V.m.f.w.C.S.H.C.K.K.L.K.C.C.C.C.L.v.<.N.N.$.h.x.h.h.j.k.z.d.d.z.d.z.z.z.k.j.h.x.k.d.V.m.J.v.n.v.I.m.T.S.U.w.T.B.Y.L.c.d.c.n.n.c.v.c.c.B.B.w.V.C.K.T.c.z.d.l.d.d.S.S.S.B.b.m.C.C.H.C.S.S.K.K.l.z.f.v.c.g.n.n.n.b.b.c.n.AX. w.:.3.3.5.=.9.7.3.B.S.3.*.=.9.a.p.i.l.2.r.....*.&.7.8.&.7.i.i.8.8.8.i.&.7.*.#.2.#.<.<.>.#.#.1.F 2.8.y.i.8.8.p.p.i.i.i.9.p.8.%.%.5.5.5...E 5.7.=.*.7.8.&.%.4.5.u.&.7.7.r.u.u.E 5.8.s.0.p.i.=.&.7.8.i.=.c.9.9.9.i.p.a.a.a.p.i.a.&.O.&.8.i.p.a.p.a.p.p.p.y.8.^ +X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XCXFXvXzXnXnXnXnXxXxX0X4XnX*.J.J.J.f.g.f.f.g.n.c.f.f.f.j.j.k.j.h.h.h.j.h.z.L.F.C.S.S.H.H.n.f.B.S.B.S.C.K.K.C.K.K.K.K.K.C.w.g.I.v.f.n.I.g.j.N.x.j.k.z.k.d.z.k.k.k.j.x.j.z.n.C.C.n.n.T.f.l.T.m.Y.P.C.b.b.n.n.n.S.C.C.V.c.v.c.n.S.V.m.S.K.Y.T.J.j.k.z.h.j.S.K.C.C.Y.S.S.C.C.C.C.K.K.n.k.d.l.v.v.c.n.n.b.w.w.q.n.#X. Y.:.3...*.3.7.8.&.&.0.*.=.9.q.8.p.a.&.1.2.*.5.u.*.7.*...*.8.i.i.i.8.i.8.&.3.1.<.<.<.$.$.$.2.#.%.$.<.t.&.i.7.i.p.i.p.p.p.a...%.E E E *.&.=.&.7.7.3.5.8.7.t.%.t...&.7.7.t.%.u.E u.8.8.y.p.i.8.q.*.=.n.9.0.9.i.0.0.p.a.p.p.i.i.i.3.+.=.8.8.7.8.7.&.p.a.p.6.C.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXCXhXkXxXMXnXnXnXnXfX0X4X[.d.J.g.g.g.c.c.g.c.v.f.v.v.x.h.j.k.G.x.h.h.h.g.L.S.V.S.C.Y.V.c.I.K.K.V.H.C.K.K.K.L.L.L.L.K.B.T.K.S.S.S.V.B.V.V.d.h.N.N.x.x.j.z.z.k.k.x.j.j.f.B.b.g.T.T.V.n.z.I.S.V.S.C.B.w.n.c.K.L.H.S.T.T.B.m.b.w.m.V.H.K.b.z.z.j.X.X.x.c.n.b.S.S.H.S.S.C.K.C.K.K.v.M.d.l.l.v.c.c.c.n.c.n.w.b.d.e.. +Xl.| 3.3.*.&.8.7.5.q.=.*.n.9.8.i.a.8.1.1.u.5.u...5.t.5.*.7.i.p.p.8.8.8.&.7.r.<.#.<.$.$.J #.1.2.X.$.1.2.5.6.i.y.p.p.a.7.4.2.R E E E *.*.&.=.7.7.3.4.*.i.3.2.t.*.&.7.8.t.%.u.u.t.7.8.i.i.8.3.=.=.9.9.9.i.9.0.a.a.8.&.7.7.=.=.=.=.7.7.&.5.4.5.t.4.8.a.6.i.@X+X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XD D gXzXzXMXnXnXnXxXuX0XfX=.v.c.c.v.g.v.v.g.c.v.g.l.x.x.h.x.j.z.G.j.h.c.C.B.S.K.H.V.S.S.C.L.C.H.C.C.K.K.K.K.K.K.K.S.w.B.S.V.V.S.V.T.b.V.n.h.N.h.k.x.h.j.z.x.N.h.N.<.N.m.H.V.V.S.H.J.j.n.B.V.B.m.V.B.T.V.C.C.S.b.B.C.Y.S.T.b.V.H.L.V.x.#.k.j.h.X.d.f.d.z.k.l.v.T.S.S.C.C.C.c.M.d.d.d.l.v.c.q.n.n.c.c.b.b.c.z.e.. B.:.*.&.&.3.5.5.O.b.B.3.9.T 8.7.y.i.M.2.4.u.4.E 4.4...*.&.8.&.8.y.8.8.7.7.4.>.#.#.<.,.,.,.$.#.F %.t.%.%.3.7.8.i.p.*.>.#.2.%.4.4.u.*.&.&.&.&.7.3.u...*.u.r.u.*.5.5.4.r.u...4.5.&.&.8.i.8.5.&.9.i.8.p.p.p.a.a.p.&...*.&.&.&.&.=.T 8.*.%.Y *.*.=.u.U 3.t.A CXVX#XVXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XCXO zXfXnXMXnXnXnXfX0X4X.#.1.<.,.<.#.2.X.2.d.4.u.t.5.3.7.8.1.$.2.2.r.r.4.t.*.&.*.&.*.&.*.......u.%.u.3.5.2.#.r.u...t.5.&.&.8.i.7.*.8.-.i.8.i.9.a.a.p.=.*.*.*.=.=.8.8.=.=.=.q.=.E ..=.8.5.2.t.:.O.OX. +XVX@XBXVXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX_ gXkXxXnXMXnXnXxXxX0X4Xw.T f.J.l.c.v.f.f.c.f.j.N.N.h.x.j.x.x.z.z.v.U.K.V.V.K.K.S.S.S.C.C.C.C.C.K.m.c.n.B.S.H.Y.S.v.l.n.B.S.B.n.v.g.b.z.x.j.z.d.k.k.x.h.j.x.$.$.x.h.k.z.k.h.h.j.T.T.g.n.V.K.L.K.K.C.S.C.S.S.H.V.S.S.S.S.B.B.B.k.j.G.k.h.X.j.z.f.d.d.k.d.v.v.c.n.n.b.S.f.X.k.z.z.d.d.l.v.c.n.c.v.v.n.n.l.M.I.DXt.-.s.5.5.u.*.*.t...8.8.s.i.8.&.3.3.8.&.2.%.2.%.4.*.=.7.p.5.<.O.3.&.3.3.u.#.1.r.4.4.#.<.1.R %.>.1.t.t.t.5.*.8.M.F X.2.2.r.%.4.5.*.*.&.&.5...*.*...*.u.4.3...*.4.2.4.u.5.5...*.&.=.7.8.&.8.p.9.8.8.9.7.*.5.......*.&.=.8.8.8.i.7.7.9.=.*.7.8.5.E *.*.5.*.GX!.b.B./ 7X+XmX_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ O zXzXxXnXnXnXzXxXfX0XsXT c.v.J.f.v.c.f.f.g.b.k.h.x.x.k.d.J.d.d.e.L.Y.S.H.C.Y.H.C.C.C.K.K.H.m.n.g.m.S.K.K.C.C.K.C.n.v.T.V.b.c.c.n.T.l.j.k.Y j.k.z.j.k.z.k.j.j.j.z.d.f.z.k.z.c.K.m.n.T.T.T.T.S.S.B.Y.C.S.S.C.C.H.H.S.S.S.B.B.g.j.j.j.x.h.X.h.l.z.z.d.d.v.v.c.n.T.S.n.x.j.M.k.z.z.d.d.l.v.v.c.v.j.d.n.v.Y w.CXc.t.&.*...5.3.&.t.u.=.8.0.8.8.7.7.7.i.8.2.r.4.4...&.7.y.8.<.$.4.4.5.3.5.2.1.2.4.Y %.4.r.2.%.M.u.3.&.5.4.3.&.u.F F X.X.1.2.r.%.t.3.3.&.&.5.E ..*...5.t.t.5.3.5.2.1.4.5.3.*...5.5.&.=.8.&.7.i.8.8.=.i.5.2.4.u.u.u.....&.8.8.7.7.0.8.i.q.5.7.+.u.5.&.&.&.*.&.v.&.8.=.m.` 7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).D gXzXfXzXvXnXnXzXxXuX0X.J $.F #.1.t.4.r.4.R R M.5.7.7.*.4.*.i.8.7.8.u.1.X.F X.%.X.#.2.t.4.R u.3.*.&.5.4.5.5...5.u.r.4.u.t.u.r.r.4.5.*.M.M.5.5.7.7.8.&.&.i.7.8.8.=.=.*...*.d.u.4.t.3.y.p.@.=.s.=.i.8.5.5.4.4.*.7.7.7.=.=.=.=.=.6.+.9.VXVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ jXzXfXsXnXnXxXnXxXxX0XqXg.c.g.g.f.z.l.v.v.f.f.d.z.z.z.l.V.U.L.V.H.S.K.S.T.S.K.K.K.C.m.b.B.b.n.m.H.C.K.L.K.K.K.H.S.S.b.c.l.l.c.T.n.d.k.k.b.S.H.C.L.n.x.z.%.m.L.f.n.T.V.V.n.g.b.T.V.V.T.g.v.v.v.z.n.H.T.n.n.B.Y.K.K.C.S.H.S.S.c.x.M.k.v.f.k.j.l.v.T.H.V.S.S.c.M.z.z.j.h.x.x.k.d.l.l.l.l.f.z.k.M.k.f.g.l.{ /._.O.9.=.u.*.t.*.9.0.p.7.8.i.i.8.i.i.y.7.2.2.4.3.&.7.&.O.4.r.#.2.4.4.4.2.2.t.%.%.*.8.=.=.*...7.=.7.7.9.i.1.2.%.h.X.1.#.1.2.2.r.4.4.u.t.2.r.3.*.7.7.*.u.%.4.4.4.4.r.%.t.t.c.v.O.u.&.7.8.7.5.7.8.=.7.8.=.*...=.8.8...t.*.8.8.3.s.-.3.9.i.t.r.r.t.+.7.7.8.=.7.T =.&.i.y.7.P +X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).D gXzXfXxXkXnXnXnXxXuX0XxX=.l.g.g.f.d.d.l.l.z.d.z.z.j.I.D.L.S.V.K.K.K.C.B.V.K.K.b.c.v.z.c.b.V.L.C.C.K.L.L.K.C.C.S.B.T.m.c.k.v.B.d.z.v.B.Y.V.V.S.S.C.f.X.v.P.I.c.B.K.K.Y.S.T.g.n.T.m.n.I.f.J.c.l.k.n.T.c.c.b.S.V.v.S.C.S.B.T.n.k.v.S.n.v.B.V.n.b.F.S.m.m.H.V.z.v.n.v.j.j.k.j.h.x.x.j.z.z.d.z.k.z.c.l.} } GXCX=.:.4.3.&.*.i.s.p.8.8.8.8.3...7.*...5.r.2.#.2.*.5.4.0.a.p.7.&.&.7.&.r.2.3.R R *.&.&.7.&.*.&.=.&.&.8.7.u.5.3.r.#.#.X.F <.#.1.X.#.>.1.r.R 8.p.6.8.*.5...5.4.r.4.2.2.4...s.&.r.t.*.7.&.3.5.4.8.i.8.8.7.5.9.s.7.9.i.u.u.5.5.5.9.q.&.p.8.1.1.r.r.%.*.@.7.8.i.T q.=.7.i.+.B.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X_ hXzXsXsXnXkXnXxXnXxX0X4Xg.&.v.n.c.J.d.d.d.z.z.z.z.k.I.F.K.S.V.K.L.K.L.S.T.V.V.B.T.B.c.c.B.K.L.H.H.Y.H.Y.S.S.V.V.B.m.T.b.f.l.I.f.d.b.b.n.T.B.m.T.B.n.k.V.V.c.n.V.S.V.B.B.V.n.T.Y.V.I.c.J.d.c.v.z.d.c.n.b.m.H.V.h.l.b.b.b.b.n.v.c.P.V.n.V.B.b.T.C.V.B.m.V.S.n.c.b.T.c.k.j.N.N.N.h.h.j.X.x.k.d.c.l.r.{ d.7X. V.} 5.u.3.8.6.0.K.s.8.i.=.&.&.&.5.t.t.4.$.<.$.2.2.7.[ s.i.i.8.=.&...t.&.p.p.8.&.&.&.=.=.7.7.7.7.&.=.*.u.3.&.*.2.1.1.<.$.%.%.R #.#.4.u.E r.q.9.3.3.3.*.u.u.u.%.1.M.l...5.t.r.u.*.&.*.r.t.r.3.8.6.i.7.3.8.q.7.i.8...O.4.r.t.&.&.=.p.*.#.r.2.$.>.2.5.&.8.i.i.i.q.8.8.@.9.#XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ aXzXfXsXsXzXlXnXxXxXfX0XfXq.q.g.v.f.z.z.d.z.G.d.z.k.B.L.C.C.K.C.K.K.L.L.V.b.m.S.S.B.n.n.V.L.C.C.S.S.S.S.B.B.m.w.m.m.b.T.n.n.T.e.b.b.I.b.n.n.n.n.b.g.e.U.v.Y.V.B.S.m.T.T.T.V.S.S.Y.K.T.z.z.v.c.l.z.d.b.B.B.Y.H.l.d.v.v.g.b.c.c.g.n.b.m.T.m.B.T.m.S.V.B.m.B.B.g.c.n.T.n.X.h.N.N.h.X.k.X.h.d.v.v.c.%.,.g.. . C.:.5.u.4.&.p.8.0.s.i.i.8.8.8.=.7.*.5.5.1.#.4.1.r.i.y.i.i.i.i.8.&...q.8.s.9.8.8.7.=.8.8.i.8.=.8.7.=.=.&.*.*.7.E H #.<.$.1.2.%.1.4.t.E E 2.h.M.2.%.u.r.1.1.%.%.2...z.u...M.r.4...&.5.2.%.t.5.5.&.8.8.7.&.7.8.i.&...=.&.u...&.&.=.i.4.2.4.r.2.2.r.1.r.*.7.i.i.9.9.9.8.7.W.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).#XgXzXsXsXxXlXkXxXnXxXzX0XxX9.v.g.n.d.z.d.d.d.f.z.c.C.C.K.K.S.S.C.K.L.L.K.T.m.V.S.V.b.T.m.C.L.C.S.S.C.H.S.S.B.m.m.m.m.b.b.V.S.B.Y.C.S.S.B.n.c.n.g.c.P.Y.n.C.S.V.V.I.b.w.T.T.B.V.V.K.L.c.z.z.c.l.M.l.n.B.V.C.Y.k.X.z.z.l.c.J.n.T.b.T.m.m.m.B.V.H.S.S.V.B.m.m.m.b.n.b.B.l.h.h.N.N.h.k.h.j.v.l.l.f.M.z.(.. . V.:.t.t.t.&.p.a.p.i.p.i.i.8.8.7.=.&.*.*.3.%.2.r.4.8.p.i.i.p.i.=.*...v.7.8.8.8.8.8.8.8.i.7.3.8.8.=.&.&.=.&.*.&.q.E <.<.1.1.X.1.2.t.u.E 4.u.4.2.1.#.1.$.#.2.2.#.1.z.Y *.*...t.2.M...5.1.2.u.t.u.*.5.&.&.7.8.8.8.5.q.0.8.=...*.*.T 8.1.1.4.u.5.3...*.E 4.7.i.i.p.9.s.8.8.`.7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX_ jXuXfXsXwXfXkXkXnXxXxXuX0X.2.2.2.2.2.M.%.4.r.u.l.l.u.u.5.u.2.1.t.4.4.u.%.4.&.&.&.*.*.7.7.8.8.7.8.=.8.p.4.#.$.1.&.8.7.&.&.*...*.i.s.-.i.0.9.B.VXVX_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX_ dXzXsXsX4XeX_ nXzXnXzXpX0X.2.X.<.>.4.8.8.7.=.7.&.t.7.p.i.p.i.8.C.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).D sXzXfXsX4X2XCXgXkXnXuXpX0X.#.4.&.8.&.&.&.*.7.&.3.E 4.E *.&.&.&.8.=.*.5.R u...*...*.E 4.%.4.1.<.2.u.r.#.1.R r.2.<.$.#.2.2.1.u.5.3.u.u.*.*.*.u.2.#.2.2.%.%.F #.2.u.E ..*.5.*.i.7.8.i.E >.%.#.>.#.1.r.7.6.7.7.7.*.7.p.p.p.p.i.b.` 7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ jXzXfXsXqX4X_ O lXxXnXfXpXsXG n.n.n.n.m.B.d.I.K.K.H.V.B.S.V.V.V.n.n.V.S.V.c.b.L.C.C.K.L.C.m.n.n.n.c.v.l.n.n.b.T.w.m.B.B.n.c.c.v.v.d.l.f.c.b.m.m.T.n.v.J.v.n.T.T.e.B.V.V.S.C.H.V.n.n.T.g.g.J.j.j.d.v.C.L.K.C.C.H.S.B.B.m.m.V.V.m.w.b.b.B.m.b.c.v.c.b.m.B.m.c.d.l.c.c.v.f.d.d.l.f.z.k.v.v.f.v.R O.=.Y.+X. W.&.7.8.i.8.8.&.&.....E E E E R 4.t.*.5.4.#.,.<.>.u.&.*...&.&.3.t.4.t.3.=.=.&.*.&.&.&.*.E t.t.3.&.7.*.t.t.......E E ..*.5.r.4.%.1.<.<.#.1.1.2.%.r.r.$.#.#.%.#.1.%.X.u.*.R E ..*.*.5.1.r.2.#.X.2.M.T ..E *.=.t.O.8.8.7.8.5.$.X.1.<.$.1.r.r.*.i.8.7.7.8.6.i.p.i.p.T !.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).).gXzXsXqX4XeX_ gXkXxXzXpXfXs.c.g.c.g.b.S.S.V.S.V.V.Y.K.L.K.S.Y.Y.B.V.T.l.z.C.P.H.K.S.V.m.b.T.m.B.T.n.l.f.n.c.c.b.V.m.B.V.b.n.c.v.f.d.d.l.c.T.B.w.c.c.g.b.b.I.n.V.C.C.S.H.S.B.B.m.m.b.b.T.T.z.z.l.f.T.K.L.L.K.C.C.K.K.K.C.S.V.B.m.m.m.m.w.b.n.c.n.c.v.c.n.c.v.v.c.c.f.d.l.f.v.l.k.z.v.v.c.z.2.2.l.I.Y.Z.&.+.8.8.8.p...1.r.4.........t.4.5.u.4.u.t.1.$.<.$.u.*...&.=.*.&.&.3.u.t.5.&.&.&.&.*.*.=...2.%.4.*...O.....E E ....E ....4.1.1.R %.#.<.,.$.r.4.r.r.2.h.>.#.%.M.E *.l.=.&.5.4.E *.&.5.2.4.4.#.#.2.l.q.E 5.7.7.r.%.3.7.8.7.2.>.2.X.<.<.2.O.l.4.O.7.8.8.7.8.i.i.i.6.s.mXVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ hXpXfXsXqX0X}.DXlXxXzXuX0XgXT c.c.m.K.K.K.V.S.S.S.C.K.K.L.C.K.L.Y.H.T.z.c.K.C.C.H.m.m.B.B.V.S.S.B.T.d.l.n.n.c.w.B.B.m.m.m.b.b.n.c.c.l.f.c.b.T.g.v.c.v.n.V.b.I.H.H.S.K.C.S.V.m.m.B.m.T.b.T.B.c.J.c.c.g.v.n.n.n.V.I.g.g.g.b.B.V.S.V.B.m.b.b.b.b.v.z.z.c.v.d.c.n.c.c.v.v.v.c.v.k.x.f.c.c.M.#.%.%.t.I I O.3.8.=.&.&.*.4.1.1.%.%.E *...t.*...2.2.u.r.#.X.F 1.4.&.*.E ..&.*.*...E ..E E ..5.t.t.*.&.2.2.t.u.*.1.1.*.3.4...*.R 4.%.2.2.#.1.%.X.1.#.$.<.2.r.1.X.j.#.<.%.d.E t.5.3.*.*.&.5.R R E u.r.4.u.r.1.2.R u...&.&.4.2.R t.5.&.u.1.#.2.X.$.#.t.5.9.E 1.5.6.8.8.6.y.p.p.i.Z.7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XD $XgXfXsXsX0XeXD zXnXxXzXpXeXC l.b.L.F.C.S.T.B.Y.S.S.H.C.L.L.L.g.v.V.B.n.S.L.H.C.V.m.B.S.S.C.S.S.H.T.z.l.c.q.q.b.V.V.B.m.m.b.b.T.n.n.n.v.c.b.n.v.v.c.c.n.S.S.B.Y.S.S.C.C.C.S.B.V.V.B.w.b.b.m.T.c.g.n.b.v.z.v.g.T.v.k.k.M.f.n.n.T.B.B.T.n.n.b.n.z.d.v.n.k.N.k.g.n.c.n.d.k.k.j.x.k.v.v.M.1.%.E %.r.u.U t.&.&.*.&.*.5.t.4.%.H %.X.u.5.5...R X.%.u.2.$.F $.<.<.%.*.&.&.*.*.*.....E E E E 4.%.t.=.E 1.4.4.*.M.<.$.2.E E *.4.$.>.>.#.2.2.%.R 2.1.#.#.#.#.1.x.X.h.$.1.E 4.O.t.5.3.*.&.&.=.*...4.4.$.<.2.t.2.r.u.5.&.5.>.$.X.2.4.t.t.1.1.%.%.1.#.2.4.t.....E ..&.&.@.8.0.p.i.S.CX@X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ hXpXsXsXqX0XtXdXkXxXzXpXqX7XC.w.K.C.K.S.w.B.Y.C.V.S.C.K.U.V.h.d.n.b.S.C.F.K.S.V.B.B.S.H.H.H.K.C.v...l.v.g.n.b.m.S.B.m.w.b.b.n.n.c.v.v.g.T.g.v.c.g.c.c.T.g.n.L.K.C.C.K.K.K.C.S.S.B.m.w.b.b.T.n.n.I.T.T.v.n.b.n.b.b.b.b.b.n.v.v.g.n.n.g.n.T.g.d.v.v.c.z.h.h.x.d.f.d.j.k.X.x.k.z.z.2.2.r.%.R R 1.r.5.4.5.7.=.&.&.&...E R R %.%.r.2.4.M.%.2.%.4.$.J ,.,.<.,.J #.4.%.*.&...u.u.u.R u.t.t.5.&.&...4.4...u.#.$.$.<.$.X.1.$.>.<.#.4.r.%.R 4.1.1.1.1.1.>.#.1.<.$.>.2.r.r.u.5.3.*.7.&.&.&.7.7.*...u.<.J r.u.4.4.5.5.#.,.>.F #.1.r.2.2.2.2.Y M.1.1.2.2.1.4.....3.*.7.9.=.....&.Z.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ 1XxXzXsXsX3X0XxXnXnXzXpXpXeX. S.S.C.K.S.b.b.B.V.V.V.H.K.Y.b.j.k.c.T.S.C.C.H.H.S.V.S.H.Y.S.K.K.c.z.l.l.l.v.c.c.n.m.B.m.m.m.f.k.z.z.k.J.b.T.n.v.n.n.c.c.v.k.c.C.L.U.L.L.K.L.K.C.H.S.B.w.b.n.b.T.g.T.T.f.l.n.n.n.n.b.w.b.n.n.q.v.v.c.c.c.n.b.n.l.d.f.c.d.k.j.h.N.x.j.z.k.j.j.z.k.{ 2.2.1.1.2.%.Y 1.O.5.d.u.&.8.7.&.*.E u.R 4.u.%.F %.R %.%.4.2.<.#.#.1.1.r.2.#.,.J >.%.5.5.t.4.t.t.u.5.....2.4.4.R M.1.#.$.1.<.<.1.$.>.$.$.2.4.4.%.r.r.r.2.1.1.#.$.1.#.>.$.1.r.2.2.u...*.&.8.=.7.&.&.&.&.*.&.t.#.$.r.r.r.%.1.<.1.&.8.&.4.4.4.4.4.r.R H 2.2.r.%.1.1.4.t.5.*.=.=.E E ..5.3.!.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ iXzXfXsXsX4X4XzXnXnXuXpXqX^ H.C.K.L.S.g.c.c.b.V.S.S.K.B.n.g.l.f.b.V.H.C.C.H.H.S.H.C.C.K.K.l.%.z.d.l.v.l.v.c.v.c.T.m.c.z.k.k.z.d.z.k.l.g.n.n.n.g.c.c.c.f.d.T.B.m.T.m.S.S.B.V.V.T.b.n.n.n.T.b.c.c.J.h.k.n.c.q.c.q.n.n.n.q.c.c.c.c.c.n.b.b.c.v.v.c.k.x.k.j.j.x.X.k.z.z.k.j.z.j.2.r.2.1.1.2.R E %.r.*.z.1.R ..*.*...E R 4.4.%.X.M.R R R u.R 4.t.5.t.t.u.t.5.t.2.#.,.,.1.2.%.4.r.2.r.%.F #.1.1.$.X.1.#.#.>.<.,.,.<.$.$.<.1.u.%.2.>.#.2.2.2.2.1.$.<.1.2.#.#.1.1.#.#.%.E U 3.5.*.K &.*.&.&.*.*...3.2.$.#.1.%.X.%.i.[ s.i.i.=...t.r.2.%.X.4.*.*.5.4.4.5.5.5.&.T d.E ..*.&.| S.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmXD D gXuXxXsXsX4XqXnXxXzXpXxXo.C.K.U.L.n.d.l.n.n.B.B.V.C.S.v.T.V.b.T.V.B.C.K.H.C.S.H.C.K.L.S.M.X.z.k.d.d.z.d.c.n.c.v.d.x.h.M.d.l.l.d.k.k.z.J.v.n.n.c.v.c.c.k.d.f.d.c.n.c.v.l.v.f.d.l.v.c.n.b.n.v.z.$.N.x.c.b.n.n.n.n.n.q.g.c.c.n.n.b.b.c.z.z.z.z.h.N.x.k.j.M.X.h.k.z.z.k.k.z.j.2.2.1.#.2.2.%.E r.%.2.2.R 4.2.2.r.*.5.t.4.t.2.X.R R R R u.t.5.5.4.4.4.R E 4.4.t.5.4.$.,.<.2.2.1.2.2.1.#.1.2.1.#.X.1.#.<.$.d.z.#.,.<.<.$.%.u.M.<.<.<.$.<.<.$.$.<.<.$.2.2.#.2.2.1.1.#.1.%.X.4.#.r.7.7.=.&.*.*.....u.#.#.2.%.X.7.y.i.9.8.i.8...t.R 4.O.R *.*.....E E *.&.*.d.Y E ..*.&.7.+.C.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ iXzXfXsXsX3X4XqXnXzXuXS.[ K.L.F.w.M.v.K.B.c.T.m.S.K.S.k.z.T.Y.K.K.S.K.L.L.K.C.C.K.C.B.B.l.M.Y z.Y k.k.z.l.l.k.j.Y z.j.j.d.d.d.d.z.j.k.k.j.d.n.n.c.c.c.z.z.l.f.g.b.n.c.c.c.c.l.l.v.g.n.n.c.g.z.$.N.X.l.g.n.n.c.b.b.c.n.n.n.c.f.l.k.j.x.j.x.h.N.N.X.j.k.x.x.X.x.d.z.j.k.k.%.r.2.#.$.2.r.R Y %.2.2.R E R %.1.2.&.8.7.7.*.t.%.%.Y R u.E *.*.5.R Y E E R 4.%.R 4.5.4.,.<.4.4.2.%.%.2.2.4.r.2.X.%.N.<.,.A CXVX$Xe.$.#.r.4.t.4.<.<.<.<.<.<.$.$.$.#.$.$.#.1.R %.%.R X.1.4.R 4.O.1.t.7.7.=.&.....E 4.#.1.2.2.1.&.i.i.8.8.8.8.*.u.R =.o.i.8.=.*.E u.E ..*.=.d.4.....&.7.7.U L.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX_ jXuXsXsXqX4X4XfXzX;X[ C.K.F.L.l.d.F.! S.n.m.m.S.L.S.v.d.l.B.L.w.z.b.V.H.C.L.K.C.V.B.V.f.k.Y z.z.z.d.d.k.j.j.j.z.k.k.j.d.l.l.d.k.k.M.j.j.k.f.g.c.v.I.J.z.c.c.c.b.b.n.c.c.c.c.c.c.n.T.c.v.n.z.N.X.k.M.j.k.j.x.z.c.n.c.z.k.k.X.j.x.h.X.j.j.k.j.h.h.j.Y h.X.x.x.d.z.j.k.k.%.2.#.1.4.%.%.%.4.4.2.R E R %.1.1.#...8.=.&.&.&.5.%.%.Y E ....E *.R %.R %.r.1.X.4.u.E 5.$.<.t.R 4.R 4.2.4.4.R %.%.F #.J f.. @X@X. AX2.} u.r.4.#.<.$.<.<.<.$.X.$.$.#.$.,.1.4.4.R E R 4.4.R ..E u.5.r.4.5.....*.*...t.1.1.4.r.1.*.y.i.i.8.8.i.&.u.%.&.s.i.7.=.=.&.5.u.&.*.*.&...*...&.+.3.B.VXVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.mX_ ).xXzXsXsX3X4X4XxXH.S.B.K.L.H.v.U.L.n.m.b.m.B.H.L.S.T.n.z.l.H.d.h.X.h.j.f.V.S.m.T.m.m.d.Y z.d.z.d.d.z.z.k.z.k.j.j.j.z.z.l.f.d.k.k.j.k.k.j.z.v.f.c.g.z.v.b.T.B.B.b.n.n.n.n.n.n.c.T.g.d.f.g.z.X.k.x.x.h.$.<.$.X.x.j.h.$.j.k.j.z.k.j.j.j.k.k.j.x.h.j.k.X.h.X.j.z.k.j.k.z.%.1.r.t.t.%.2.r.2.%.%.E E R 1.#.#.1.M.&.7.*.&.*.5.5.u.u.E E u.4.R 4.2.1.2.2.2.2.2.%.E 4.2.#.4.E E E u.4.4.%.R %.1.#.,.h.BX+X#X#X+X' 1.r.4.4.1.<.<.$.#.#.#.1.$.<.$.$.<.1.5.t.E E R 4.R u.E u.R R R R R r.2.2.%.R E u.2.2.2.2.2.%.8.y.y.8.8.8.&.u.4...7.8.=.7.7.=.=.3.&.&.&.=.c.=.*.=.q.C.VX7X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ iXuXfXsXsX3X4XgXo.V.K.B.b.n.B.L.m.c.c.w.m.B.Y.K.C.B.T.l.M.z.j.x.h.<.h.l.l.b.b.b.S.b.j.z.z.z.z.z.d.d.d.l.d.z.k.j.x.X.h.j.d.l.z.k.k.k.j.k.j.k.J.c.f.f.c.b.V.V.c.l.l.z.l.n.b.b.T.n.d.d.v.c.j.h.N.$.h.x.h.h.N.$.$.$.N.N.k.z.k.z.l.d.j.j.k.k.k.j.x.k.Y x.1.h.X.X.X.j.J.z.O.4.t.t.u.%.r.R r.r.R R R %.1.1.%.H %.%.u.5.3.5.5.*.&.5.2.2.r.4.4.%.1.2.X.1.#.#.1.1.%.%.2.2.4.5...E ..R O.4.R X.1.,.1.`.. _.#X#XBXDXM.%.X.2.1.<.$.#.F X.1.$.$.#.$.<.$.4.t.E E u.R E 2.2.4.4.O.2.2.4.E E X.1.1.r.E E *.5.$.#.2.F %.%.5.8.i.8.=.*.u...=.8.7.7.&.=.=.&.&.&.&.&.l.q.P ` VX+XVX_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX_ hXzXsXsXsX4XwXo.S.K.B.w.C.L.V.m.b.V.w.m.S.C.K.K.S.V.f.j.h.j.M.j.$.x.l.d.v.T.m.b.d.X.j.M.k.l.l.k.z.d.d.d.Y z.z.d.d.j.h.x.k.d.z.k.j.j.k.k.k.z.v.c.c.c.n.n.v.d.d.z.z.z.d.v.f.l.l.l.l.v.f.$.N.j.z.v.n.n.n.v.z.N.<.$.$.z.l.z.d.l.d.k.z.d.d.z.j.x.z.j.$.z.A.A S (.A r.4.4.4.4.4.4.%.r.R R 2.4.4.2.%.2.%.Y %.2.1.1.r.%.4.*.&.5.r.%.%.%.X.#.#.F h.N.$.#.1.r.1.#.X.2.X.4.*.....E 4.4.E R %.>.>.`.. #X#X#X#X#X. f.>.#.1.X.2.#.1.1.#.>.#.#.$.>.1.X.R E E E u.E r.2.2.1.1.2.r.r.2.%.E E R R ....u.z.u.4.4.2.%.1.#.#.#.5.8.8.&.E u.*.7.7.7.8.8.*.3.+.*.&.&.*.b.+X+X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ D sXfXsXwX4XwXH.-.m.m.S.K.H.K.S.m.K.b.m.H.C.C.K.H.S.v.h.j.k.z.j.j.c.c.c.c.V.V.k.k.v.l.z.z.d.z.j.x.z.d.z.j.v.b.b.b.n.k.h.h.x.z.k.k.k.j.k.k.z.d.c.v.c.c.v.v.n.c.d.d.d.l.z.j.k.l.l.d.l.d.x.d.c.c.n.b.n.n.b.b.g.d.$.$.l.f.l.l.l.d.d.d.d.d.z.j.j.z.h.$.) . +X+X. CXc.{ 2.%.r.r.r.X.2.r.R %.r.4.X.%.X.%.2.1.2.1.2.r.r.u.&.*.r.%.R R %.1.#.#.#.$.>.1.1.r.%.X.#.1.X.%.u.*.*...*.u.4.E u.>.>.' . #X#X#X#X_.. VXX.>.>.1.Y H 2.1.#.>.$.$.<.$.%.H #.r.&.E E E R 4.R r.1.#.#.$.%.4.%.R E E E 4.1.1.#.#.1.%.r.R R 4.r.>.>.4.*.7.&.5.5.3.3.&.T *.t.5.*.*.&.&.&.=.!.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ jXuXsXsXwX4XA o.B.V.H.S.B.B.C.H.B.m.m.B.T.B.V.B.T.d.j.M.z.l.d.z.c.T.S.S.V.B.v.n.b.m.T.l.j.z.k.j.k.d.k.f.m.b.b.b.m.v.h.x.h.j.z.k.k.k.k.k.k.z.v.n.n.c.n.n.n.g.c.l.l.v.l.z.d.l.l.l.f.c.n.n.v.f.c.n.n.g.c.n.T.m.G.$.l.l.f.l.f.v.f.d.d.d.d.j.k.k.#.f.+X@X#X#X#X@XCXw.{ } 2.2.%.%.1.2.%.4.4.r.X.%.%.X.F X.1.$.2.r.u.*.*.4.4.u.R R %.r.2.#.#.1.2.2.1.2.2.%.%.#.#.%.5.*.*.*.*.5.4.E r.>.( . #XmX#XSXVX. . J.<.2.1.X.Y X.1.1.#.$.<.<.$.%.%.#.>.2.E *.......R r.%.X.%.1.$.#.5.t.R ....%.<.<.<.1.2.2.2.4.u...t.4.%.2.#.<.#.5.&.3.5.........5.*.*.7.&.&.&.*.S +X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmXD _.gXfXsXsX4X3XY.[ [ [ H.V.B.L.P.H.V.V.B.b.w.m.T.b.z.j.d.n.n.d.d.C.K.V.H.C.T.n.c.b.b.m.b.z.z.z.z.l.d.l.n.b.n.n.n.n.v.x.X.h.j.j.k.z.k.k.k.j.k.z.c.b.n.n.b.n.c.c.v.v.v.v.z.f.v.f.v.c.n.n.c.v.v.v.c.n.c.v.g.c.v.c.z.z.v.v.v.c.v.v.l.l.l.d.j.k.j.#.S . #X#X#X#X#XBX. ) %.>.1.R r.1.%.4.r.%.r.%.R 2.2.M.X.$.#.r.r...*.u.t...R u.4.4.%.2.2.r.4.t.r.#.1.r.R %.#.1.%.5.&.&.*.*...4.R <.e.CX#X#X#X_.@X+X/ f.<.2.M.M.H M.1.1.2.$.,.<.#.X.1.$.#.2.$.>.t.E 4.....u.R R X.X.X.#.%.t.E Y %.#.F #.<.$.2.r.2.t.E E E 5.5.5.t.2.#.r.3.&.*.*.*.*.*.3.*.*.&.&.&.7.*.Y.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ iXuXsXsXwX4X3X;XC.A Y.H.S.S.C.H.S.S.H.S.B.B.T.B.f.M.T.T.b.n.T.K.S.V.S.K.T.b.m.n.w.w.B.b.z.z.f.v.v.n.n.q.g.c.c.n.c.k.x.h.X.h.h.z.z.k.j.j.k.j.j.g.m.m.m.w.n.c.c.f.v.l.d.v.l.v.c.n.n.q.c.f.l.f.f.c.c.c.l.d.f.v.v.l.v.c.n.g.c.g.v.l.l.z.j.k.j.j.OX+X#X#X#X#X#X_.@X. (.v.{ { R R %.r.%.4.r.2.%.2.r.4.%.$.r.2.R *...5.....E u.%.4.5.5.5.5.5.5.%.1.1.2.2.1.X.M.2.3.7.*.E *.*.4.{ 1.`.+X#X#X#XVX@XI.<.>.R M.%.R %.1.#.2.#.,.<.#.#.$.>.1.1.$.<.,.#.5.t.4.R R E R H R X.F X.%.%.%.#.$.F F #.<.$.2.2.4.............3.3.3.U u.3.7.&.3.&.=.E R *.*.&.&.&.U A.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XD AXxXuXsXwX4X4XqXxX0XgX[ C.C.S.S.H.H.Y.H.S.V.m.B.v.f.b.n.T.S.V.B.B.B.V.H.w.b.m.b.b.b.m.S.n.l.v.c.n.n.c.c.v.v.c.n.c.k.X.j.k.h.N.h.X.1.h.x.h.x.d.c.g.T.g.c.n.c.c.c.v.k.d.c.v.v.n.c.c.c.l.l.l.v.f.z.k.z.d.z.k.d.d.d.v.g.q.n.n.n.c.d.d.z.k.k.1.e.. #X#X#X#X#X#X#X#X#XCXCX( M.r.t.4.%.4.r.r.2.%.%.2.%.%.%.M.4.....5.*.*.*...R %.5.3.*.*.3.5.5.4.1.X.2.>.1.z.Y t.&.&.U U *...4.>.A . #X#X#X#XBXmX#.>.%.r.2.4.4.1.#.#.#.<.,.$.#.$.#.2.2.1.$.$.$.2.r.4.4.r.%.R R R X.F %.R %.H X.<.,.,.<.$.,.<.2.#.2.5.U R u.....*.....E ..E 5.3.&.=.=.l.E *.&.=.=.3.m.VX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ iXfXsXsXqX3X4XzXgX;XC.S.C.C.C.K.C.C.C.H.S.B.T.v.c.n.V.C.B.B.V.V.V.V.B.S.B.b.w.m.m.m.V.c.v.c.n.n.b.n.c.c.g.v.l.k.h.x.j.j.X.h.#.l e.G.X.z.v.b.g.b.g.k.z.f.v.c.c.f.d.d.d.v.g.g.n.n.c.g.c.z.j.x.h.h.h.d.d.k.z.z.Y f.n.n.b.n.n.g.d.l.k.k.j.k.$X+X_.% #X#X#X#X#X#X#X_.VXCX( { %.2.%.t.r.2.%.%.4.R %.4.Y 2.E E 4...*.*.&.5.%.t.*.*.&.*.*.5.5.u.1.X.%.2.X.H R R } I :.:.O.R { z.@X@XmX#X#X#X).+Xz.>.r.2.R R %.2.1.2.1.1.2.X.%.X.2.2.F 1.1.1.1.r.u.4.4.4.r.%.E %.#.X.E R H %.#.<.<.,.,.<.$.1.2.#.>.2.4.4.4.t.5.E ........E 4.4.&.=.=.l...l.=.=.T ( +X@XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X)._ dXuXsXsX3X4XhX[ [ L.B.c.m.B.S.C.H.m.V.m.T.T.c.v.T.S.S.m.B.S.S.S.V.B.B.B.B.m.m.m.B.m.z.v.g.c.n.n.n.q.b.l.h.h.X.h.h.h.j.k.h.$.Z.CXZ.v.S.b.T.T.n.k.k.d.l.c.c.c.c.c.d.k.z.z.d.v.l.d.d.k.N.N.j.x.x.j.d.d.d.d.d.k.f.b.b.b.b.b.c.l.l.z.k.2.A . #X#X#X#X#X#X#X#X#X#X#X#X@XBXI.#.r.t.3.4.#.%.r.r...E u.4.%.u.4.4...*.*...4.r.5.*.*...3.=.7.l.X.>.X.k.%.%.4.2.%.g.e.V.w.S.g.v.` CX#X#X#X#X#X#X. JX>.%.E %.2.X.%.2.1.1.2.%.2.#.1.#.F X.1.#.X.2.%.E E R 4.1.$.2.%.1.R %.2.R 2.2.t.4.r.2.R %.$.<.#.<.$.1.1.2.t.t.4.E 5.E t.E E E E *.v...3.l.v.*.*.$X+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmX_ jXuXsXsX3X4XC.[ C.L.L.v.v.m.m.V.S.f.l.c.f.l.k.l.m.T.B.V.V.H.C.K.H.S.B.m.m.m.m.m.S.S.x.z.b.b.b.b.g.b.c.x.N.X.j.X.x.x.k.k.h.1.A . ` b.I.n.b.g.d.k.d.d.z.c.g.v.v.v.d.d.k.j.z.d.z.Y x.N.h.x.j.j.x.k.l.d.l.l.d.d.c.m.w.n.n.b.g.f.l.d.M.g.7XBX_.#X@X+X. CX7XSX#X#X#X#XSX. /.#.t.5.5.*.4.2.4.%.u.5...%.R R r.4.5...E *.B.B.*.*.*.U *.=...%.#.2.%.%.%.R 2.{ S CXCX+X+XCX@XBX+X_.#X#X#XSX7XCX#X] d.} %.2.1.2.%.#.1.2.1.#.2.X.%.%.%.%.X.X.F X.E R 4.E 4.2.#.$.4.2.2.1.%.E ..5.4.4.u.5.U t.%.$.,.#.r.%.#.h.R t.E *...4.t.E ..5...l...5.l.=...E n.VX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ $XfXfXsXqXwXC.H.C.L.L.B.v.w.B.S.C.H.d.X.k.z.l.g.B.S.B.B.Y.C.c.m.Y.C.S.B.m.m.m.m.S.f.X.j.k.v.b.b.n.v.j.X.x.x.h.h.X.x.j.j.h.h.g.. R.n.n.T.f.k.z.z.z.d.z.z.f.f.f.c.f.k.k.d.f.d.d.z.M.j.M.j.j.k.z.j.z.l.v.d.z.f.l.n.m.n.g.n.c.c.f.d.k./.. +X. CXVXQ.V.Y.#X+X#XSX#X#X#XBXSXd.O.4.O.&.7.4.r.O...l.u.%.E %.r.4.4...E *.s.-.&.*.&.&.&.#.<.#.X.4.4.r.%.I >.q . @X#X#X#X#X@XVX#X#X#X_.#X. mXm.=.&.&.X.1.2.2.2.X.%.R H %.%.%.%.X.1.1.#.#.>.<.$.%.R 4...R 2.#.<.1.2.1.2.%.E ....t.%.E E u.R t.r.#.4.4.R 2.X.%.4.l.f.Y R E E E ..*.4...=.E U g.A._.@XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX_ dXuXsXwXdXH.H.S.S.T.B.T.n.V.S.H.w.M.d.n.n.B.B.H.K.B.S.C.L.l.d.n.b.B.V.B.B.B.H.T.N.j.k.h.X.k.z.z.j.x.j.x.h.j.h.N.X.j.j.x.#.g.. Y.n.T.n.z.k.d.d.z.z.z.k.k.f.c.g.d.X.z.f.l.l.d.z.k.Y k.k.d.v.l.k.k.l.d.d.z.J.l.c.m.n.c.c.n.v.f.l.z.c.w.V.;.V.=.t.:.} ..` . VXmX#X#X#X. m.} &.9.5.&.5.2.4...&.R Y R %.4.r.2.*.&.*.3.*.&.&.&.9.%.#.%.5.5.H %.{ >.>.g.CX@X#X#X#X% #X#X_.#X#X#X#X+X$XT | 3.7.&.X.2.1.1.1.2.R %.2.1.#.#.#.1.#.#.#.#.#.<.,.$.4.r.%.2.#.$.<.2.4.2.r.%.%.4.E ..R %.r.R E 4.R t.4.4.4.r.1.2.l.O.4.e.( ( w.c.c.v.w.' (.;.A.mXCX7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XD 1XsXqXeXH.o.V.w.b.m.H.V.n.m.B.n.M.w.K.n.B.H.S.V.B.S.C.U.V.z.l.c.v.n.B.S.V.V.m.m.l.j.k.x.X.j.X.Y k.j.j.x.j.k.j.N.h.j.j.h.h.f.A.T.T.T.T.d.z.f.l.z.k.k.z.d.v.c.l.z.k.v.l.d.l.l.d.z.d.d.c.n.c.c.z.j.z.z.z.z.z.f.c.v.v.g.n.g.f.f.5.5.O.u.R :.I O.5.5.5.:...Z.+X@X7XCXCXCXmX..q.S.t...*.t.t.t.r.M.Y 2.r.%.R 2.%.&.=.8.8.&.&.8.&.5.*.*.*.&.5.1.X.z.A +XBX_.#X#X#X#X#X#X#X#X#XSX+X$X*.3.&.7.6.&.2.2.1.1.#.1.1.1.1.1.1.#.#.>.$.>.<.<.,.<.1.%.1.2.#.1.%.1.r.t.t.%.r.r.r.4...&...Y Y Y E Y Y E t.4.4.r.r.z.z.R A.. CX+X7X#XSXSX+X+XBXCX+X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ hX0X;Xo.V.m.w.m.S.Y.K.T.n.m.b.T.~ S.v.m.C.V.V.S.C.L.L.n.l.n.c.c.n.w.B.B.n.c.b.b.k.j.j.j.x.j.Y z.j.j.j.j.j.j.h.h.j.j.X.x.z.d.n.T.V.V.v.z.v.l.z.z.d.l.f.l.J.z.z.l.v.f.l.v.l.d.v.b.b.b.n.g.g.d.j.z.z.z.k.G.z.v.d.d.f.J.z.*.5.U U t.E ..5.3...5.5.*.5.E | C.. SXQ.m.d.c.c.3.4.=.T 5.E u.4.r.%.M.4.2.r...u.2.r.4.u...&...*.*.&.3.3.*.3.3.t.A.. . @X_.#X#X#X#X#X#X#X#X#XmXZX+Xq.| &.&.7.i.d.X.2.1.1.#.#.$.#.1.1.1.>.$.<.<.$.<.,.<.%.E u.1.2.X.1.F 4.U 4.4.%.2.2.X.%.Y X.X.H M.X.M.R E E R t.E 4.4.Y e.DXCXVX#X#XAX@X@X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ yXuXhXo.K.C.m.B.Y.K.K.C.V.S.K.F.C.b.n.c.Y.C.H.C.C.C.B.m.V.B.b.c.v.c.n.n.v.c.b.b.z.j.k.M.j.j.j.Y j.j.j.k.j.X.x.h.x.k.j.x.d.f.c.n.m.T.n.l.d.f.d.d.l.f.l.z.k.z.d.v.v.v.v.l.d.l.b.b.b.b.n.n.c.l.z.z.d.d.j.j.z.l.l.J.M.I 5...&.l.O.t.t.5.5...5.:.t.&.5.*.l.=.e...O.} 3.q.3.5.*.&.u.4.R E Y r.r.Y E R r.R ..t.r.$.$.>.X.1.h.Y 4.4.3.3.*.3.3.q.#X@XmX#X#X#X#X#X#X#X#X#X7X. . S.:.3.*.+.*.7.M.2.%.r.2.1.$.#.X.1.>.%.u.r.r.#.$.#.2.t.%.1.4.u.R 2.#.2.t.4.4.R R %.H F <.<.#.#.#.#.r.1.%.Y 4.4.u.5.4.Y E ` . #X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ dXgXo.K.C.S.S.H.L.K.T.T.Y.L.K.m.B.m.c.b.C.K.C.S.b.n.m.m.m.m.n.c.c.l.c.b.n.n.n.k.x.z.z.k.x.X.Y j.k.k.k.k.x.k.X.j.k.j.j.z.f.c.n.g.n.b.I.z.z.l.z.J.d.l.k.z.d.d.v.c.c.c.v.l.v.n.n.n.n.n.n.g.v.z.j.z.d.x.k.l.v.d.M.d.S.DX$XmXSXY.O.t.5...U I m.b.O.5.t.v...:.O.5.U =.C.H.9.&.*.5.4.r.%.%.2.R E R R r.r.E E t.%.1.$.1.2.h.u.4.u.5.3.&.3.&.O.e.. #X#X#X#X#X#X_.VXCX+X`.P e.U +.&.&.&.*.3.X.%.2.2.%.2.#.1.X.#.>.4...R 4.#.#.4.u.4.%.R E E 4.2.4.t.4.R E R R R j.#.$.r.4.4.4.t.4.1.X.X.2.5.5.*.E E ..!.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"_.SX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ iXxXH.S.H.K.C.C.L.I.M.d.V.H.B.V.B.B.w.n.m.Y.K.V.b.b.m.m.b.b.n.n.b.v.v.n.v.c.v.j.j.k.z.d.z.j.k.z.j.k.z.Y j.j.k.k.z.k.X.d.v.I.I.c.n.c.T.n.z.d.d.k.G.k.k.d.l.l.v.v.c.v.v.l.v.n.n.c.n.b.b.g.d.k.k.z.j.j.l.v.l.Y A ).. +X7X@X. +Xl.:...5.} m.. Y.} 5.E t.u.5.5.5.5.t.O.=.F.q.5...u.4.%.2.%.E R M.%.4.%.R E u.4.2.#.1.H 1.z.*.5.t.*.&.&.&.3.T VX. @X#XmX_.VXCX+X/ S.=.5.+.7.&.7.*.3.*.3.4.2.%.f.d.Y 2.#.X.F %.M.R u.%.4.5.5.4.u...u.%.r.r.u.5.4.R E R R Y X.#.2.2.2.r.4.t.4.r.1.X.1.1.5.3.&.*...f.DXBX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"mX_.mX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX7XjXS.C.K.K.K.C.m.n.T.n.n.C.K.C.C.H.H.S.V.V.V.m.V.B.B.B.w.b.n.n.w.n.v.c.c.c.j.X.k.d.d.l.l.k.Y k.j.k.z.k.j.k.j.k.d.k.j.d.J.l.g.g.v.f.n.B.v.z.l.d.z.k.k.f.f.f.v.c.c.v.v.c.n.n.n.n.b.n.l.d.j.x.z.G.k.l.f.l.z.z.#X. #X#X#X#X#X+X/ O.{ { n.+X. b.O.5.5.t.5...5.t.5.*.*.t.5.u.4.u.t.%.%.r.E 4.%.X.%.E E 4.R ..t.%.#.#.X.F X.*.*.=.5.5.=.&.7.U w.(.mX. @X+X+X!.n.5.U 3.7.i.i.&.&.*.3.*.&.3.4...l.....X.$.1.1.X.4.4.r.t.*.5.u.....u.%.4.%.t.t.t.5.E E u.%.%.2.r.t.1.#.r.4.4.4.R 2.%.2.1...&.&.*.U w.7XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XCXE.m.C.C.S.V.B.m.S.S.S.B.m.m.S.S.B.T.w.b.w.b.n.m.V.B.B.T.n.n.c.m.v.j.d.l.l.k.x.z.l.l.l.l.z.k.z.k.j.z.d.k.z.k.j.k.j.k.z.l.z.d.c.v.c.v.g.n.f.d.l.l.d.d.l.v.f.l.v.c.c.c.g.b.n.b.b.B.g.Y %.h.j.l.l.d.f.v.f.M.f.VX@X#X#X#X#X#X#XCX' n.e.VX+XBXb.| *...U E ..5.:.U &.*.*.4.%.4.r.2.r.2.4.E r.%.X.%.E R %.2.R E t.2.1.X.%.N.M.8.s.b.&.&.=.5.u.I O.d.Y.BX(.c.4.O.*.*.7.8.i.i.8.3.*.&.&.3.*.&.*.U 5.t.{ $.F #.<.1.X.t.*.5...*...t.4.E u.4.t.E ..*.....%.r.5.5.3.*.5.{ 2.r.4.R R %.%.#.X.*.7.&.*.U A.CX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X% #X#X#X#X#X#XSX#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@XW.C.K.B.S.C.C.K.B.B.B.B.B.m.n.v.f.f.l.v.c.n.m.n.c.c.c.n.b.n.n.b.B.l.j.k.d.l.v.z.z.f.f.l.l.z.Y z.k.k.z.z.k.k.j.k.j.k.z.k.d.z.k.f.n.n.v.v.c.n.v.d.d.d.l.l.f.l.z.f.n.n.c.n.b.b.b.m.w.X.h.j.J.e.( v.l.f.l...%.A CX#X#X#X#X#X#X#X#X+X. CX@X#XCXS.:.&...t.5.5.:.m.B.&.*.*.u.R 4.%.2.2.r.E R 4.%.X.%.E R 4.4.R ..E 4.%.X.H 1.r.&.*.H.H.T 4.4.4.4.O.I } v...} t.*.3.*.7.8.i.i.p.7.3.&.&.&.&.&.*.3.3.=.M.>.%.%.>.1...3.*.&.&.*.u.t.5.5.t.5.5...E 4.E R r.3.&.&.*.5.T g.{ 2.r.r.r.Y Y F t.&.7.7.*.U A.CX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X% #X#X#X#X#X#XSX#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVX;.B.K.L.L.C.S.S.V.B.V.B.m.m.V.T.l.v.v.g.n.n.n.n.n.c.c.c.g.b.m.b.z.j.l.d.l.v.v.l.z.v.v.v.f.d.j.k.z.z.j.j.k.j.j.z.k.z.G.k.z.z.k.d.T.c.v.v.c.n.T.n.d.d.f.f.f.l.d.z.c.w.n.b.m.m.B.b.w.A A.`.mX+X. I.R z.M.M.S +X).#X#X#X#X#X#X#X#X#X#X#X#X#X@XSXq.| 5...} { b.. A.| t.t.5.k.R E R %.R R 4.u.2.X.r.R 4.R E R R ..R t.%.%.%.2.&.7.3.8.*.r.4.u.t.u.t.4.:.4.t.3.*.3.&.7.8.i.i.i.&.5.*.7.=.7.*.3.&.&.(.g.>.%.%.1.%.*.&.&.=.*.t.5.*.u.t.3.5.5...E R u.4.5.*.&.&.&.| n.. d.<.1.2.z.d.4.4.*.7.=.&.*.U Z.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X_.#XSX#X_.mX#X#X#X#XSX#XSX#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X@XL.B.H.L.C.V.V.S.H.S.B.B.m.m.B.B.v.l.v.c.n.n.b.b.q.c.c.c.n.n.v.h.<.N.f.v.l.v.c.c.f.v.v.v.v.l.k.z.z.z.G.k.j.k.z.z.k.z.z.k.z.z.k.k.v.b.c.v.n.b.B.n.z.d.v.f.v.l.l.z.k.c.b.b.w.w.n.X.I.CX. BX@X#X+X/ z.z.l.) . @X_.#X#X#X#X#X#X#X#X#X#X#X#X#X_.7XVXZ.P (.V.;.. ;.O.5.q.T 5.E E R R R 4.4.4.r.2.X.2.R 4.E E r.r.E ..E 2.F Y X.u.i.&.u.r.4.E t.t.5.5.u.t.u.u.5...*.*.7.i.8.i.&.5.5.*.&.7.&.3.*.+.T $Xk.{ R r.2.u.&.&.&.*.3.&.&...u.*.3.............*.&.&.&.*.*.I q.. SXR r.z.z.R t.t.&.7.&.&.U c.@X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#XmX#X#XmX#X_.#X_.mX_.#X#X#XmX#XSX#XSX#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@XR.S.C.H.K.C.H.C.C.C.S.B.m.T.m.m.v.l.c.v.g.b.m.w.n.g.c.n.c.l.h.<.$.<.z.c.v.c.c.c.g.c.l.v.v.f.l.l.d.d.k.j.z.z.l.z.z.z.k.k.z.z.z.j.d.n.T.T.n.n.c.d.l.d.f.v.v.f.l.z.z.k.d.l.l.z.M.h.j.(.+X#X#X#X#XBX$X(.#X+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X+X+X+X. . W.| &.s.v.=.5...R r.r.4.4.4.2.1.r.%.%.R u.E E %.r.%.E E 4.2.%.X.4.&.u.r.t...t.4.t.5.5.5.5.3...5.3.*.7.7.&.3.3.5.5.3.*.*.3.3.3.3.3.=.DXz.>.R 2.%.5.*.*...3.=.n.=.t.*.&.&.*...*.*.*.*.&.&.&.&.&.U v.(.7X. _...} { O...E &.3.U U ..DX+XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X_.% _.#X_.mX#XmX#X% #XmX_.#XSX#X_.SX_.SX_.SX#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVX`.K.K.C.H.L.L.C.S.V.I.n.m.T.m.m.f.l.f.v.n.v.z.v.b.n.g.n.n.n.g.v.f.k.k.c.c.c.q.n.n.v.l.v.l.v.f.l.l.d.j.k.d.z.d.k.k.z.k.k.z.z.k.z.v.c.I.T.I.d.l.l.l.l.n.f.l.d.z.l.v.v.l.k.x.X.j.d.1.I.. AX#X#X#X_.BXBX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X7X(.0.7.8.*.t.*.*.5.%.4.4.4.t.2.#.2.%.%.R E R R 4.R R r.4.E u.4.%.M...u.4.E ..t.4.t.*.&.3...5.5.*...3.&.3.5.5.u.E u.t.u.5.| O.t.=.=.5.C.+Xz.{ R r.4...*.5.5.*.c.v.5.t.3.*.*.5.O.O.| t.5.=.7.&.&.| m.BXBX_.#X. ;.O.v.l.%.4.I *.=.=.( . #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#XmX#X#X% _.#X_.#X_.mX_._.#XmX#XSX#XSXmXSXSX_.SX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.VX#XSX`.^ C.B.b.c.v.v.v.n.b.m.m.v.l.v.v.b.d.$.z.g.c.c.c.g.n.b.b.n.n.v.c.g.q.g.n.n.n.c.v.v.v.f.v.f.z.k.d.l.d.l.z.d.d.j.f.l.k.k.d.n.I.T.B.I.d.c.l.d.c.m.v.d.l.d.l.c.c.g.c.k.j.j.z.Y X.!.. #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXBXm.3.i.8.5.4.*...5.t.4.Y u.r.#.1.r.M.R %.4.E R %.4.4.%.%.E 5.4.%.Y u.5.*...t.4.4.3.8.8.8.7.&.3.5.t.5.t.t.t.t.t.U ..U t.t.c.S.;.`.1XFXCX#XM.2.E 2.4.*.*.u.5.*.l.t.5.5.5.O.O.:...b.v.E U | | | | n.BX+X#X#X#X#X7X#XBX` e.w.e.' #X#X7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X% _.#X_.#X#XmX#XSX#X#XmX#XSX_.SX#XSX#X_.#XmX_.SXSXSX_.SX#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVX@XBX@Xe.c.n.n.q.n.c.n.n.m.T.f.l.v.v.n.n.f.v.v.c.v.v.c.v.c.v.v.f.v.c.n.n.n.n.b.n.c.v.c.v.v.c.v.z.z.f.d.l.f.d.d.z.z.n.n.z.M.J.n.I.T.V.T.v.v.l.v.n.b.g.l.f.l.f.v.c.c.n.c.z.j.M.z.%.j.' . #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmXVXCXb.3.8.8.*.t.u.....3.5.u.Y X.1.2.%.R X.r.4...E R 4.t.E R R *.R %.j.O.3.*.t.t.5.t.*.*.5.5.5.5.5.t.t.t.t.t.u...5.E 5.t.:...VX. +XBXBX+X+XSXM.{ R %.4.5.u.t.u.*.d.%.Y k.u.) !.A.' BXVX_.' w.q.b.S.% +XSX#X#X#X#XAX7X@XBXCX+X+X+X@XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#XSX#X#X#X#X#XmX#XSX#X_.#X#XSX#X_.mX_.#XSX_.SXSX_.SX_.SX_._._.mXSXSXSXSX% _.SX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@XmXV.n.n.b.b.n.b.b.T.m.f.d.v.v.v.c.w.n.v.v.v.v.v.v.c.l.d.d.d.l.d.g.b.n.n.b.b.g.c.c.c.d.l.v.J.l.v.f.d.d.z.z.z.v.c.n.d.M.v.I.b.T.V.S.c.v.b.n.n.n.m.n.l.v.v.v.c.c.c.c.n.z.j.z.d.2.z.#XBXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX+X!.=.+.7.7...t.r.n.B.t.*.u.h.j.X.X.%.r.2.4.u.E ..5.%.4.*.t.4...u.%.%.l...t.5.5.t.u.4.r.4.t.u.t.t.5.t.E u.5.5...5.r.{ } ..( CX#X#X#X#X#X@XVXz.{ u.r.4.5.u.4.u...l.E %.z.( . CXCX+X#X).7X+X+X7X7XCX@XmX#X#X#X#X#X#X#X#X#X#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#XSX#X_.#X#X_.#XmX#X#XSX#X_.mX_.mX#XSX_.mXSXmXSXmXSXmXSXmX_._.SXmXSXSX$XSXSXSX_.% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X7X(.B.V.S.V.V.I.n.b.b.n.z.l.l.l.v.n.n.n.v.v.v.f.f.l.z.z.l.d.d.l.z.d.w.b.n.n.b.n.q.g.f.d.d.f.c.g.b.g.l.d.z.d.d.l.J.f.f.z.n.T.T.T.V.V.n.n.T.g.g.T.m.m.n.v.v.v.v.v.c.v.c.n.d.H z.z.1.e.. #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@XF.7.3.*.*.&.*.4.4.&.b.5.5.5.r.h.h.X.2.2.2.%.E ......R 4.5.R %...E r.Y g.M.2.4.4.r.r.r.4.t.t.t.t.5.u.U ..5.R O.{ { r.w.Q.SX+X#X#X#X#X#X#XVX7Xl.{ E %.r...5.4.u.E *...1.e.. #X#X#X#X#X#X#X#X#XAXVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#XmX#X_.mX#X_.#XSX#X#XmX#X#X#XSX_.mX_.#X_.SX_.SXSXSXSXSXSXmX_.SX_.SXSXSXSXSXSXSXSX#X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X` V.S.H.V.m.n.v.v.v.c.l.l.v.f.c.b.b.n.c.f.v.f.d.j.h.h.j.d.l.d.d.z.b.m.n.n.c.n.n.c.l.v.c.c.n.n.g.b.b.w.c.f.g.c.d.d.v.v.T.B.I.T.V.K.T.n.c.g.b.T.T.T.B.g.f.v.v.f.v.q.c.n.c.l.k.d.M.z.#X+XmX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVXmXi.@.i.&...*...u.u.t.4.=...t.4.2.1.1.#.2.2.%.5.E ......R E ..t.....%.j.%.2.2.r.r.r.%.u.t.R ..5.5...5.u.O.{ { } v.V.GXCX. 7X#X#X#X#X#X#X#X@X@Xd.} E 4.r.t.5.4.4.E *.d.2.c . #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X_.mX_.#X#XmX_.mX#XmX#X_.#X_.mX_.mX#X#X_.SXSX#XSX#X_.#XSXSXSXSXSXSXSXSXmX_.SXSXSX$XSXSXSXSXSX_.SX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVX#XS.m.B.m.b.n.c.v.c.q.f.d.c.v.q.n.n.q.c.c.v.d.M.X.j.j.j.k.d.f.l.d.v.m.m.b.n.n.c.f.v.g.c.c.c.g.n.n.I.S.V.J.c.n.d.z.v.g.n.T.m.T.S.K.V.c.c.n.b.T.b.T.T.v.d.c.c.v.v.c.c.c.v.g.l.k.d.%.I.BX).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XBXB.+.@.8.*.*.5.u...u...c.*.t.4.t.%.%.4.1.1.r.......*.5.........E ..E %.r.4.4.%.4.r.4.*.E 5...5.t.5.t.O.E n.V./.BX. +X#X#X#X#X#X#X#X#X#X#XVX7Xl.} E R 2.u.*.t.4.E ..l.%.A.. #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X% #X#XmX_.#X#X#X_.#XSX#XSXmX#XmX_._.mX#XmX_.SX_.SXSXSX_.mXmXSX$XSX$XSX$XSXSX$XSXSXSXSX$XSX$XSXSXo SXSXSX% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X;.q.b.m.b.b.q.T q.n.v.v.g.g.g.n.n.c.g.c.l.Y j.j.k.d.l.l.l.l.d.d.k.f.n.n.v.l.d.d.f.c.v.c.g.c.b.T.T.V.L.T.f.I.g.z.c.f.g.V.B.e.V.T.b.n.n.n.w.T.T.T.n.f.d.f.g.c.c.v.v.c.c.v.c.d.z.d.2.A.CX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X_.H.i.@.| 4...u.5.d.5.t...*.3.u.5.7.5.#.#.1.u.*.*.*.....*...5...E t.R r.4.4.E R t.E E 5.t.t.u.5...*.| S.. . CXVX#X#X#X#X#X#X#X#X#X#X#X#X).BXv.} E R r.4.5.t.4.E ....d.' +X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X_.#X_.#X_.#X#XmX_.#XSX#XSX_.#XSXSXSX#XSX#X_.mX_.mX_.mX_.#XSX_._.SXSX_.SXSXSX$X$X$XSXSXSXSXSXSXSX$X] SX$X`.$XSX$XSXSX#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X#XZ.V.w.s.s.s.n.b.n.b.m.m.w.b.v.v.n.c.l.d.d.z.z.d.d.v.c.c.v.z.j.k.z.z.z.k.j.v.n.l.f.c.g.b.n.T.V.S.B.f.v.v.c.I.v.f.k.c.T.n.T.V.V.T.I.n.T.T.m.V.b.v.v.l.d.c.g.g.v.f.f.c.c.c.n.d.l.%.A CX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX@X+X$X!.S.*.r.u.R 5.*.*.*.*.5.u.&.*.X.#.1.1.%.&.*.*.*...E ..t...*.*...4.u.E 5.4.4.4.4.4.5...*.7.7.7.3.B.BXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+Xn.{ E E %.4.5.5.t.t.E E n.mX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#XmX#XmX_.#XmX#X#X#X_.mX#X_.mX_.mXSX#XSXSX_.#XSX_.SXSXSXmXSXSX_.mX_.SXSXSXSXSX$X$X$XSX$XSX$XSXSX$XSXSXSX$X`.DXSX`.SX#XSX#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX@XBX@X` ;XgXgXxXgXe.G s.G s.9.m.Z.e.l.l.l.v.v.d.z.c.n.g.c.n.d.1.j.l.z.k.k.j.n.Y.T.g.c.n.n.b.I.n.K.T.k.l.v.c.g.c.v.k.J.T.g.T.S.Y.S.T.T.B.V.B.I.c.v.c.c.d.v.c.c.g.v.c.v.c.c.g.v.l.Y V.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X+X+X@Xe.} 4.u...*.3.3.5.*.&.t.N.X.X.>.%.&.*.*.*...t.O.t.t.E v.d.r...t.%.4.4.t.u.5.*.=.7.7.7.7.3.b.7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X. A { E E 4.r.3.*.E t.5.E g.mX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X_.#X_.#XmX_.#X_.mX#XmX_.SX#X_.mX_.SX_.SXmXSXSX#XSX#X_.SX_.#XSXSXSXSXSXSX_.SXSXSXSXSX$X$X$XSXSXSXSXSX$XSXSXSXSX$X$XDXSX$XDXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@XCXrXfXgXuXuXgXy w.I.k ;X. . Y.l.v.v.l.c.c.n.b.n.n.c.c.c.k.j.z.k.j.X.f.T.V.S.n.c.c.n.b.T.g.T.v.j.d.g.g.c.f.g.J.z.T.n.T.Y.C.Y.C.C.V.b.n.n.v.v.n.v.d.v.c.c.c.c.c.v.l.v.c.v.d.d.v.mX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+X. V.} 4.E ..5.*.&.&.*.u.1.h.1.$.Y T *.*.*.&...E E 5.....4.R E O.4.4.4.5.3.3.*.&.+.3.3.| | ;.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X. Y.} E E R 2.t.3.5.t...4.n.BXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#XmX#X_.#X#X#XmX_.SX#XmX_.SXmX#X_.SX#XSX_.SXSXSXSXSXSXmXSXSX_.#X_.SXSX$XSX$XSXSX$XSXSX$XSXSX$X$X$XSXSX$XSXSXSXSXSXSXSXSX`.$XSX8 SX_.mX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ iXfXhXgXzXuXfXsXqX0XwX$ . Y.l.v.v.v.c.m.w.b.b.n.n.c.w.b.k.x.k.d.d.v.I.T.V.n.g.n.n.b.w.T.g.g.f.v.b.g.c.v.g.l.k.v.T.g.B.S.Y.Y.T.n.n.b.n.c.g.c.v.v.v.q.c.c.g.c.v.v.f.c.c.l.l.d.Q.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X. A :.u...5...u.5.t.r.%.X.$.1.d.&.&.*.*.&.&.=.u.%.R 1.2.E t.%.4.4.2.%.t.5.5.:.| 9.s.s.L.@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX+Xw.} E E E 2.4.3.t.U ..O.w.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#XSX#X#XSX#X_.mX#X#X_.mX#X_.SXSX#XSXSX_.mXSXSXSX$XSX$XSXSX#XSXSXSX_.SXSXSXSX$XSXSXSXSXSX$XSX$XSX`.DX] $XSX$X`.SX$X8 $XSXSX$XDXDXSX8 `.SX% #XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ yXfXhXhXfXzXxXfXuX0X0XrX. P v.T v.c.b.b.b.b.b.b.c.g.V.T.l.z.v.n.v.d.n.B.V.b.v.c.b.I.I.n.n.T.T.g.c.c.v.c.c.z.k.k.g.T.v.T.C.n.v.c.b.b.n.b.n.c.n.n.v.c.g.c.g.v.v.c.v.c.n.v.v.Y A.CX% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmX@X. I.:.5.t.u.t.O.r.%.%.t.1.h.E 5.*.&.*.&.*.&.5.1.1.2.2.%.R R r.%.1.2.r.I 4.n.R.VXBX+XCX#X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+Xb.} ....E R R 5.5.u.5.O.w.7XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X_.% #X#XSX#X#XmX_.mX_.mX_.SXSXmX_.SX_.#XSX_.mX_.SXSXmXSX$XSX$X$XSXSX_.mXSX_._.SXSX$XSX$XSXSXSXSXSXSX$X$XDX`.DX] $X8 $XSXSX$X] SX$X$X`.DXDX`.DXSX#XSX#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXAXsXhXtXqXfXuXxXfXuX0XqXCX! v.c.v.v.b.n.b.b.b.b.c.m.S.w.c.c.v.v.c.f.g.Y.Y.S.S.g.v.b.n.n.I.I.T.I.J.l.f.v.J.k.k.j.z.I.b.n.T.n.n.n.n.b.w.w.w.m.I.v.f.v.q.n.n.n.c.v.v.c.n.g.v.Y ;.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.BXBXd.{ :.} } ..S d.r.r.2.1...5...&.&.&.&.&.3.2.2.2.%.%.r.4.r.4.r.1.{ %.( . CX@X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#XVX7Xg.O...5...E %.t.&.5.5.U n.@XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X_.mX#X_.mX#X#X_.mX_.#X#XSX#XSX#XSXSXSXSXSXSX_._._.SXSX#XSX$XSX$X$XSXSXmXSXSXSX_.SXSXSXSX$XSX$XSXSXSXSXSX$XDX`.DX`.DX] $X$XSXSXDXSXSXDX8 $X$XSXDXDXSX_.mXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ dXsXjXqX4XfXxXxXuX0X0XiXZ q.q.c.v.n.b.n.n.b.n.c.V.S.n.c.c.v.v.v.v.l.A.+X@X7X`.I.l.l.g.b.T.T.T.f.l.l.f.v.v.z.x.k.n.T.g.n.n.n.n.b.T.m.B.B.n.J.r e.c.c.n.n.n.c.c.c.v.c.n.n.d.A +X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.CX(.v.l.b.Y.@XDXr.r.%.2.M.*.5.5.*.&.&.&.&.*.r.2.%.r.r.2.r.4.R R 2.%.OX. VX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+X/ t.E 5.....t.r.3.&.5.E O.m.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X% #X_.mX#X#X_.mX#X#XmX_.mX#X#XSX_.mXSX$XSXSX$XSXmXSXSXSXmXSXSXSXSX`.$XSX`.DXSXSXmX_.SX_.SXSXSXSXSX$XSXSXSXSXSXSX$XSXo DXDXDXDX$XDX$XSX`.$XSXDXDX`.DXDX`.DXDX#XSX_.#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ aXuXtXhX0X4XsXsXuXuX0X4XaX-.T n.v.n.b.b.n.m.n.b.B.I.v.l.l.l.v.v.d.d.d.e.`.. . 7XA.I.c.n.n.T.n.f.f.l.J.n.n.k.x.k.c.I.n.n.b.b.w.m.T.B.g.l.d.l.e.. e.l.n.b.n.c.c.g.c.q.n.n.c.e.@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmX+X+X@XCX. . ) { r.X.2.l.*.U 3.*.&.&.&.&.7.E R R R %.%.r.r.4.4.} z.DX. . 7X_.% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XCXR.O.5...*.*.5.4.5.&.5.5.U / +X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X_.#XSX#X#X#XSX#X#X_.mX_.mX#X#XSX_.mX_._.SX_.#X_.SX$XSXSX$XSX$XSXmXSX$XSX$X$X$X$X$X`.SXmXSXSX$XSXSX$XSX$X$X$X$XSX$XSXSX$X] DXDX`.DXDX8 `.DX`.SXo DXSX] $XDXDXDXDXDXDXDXSXSX#XAX#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XD _.sXfXdXqXwX3X4X3XwXqX0XuX.2.2.%.R 4.%.4.4.u.R r.} { u./ . #X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXVXBXSX_.b.I 3.*...E *...*.&.*.U =.$X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X_.% #X_.mX#X#XmX#XmX#X#X#XSXSX_.SX_.mXSXSXSX_._.SX$XSXSX$X$X$XSX$XSXSXSX$XSX$XSXSX$XDX`.$XDX`.SXSXSX$XSXSXSX$XSX`.SX`.$X] DX$XSXSXDX$XDXDXDXDXDXDXDXDX] $XDXDX`.DXDXDX@ 5 DXDX@ DXSX_.#XAX#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).D rXfXsXsXsX3XqXqXqX4XuX0XqXm.G G b.b.w.B.V.B.w.m.m.n.n.c.z.Y k.M.z.d.l.d.X.d.AXCX#X@X@X+X!.e.;.e.z.l.f.g.v.k.h.j.J.g.I.w.w.T.S.g.z.z.d.l.l.l.v.b.n.b.b.b.n.n.c.c.l.l.Z.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+XP @.8...H 5.*.&.*.5.&.&.7.&.7.&.2.2.2.2.4.E E R u.u.U R E ..:.r.!.. @XSX#X#X#X#X#X#X#X#X#X#X#XSX@XBXZ.0.0.*.U *.&.*.*.&.*.*.*.3.| A CX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X_.mX#X_.mX#X#X_.#X_.#X_.mX_.mX_.#XSX#XSX_.mX_.#XmXSXSXSX_.SXSXSX$XSX$X$X$XSXSXSX$X$X_.SX$XSX$XDXDX$XDXDX$XSXSXSXSXSXSXSXo ] o `.DX8 $XSXDXDX`.DXDXDXDXDXDXDXDXDXDX`.SXDX` DX] DXDX` DXDXDX@ SX#XSX#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ AXsXqXsXsXsXqXtXjXfXeXsX4XqX A c.n.b.b.b.n.g.b.w.b.n.!.+X#X#X#X#X#X#X#X#X7X] m.w.m.B.m.V.m.n.Y.@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+X;.+.8.i.i.i.6.~ . iXlXzXzXzXzXzXxXzXuX0X0XuXqXfXqXuXpXfXhXSX_ mX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XBXW.8.K 8.K +.V.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#XSX#X#X#X_.mX#X#X_.#X_.mX#XSX#XSXSX#X_.SX$X$XDXDX`.`.SX_.SXSXSX`.$X_.o $XSXSX$XSX_.SXSXSX$XSXSXSX$XSXSXSX$Xo SXSXSX`.DXDXSXSX$XDX`.$X] DXDXFX@ @ FXDXDXDXFX' FX6 / 2 HXHX# (.FXGXFXFX5 DX@ DX` FXFX' 6 GX6 5 DX2 ) 2 ` DX8 FXGX5 DXDXDXDXFX5 (.FX5 5 5 5 FX' FXFX' FXFX@ `.DXGX2 6 6 5 5 5 5 6 4 3 3 HX3 ( 3 1 JXJXHX6 / 6 3 HXGXGXGXGX( 2 GX) 3 4 u 3 6 FX2 ) 4 4 JX2 6 5 DX' GX3 2 ' ' 6 6 N n & dXdXhXhXjXjX+ V N 2 2 / 2 6 FX6 6 m V.B.S.S.H.S.m.b.b.m.m.B.;.2 > n.c.b.b.b.n.g.n.n.n.n.Q.. @X#X#X#X#X#X#X#X#X#X+XZ.0.m.B.B.B.B.n.V.VXVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XBXs.*.i.8.i.i.@.K.. $XkXlXpXzXzXzXzXzXxXzXuX0X0XqXqXfX4X0XpXgXD _ #XmX#X#X#X#X#X#X#X#X#X#X#X#X#X7X` 8.8.8.8.3.m.BXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#XmX#X#X_.mX#XSXSX#X_.#XmX#X_.SXmX#X_.SX$X$XDXDXDX$X$X$XSXSX$XSXDXDXSX$XSXSXSXSXSXSXSXSX$XSXSXSXSX$XSX] $XSX$XDX`.SX$X`.DXDXSXSXDXDXDXDXDX`.` (.DXDXDX(.DXDXDX(.FXGX2 GX/.HXGXFXDXDX(.DXFX' FX6 FX(.6 OX' OXGX/ FXDX` 2 GXDXDX] ] 5 FXDX5 ` 5 (.DXDXFX6 FX5 ' FX5 ' FX6 6 ' FX` FX/ 6 2 3 GX/ 2 ( 2 2 3 4 ) ) u ( 5 / ( 2 2 2 HX3 3 / FXGX3 ) 4 ) ( 3 3 S q u / 6 6 ` DX6 3 HXFXFX5 6 6 5 6 n B b b B B b ~ 6 6 6 6 / 2 2 2 HX2 2 ;.B.B.S.S.H.V.w.b.m.m.B.S.: S n.n.w.w.b.n.n.b.n.c.Y.VXFX$XBX@X#X#X#X#X#X#X#XBX' b.m.m.B.B.V.m.V.AX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVX7Xn.+.q.8.i.i.6.-.VXCXAXgXlXkXpXzXuXuXzXxXxXzXuX0X4XqXsXuXqXfXgXaX_ AX#X#X#X#X#X#X#X#X#X#X#X#X#XBXP 7.6.8.8.+.9.mX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X_.#X#X_.#X% #X_.#X#X#XSX#XSX_.SX#X_.SX_.mXSXSXSX$XDXDXDXDXDX$X$X$X$X$X`.$X$X`.SXSXSX$XSXSXSXSX$XSXSXSX`.SXSXSXSX$XDX$XSX$XDXDXSX`.SXDXDX`.`.DX$XDXFXDXDXDXDX(.DXDXDXDXDXGXHXHXXX/ GXGX2 / @ FX` DXOXDX# 6 FX# 6 6 6 FXFX' 3 ' 8 DXSX6 GX` DXDXDXFX6 DX` FX' 5 ` 5 FX6 ' FX6 ' 6 5 DX' 2 HX( 6 5 5 5 ' 2 2 M 4 2 / 4 1 KX1 JX4 3 2 2 2 ( HX6 6 2 GX3 2 GX3 HX3 JX2 2 / FXFXS 4 2 6 5 5 DXDX5 ( 4 FX' 6 6 6 6 6 ' 6 6 FXDX6 / 2 2 2 2 GX2 S.B.V.S.H.H.B.w.b.m.m.V.Y.e.n.w.m.b.n.b.b.n.n.e.4 > c S 2 DXAX@X@X#XAX#X#XAX@XC.b.m.B.B.B.B.Y.#XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.BXDX7.7.i.i.8.i.8.0.`.@X_ _ dXkXlXpXzXzXuXzXzXzXzXfXpXuXqXqX0XqXpXfXyX_ D mX#X#X#X#X#X#X#X#X#X#X#X+XC.7.8.8.8.K =.' +X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#XmX#X_.mX#X#XSX#X#XSX#XSX#XmXSX#XSX_.SXSXSX_.$X$XDXDX(.DXDXDXSXSX$XSX$XDX`.SX$X`.$XSXSXSXSXSX$XSX$X$XSXSX$X] $XSX] SX`.`.SX$XDXDXDXSXSXSXDXDX`.SX`.FX6 FXDXFXFXFX5 5 GX( GXHXHXHXHX/.FXFXFX' FXFX' FX' FX` FXFXFX(.FX2 GXDXSXGXu 3 ` 5 DX8 GXHX5 ` 5 5 ' FXDXFX6 6 ' 5 5 FX6 # ' 6 GX6 FX5 ' 6 GX2 2 2 2 5 6 ` 3 1 1 JXJX1 3 6 3 HX3 2 HX/ 6 ( 3 2 6 GX3 3 ) 3 ( 3 4 A u GX' 5 DX8 8 8 3 2 5 6 6 / N 2 2 2 6 ' ' 5 6 ' FX6 6 GX5 @ ;.B.S.S.S.H.C.B.b.w.m.V.V.b.n.b.w.n.g.n.n.n.n.> : > > S c c S 2 SX#X#X@X#X#XBX] m.m.m.m.B.m.Y.SX).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+XS.3.8.=.i.8.i.i.6.!.BXmXZX_ aXdXpXkXkXuXuXzXuXuXuXxXzXzXuXuX4XqXfXfXjXD ZXSX#X#X#X#X#X#X#X#X#X#X7XS.K 8.i.8.=.+.Z.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X% _.#XSX#X#XmX_.#XmX_.#XmX_._.SXSXmX_.mX_.mXSXSX#XSXSX$XDXDX1X` DX$XDX$XSXSXDX$XDXDX$XSX$X$XSXSXSXSXSXSXSX`.o $XSXSXSXDXDXSXSX$XDXDX`.SX$XDX` DXSXSXDX5 FXDXDXFXFXFXDXDXFXFX(.6 2 ( HXJX2 GXGXHX/ FX5 DX@ ' @ FXFX' 6 6 OX6 5 FX/ 3 3 ' FX8 FX2 ' 5 DXDXDXFXFX5 5 FXFXFX5 5 FX6 / 6 ' ' 6 FX(.6 2 2 2 6 ' FX' 6 6 2 S 4 4 S JX2 4 y S 4 4 6 GX6 2 HXGX(.6 ( 3 3 HX2 3 ) S u 2 6 6 FX/ ) 4 ( GX6 ' 5 ` 5 3 u ( 6 6 6 / 6 ' 6 6 / 6 6 6 m V.B.S.S.S.H.C.m.b.m.B.S.m.b.b.b.n.c.g.n.c.n.c : 4 M M > S u u 2 ' 6 @ #X@X@X7XY.0.m.B.m.m.S.SXVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X7XDX8.7.8.7.8.8.8.i.@.C.BX#X_.AX_ _ SXtXuXkXpXuXuXzXuXzXfXfXxXfXuXfXsXfXpXhX_ D mX#X#X#X#X#X#X#X#XVX#Xs.8.8.i.8.8.3.S.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#XmX#X#XSX#XmX#X_.#XSX#X#XSX#X_._.SXSX_.mX_.mXSXSX_.SXSX$XDX(.FX(.FXDX$X$X$X`.DXDXDX$XDXDXSXSXSX$XSXSX$X$X] SXSX$X`.`.SXSX$XDXDXDXSX$XDX` DX$XSXDXDXDXDXDX$XDX5 FX`.DXFXDX@ ` @ DXFXHXJXHXHXXXGX6 FXFX/ GXFX6 FXFXOXFXFXFXFXGX6 HX( 6 5 FX2 3 DXDX8 SXSX5 ' 5 FXDX5 FX5 FX5 FX6 ' FX5 ' 6 6 GXFX' 6 FX5 6 2 ( 4 4 6 6 3 3 6 OX3 4 ) KX1 ) 6 2 3 ( 3 GX2 3 3 HX/ GXGX( & 4 ) 2 2 3 S q A HX6 6 5 DXSX6 S 4 GXFX/ 2 / 2 2 2 2 / 6 ' GX# ( V.B.S.S.S.H.S.m.m.m.B.V.b.b.n.n.n.n.n.n.c.c 2 M M 4 M 2 @ ' 6 6 2 3 2 6 ` +X`.w.m.m.B.m.m.`.7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XCXZ.3.i.8.7.7.8.8.i.@.s.#X@X#X#X#X#X_ _ D dXpXkXpXpXfXuXfXzXfXxXxXfXsXsXsXuXhXD _ #X#X#X#X#X#X#X#X7XDX7.7.i.i.8.K +.m.7XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#XSX#X_.mX#X_.#XmX#X#X_.mX#X#XSXmX_.mXSXSX_.SX_.SX$XSX$XSX_.SX$XDXDX(.FX@ ` DX$XSX$X`.o DXDXSXSXDX`.SXSXSXSX$XSXSX$XDX$XSXSX`.DX`.`.SXDXDXDX`.o ] DXFXDXDXDXSX`.DXOXDX`.5 FX' FXDXDXDX` 2 JX4 HXGXHXHXHX3 GXFXFXDX' FXDX# 6 GXGX6 GXFXFXGX/ ( ( DXDXSX5 ( 2 5 5 DX` 6 GX5 5 FX' ' FX5 6 FX' 6 6 5 ' 6 5 (.@ GX3 3 2 5 (.6 ' 2 3 4 4 3 ( 3 u u y S JXS 2 HX2 ( # GX' FX3 ) HX2 FXGX3 3 S 3 2 2 2 FX' 2 4 HX2 2 / 6 5 ' 6 3 ) HX6 6 6 GXFX@ ;.B.B.S.S.H.C.S.m.m.B.S.w.n.b.n.n.n.n.c.w.3 M u c 2 FXFXFX6 6 6 6 / 3 S M DXo S.s.m.m.B.s.R.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+XC.3.8.8.&.7.8.8.8.i.8.^ BX#X#X#X#X#X#XD _ yXsXqXpXpX0XuXqXfXfXfXxXfXfXsXfXuXdXD _ mX_.#X#X#X#X#XBX^ +.8.i.8.i.8.+.b.VX).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X% _.mX#X_.#XSX#XSX#X_.mX_.#XmX_.#XSXmXSXSX_.SXSX_.SXSXSX_.SX$XDX1X(.FXFXDX$XDX$XSX`.DX$X`.FXDX$X$X`.SXSXSXSXSX$XSXSX$XDX$XDXSXSXDXDXDXSX$X`.DX(.DXSX$X8 DXFX] DXDX(.' GXFXFXFXFXFXFX2 ( HX3 ) JXJXJXHX' FXGXHX6 FX6 FXFXGXFXFX@ ' 2 GXHXHXFXDXFX3 A 3 DX5 DX5 / 2 ' 5 FX5 5 FXFX' FX6 6 GX6 ' 5 6 GXN GXFX/ 6 FXFX6 2 3 3 M 3 GX' 5 6 u 1 JXJXKXu GX2 ( 2 3 2 GX3 ( 2 ( GXGXGXHX3 3 3 3 ( 3 4 1 4 ' 2 ( 6 FXDXFX2 HX( / 6 ' 6 6 / 6 2 B.B.B.V.S.H.H.V.m.B.V.Y.w.n.b.b.n.c.n.2 = q y 4 5 5 5 6 ' 6 / 2 2 2 2 2 2 6 A w.B.m.B.m.b.W.CX@XVX_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X+Xm.&.0.8.7.&.7.=.8.8.+.L.+X#X#X#X#X#X#X#X#X_ _ ).iXuXpXpX0XuXfXuXfXxXxXfXsXsXuXgX)._ mX#X#X#X#X#XCXZ.3.8.p.i.8.8.7.T $X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X% #X_.#XSX#X_.#X#X_.#XmX#XSX#X#XmX_.#XmX#XSX#XSX_.SXmXSXmX_.SXmXSX$XSXSXSXSX$XDX(.FXFXFXFXDXSXo $XDXDXDXDX$X8 @ `.SX$XSX$XSXSXSX`.8 `.SXSX`.DX`.] $XDX] DXDXDX] DXDXFXDXSXDXDXFX@ ` DXFXGXFXDX(.FXFXFX5 GX2 HXJX4 / HXJXJX2 GX` DXFXFXFX' ' GX/ / GXGX/ 6 2 3 ) ( FX5 DX6 3 GXFX5 ` 8 GX2 ' FX6 FX5 ' 6 ' 6 6 / GX6 FX6 6 FXDXFXHX2 2 GX6 ' 6 6 2 S 4 4 ) ( 4 2 1 A JX4 3 / 2 FX2 4 3 GXFX2 2 HXJXFXGX) 4 4 3 2 ( 2 ' 5 DX6 3 HXFXFX6 FXFX6 ' 6 # Z.m.B.V.H.S.H.H.S.m.m.;.> n.T c.c.b.( SX4 r q 6 6 FX` DXDX6 2 2 / / FX6 ' 6 m.s.B.m.m.B.b.C.@ / SX7X@X#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XBXB.+.i.8.8.7.7.8.8.8.+.B.7XVX#X#X#X#X#X#X#X#XAXD _ ).rXuXpX0XqXuXfXfXfXxXxXfXsXuXgXD _ SX#X#X#X#XBXs.| K i.i.8.8.7.8.` BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X_.#XmX#X#X#XmX#X_.% #X_.#X#X#XSX_.SX_.#XSX_.mX_.SXSX_.SXSXSXmX_.$XSX$X$XSX$XSXSX$XDX(.FXFX' FX` DX$X`.DXDXDXDX` `.SXSXDX`.SXSX$Xo $XSXSX`.DX$Xo SXSXDXDXDXDXSXDXDXDXDXDX] SX(.DXDXDXDXDX5 6 FXDXDX(.FXFX5 `.DX6 JXJX3 JX3 HX2 GX2 ( GXFX6 FXFX2 GXFX/ GXGX/ HXHX2 6 FX' JX3 5 5 DXSX5 GX6 5 5 5 5 ' 5 @ FX6 6 6 6 6 6 6 6 6 GX2 ' ' 6 ' FX6 / ( u 4 3 3 3 4 3 3 4 S 3 JXu 2 6 6 3 HX2 2 2 HX2 4 2 DXGX2 3 4 S 4 3 HX2 6 u A 3 6 6 5 5 DX8 FX/ 4 GXo ;.m.B.S.S.S.H.C.V.m.S.6 3 A Y.S 3 2 ( S S 2 2 HX2 / 5 5 6 ( ( GX2 FX' 5 2 w.w.m.m.B.m.B.m.c 1 c 6 #X@X@X#XAX@XVX#X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVXVX9.+.=.i.i.8.3.7.=.8.8.7.P +X#X#X#X#X#X#X#X#X#X#X#XD _ SXrXuXpX0XuXuXfXxXxXfXfXsXuXdXD ).#X#X#XBX(.+.&.8.i.i.i.K 7.7.!.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X_.#XSX#X_.#XmX_.#XmX_.mX_.#X#XSX#X_.mX_.#XmXSX#XSX#XSXSXSX$X$XSXSXSXSX$XSXSXSXSX$XDXFXFXFXOXFXDX$X`.DX`.DXDXDX$XDX(.DX$X8 ] SXSXSX$XDX`.8 SXSXSXDXDXDX$X8 `.DXDX`.DXDXDXFXFXDXDXDXDXDXFXFXDX` FXFXGXFXDXFXFXFXHX) 4 KXKX( JXJX4 / GX6 ` FXGXFXGX2 6 GX2 GXGXGX6 GX/ JX( ` DX8 DXu 4 ` 5 5 5 FX2 / ` 5 GX/ ' FXFX6 6 / / 6 / = / 6 DX' 2 3 3 3 2 ' ' 6 2 ( ( 3 S 3 JXKXu KXy u GX3 ( ( 2 2 ) 2 / # ' HXJX) 4 4 JX3 4 A 1 2 / 6 5 DXDX` DX4 S FX5 FXV.s.B.V.S.S.C.H.B.B.Z.# # o @ 2 2 3 2 DX' 3 ( 3 4 ) ' 2 JX6 6 FX5 DX8 2 w.b.B.m.m.m.m.m.V.> u A 1 > DX@X#XDXSX@X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X#Xq.+.=.=.+.H.V.3.7.7.=.+.;.CX#X#X#X#X#X#X#X#X#X#X#X#X#X_ _ #XsXpX0XuXfXfXxXxXzXfXfXuXjX_ #X#X#X+XZ.| 8.8.8.i.8.8.K +.Z.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#XmX#X#X#XmX_.#XmX_.#X#X#XmX#XmX_.mX_.SX#XmX_.SXSX_.SXmX_.SXSXSXSXSX$XSXSXSX$X$XSXSXSX$XDX(.GXGXGXFXFXFXo SX`.DXDXDXFXDX`.DXDX`.SXSXSX`.SX$XSXDXDXDXDX] SX$XDXDXDXo _.DXFXFXDX] SX`.` FXDX8 DX@ FXGXGXFX6 6 GX' # ( JX( JX3 S KXKXHXGXHX2 ( 6 / / 6 FXGXGXDX6 6 / 2 GXHX3 FX5 5 ) q 4 5 FX` DXFX3 2 ` 5 6 FX6 6 DXFX/ 2 6 6 6 6 6 6 6 GX/ m GX6 6 FX6 6 / m 2 3 4 3 ' ' 3 KXr S 6 KX4 2 6 GX2 HX2 6 OX' HX( 4 3 ( 3 ) 4 ) ) ( 2 FXGXu u 4 4 HX' 6 8 Z.m.m.V.S.H.S.C.H.B.;.6 6 6 / 6 6 GX2 3 ) ( HX( 3 4 3 4 4 S S 3 4 3 DX3 b.b.w.B.m.m.m.m.m.S > u c q A 3 4 c 1 2 SX@XBX@X#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXBXB.3.7.7.7.i.' s.+.7.7.+.s.@XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ D rXpX0X0XuXfXfXxXxXxXfXfXyX_ mX#X+XH.| 7.7.8.8.i.8.=.+.Y.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X_.#XSX#X_.#XmX_.mX#X_.mX_.#X_.SX#XmX_.mX_.SXSX#XmXSX_.#XSX$XSXSXSXSX$X_.SX$XSX$X$X$X`.$X$XDXFXFXGX' GX' DXDXDXDXDX5 DXDXDXFXDXSX$X8 $XSXSXDX@ `.DXDX$XSXDXDXDXDX] SXDX5 DX] DXDX5 FXDXDX`.DX' FX5 DX` ' GXFXFXFXFXFX5 FX2 HX3 KXu HX( JX4 3 GX5 DX` / 6 FXGX/ 2 HX2 / 2 GX2 GX2 S ) ' 6 ` 5 ( 3 / FX5 5 DXm HX5 6 N / 6 ' FX' 6 2 HX/ @ GXGX6 6 ' 2 ( 3 3 3 FXFX6 5 ' 5 N 4 KX4 KXu 3 4 q ( 4 JX/ 2 HX3 3 3 HXGXGX2 JX4 S 4 ( 3 4 1 q q 3 2 GX# DXSX;.s.B.V.S.S.C.C.S.Y.GX2 : / 6 GXGX2 ( 2 FXFXDXFX/ 2 ) c q q A c 1 3 A.b.b.b.m.m.m.m.m.s.V.> > u 1 c u u u c q A 4 / DX@X XBX@X#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X_.@X. K.| &.=.8.3.=.b.+.=.7.7.3./ +XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#XD _ tX0XpX0XuXuXfXxXxXxXxXfX1X_ @XVXT 3.7.=.K 8.i.8.8.+.B.BX#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X_.mX#X#X#XmX_.#X#XSX_.mX#X#XSX#X#X#X_.SX#XSX#X_.SXSXSXSX#XSXSX_.mXSX$XSXSX$X$X$X$X8 SXSXSXSXSX$X`.DXOXGXGXFXGXFX`.$XDXDXDXDXFXDXSXSX(.DXSXSXDX`.SX$XSXSXDXDXDX8 SXSXDXDX` DXDXDX5 FX` DXDXSXDXDXDX` DXDXDXFXGXDXDXFXFXFX6 FXDX(.6 4 4 ) JXHXHX/ XXGX) 3 GX6 / 6 GXGX' FXOX' GXFXGX) 3 GX' 5 ( S 2 FX5 DXDX` GXGX5 FX6 5 6 6 6 ' 6 GX6 6 6 6 6 2 2 6 6 2 2 / 6 5 FX' FX2 2 ) 2 S 1 M 2 ) u 1 4 JX4 3 6 6 6 2 GX2 FX$XOXHX) & 2 2 JX) ) 4 4 HX2 2 6 FX2 3 Y.m.B.V.S.H.C.H.C.3 3 HX6 GX2 2 2 2 2 2 / FX3 4 4 u q q A q 1 > S u w.b.n.m.B.m.w.m.m.b.S.u c 1 u S S S S c c q q q 3 ' 3 FX+X+XVX#XSX#X#X#X#X#X#X#X#X#XSXBXVXY.T &.&.&.=.8.3.5.7.7.&.7.| S.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX_ _.rXpX0X0XuXfXxXfXxXzXsXSX. (.&.+.=.&.=.8.i.K 7.+.m.7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X_.mX_.#X#XSX#X_.mX_.SX#X#XSX#XSX#XSX#X#XSXmX_.mXSX_.SX_.SXSX_.SXSX$XSX$X] SXSX$XSXSX$X$X$XSX$XSXDX(.FXGXGXGXFXDXFX(.`.DXDX` `.DX6 (.`.DXDXDXSXSXSX`.DXDX] $XSX`.DXDXDX`.DXDX(.DXDXDXDXDXFXFXDXDXDXDXDX' 6 ` ` 6 6 / GX5 FX@ ` FX3 4 KXKXKX4 4 HXKX4 FXGX6 DX/ GXFXFX2 GX2 HX2 GX2 2 6 GX2 S 2 DX` 8 DX6 2 / 5 5 5 FX( 3 ' FX6 6 / GX6 6 6 ' GX/ FX6 6 6 6 ' 6 6 2 ) S 4 ( 2 3 / ' 6 3 4 4 3 KXu 3 GX3 3 OX3 2 2 2 2 3 ( # / 2 2 3 4 JX( 3 3 3 2 1 * HXS.m.B.S.S.S.C.H.Y.& ' 6 2 2 2 2 HX( 2 2 4 q q q q q q q q q q * e.b.b.n.q.w.m.s.w.m.w.m.q * c S S u u > S u c 1 A q q q q S @ _.@XAX#X@X@XAX#X#X#X#X#X@X#Xq.| 3.=.&.&.7.7.5.u.&.7.&.=.3.q.7XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ _ iX0XpX0X4XfXsXfXxXzXdXCX] 3.&.7.7.7.7.8.8.7.+.9.% @X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#XmX#X#X#XmX_.#XmX#X_.mXSXSXSX_.#X#XSX_.#XSXSXSX#X_.SX_.mXSXSXSX#XSXSXSXSXSXSX$XSX$X$X$XSXSXSX$X$XDX$XDXDX(.' GX2 GXGXGXDX`.DX@ DXFX' FXDXDX` ` `.$XSX$X8 `.SXDXFXDXDXDX`.SX`.DX@ DXDXDXDXDXFXFXDX`.8 DX6 FX`.DXDX' GX2 GX' GXGXGXFX6 4 S 3 KXKXS 4 KXu 2 / GX( 3 2 6 2 / 6 2 / FX6 GX6 ( HX( KX2 5 DX` M y 1 5 FX5 ` 6 3 HX6 6 6 6 6 6 ' FX/ FX5 6 6 6 FX' 6 / 6 FXGXHX( 2 2 / 6 6 5 5 2 u S 4 S HXHX( y q 3 u ) 3 ( 2 3 3 HX( GXFX2 JX3 4 ( HX) u 1 ) # A.s.B.B.S.H.S.C.;.GX' 6 6 6 GX2 3 3 2 4 A c 1 c A q q A q q q q e.b.b.w.b.n.m.m.w.b.b.b.m.1 u S c > S c u A q q c u c c q y y q GX+X@XFXFX#X+X@XAX_.#XCXY.| *.&.&.&.&.&.&.5.4.*.&.&.*.*.*.DX+X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX_ _.eXpX0XuXfXfXsXfXzXiXW 3.7.&.7.&.7.8.8.8.&.T $X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X_.#XSX#X_.#XmX#XSX#XSX_._.mXSXSXSX#X#XmX_.mX_.#XSXSX#XSXSXSX#XSX$XSX_.SXSX$XSXSX$X$XSXSXo `.$XDX$XDXDX$XSXo FXFXGXGX2 GXFXGXDXDXDX(.@ DXDXFXFXDX] SXDX`.SXSXDXDXDXDXDX] o DX` DXDX8 DXDXDXFX` DXDXDXFX' ` 8 DXFX# ' FX5 5 GX2 # FXFXGXGX6 ' 2 JXS KX1 4 JXHXKXS 3 HXFX5 ` 2 GX' GX6 / HX3 3 3 2 / 2 HXS q 1 6 6 DX5 3 JX2 6 6 ' 5 FX6 ' FX6 6 6 6 / 6 FX` 5 / GXGX2 / 6 GX6 6 6 6 6 2 4 4 ) u S GXFX3 S u JX( u 3 6 6 2 3 ) 3 2 GXHX3 3 S GXOX3 ) ) HX3 2 Y.m.B.B.S.S.S.C.2 # GX5 ' GX2 3 4 4 1 c u u c * A c * c 2 / 2 c n.b.w.b.n.n.b.m.b.w.b.n.q u u c q r r 1 * A * c u u u u 1 c q q ) 3 q q u 2 $X@XBX7X#XT t.*.&.&.*.*.*.&.*.u.4.*.&.*.*.| Y.CX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ D rX0X0X0XuXfXsXfXfXv.+.&.=.7.*.&.K 8.7.7.T DX7X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X% #X#X#XmX#X_.#X#X_.SX#XmX_.SXSXmXSX_.#XSX_.mX_.SX_.SX_.SXSXSX$XSXSX#XSX$XSXSXSXSXSXSX`.DX$XSXSXSX$X$X] DX$XSX$XDXGXGXGX/ GXGXDX`.DXFXDXDXFXFXDXSXDX6 DXSX`.DX`.DX`.SXSXDXDXDXDXSXSXDX` 5 ` DXDXDX5 FX` DXDX8 FXFXDX` FX` FXGXGX' FXFXFX6 6 6 FXFXFX) u 4 S JXHX) JX/ GX) JXHX6 / GX6 3 2 ' 2 ( HX( 3 3 4 3 / 6 5 / u ) 6 GX5 DX5 5 ( 2 6 6 6 6 FX5 FX' 6 ' # 2 2 2 6 GX/ 6 5 GX2 JX4 4 3 6 6 / 3 3 ( 4 3 ) HXKX1 ( q r JXJX3 ( 3 3 3 4 JXGX2 2 3 4 KXu 3 GXY.m.B.V.S.S.B.C.m @ DX5 ( HXJXu u u u c 1 1 c u c 1 2 (.DX$X( b.b.b.w.b.w.m.b.b.b.b.q.b.c u 1 r k q c c c 1 u S c c c u 1 q q y q c c q y q 1 6 CXDXl.*.7.7.7.5.*.*.*.....u.E *.*.&.U T VX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.D _ yXuXpX0X0XqXxXfXf.6.9.&.8.&.&.7.7.7.7.7.(.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X_.#X_.mX_.#X#XmX_.mX#X#X_.#XmX_.SXSX$XSXSX#XSX#XSXmX_.#XSXSXmX_.SXSX_.SX$XSXSX_.SX$XSXSX$X$XSXSX$X`.SXo DXDXSX$X$XSXDX(.FXHXHXHX2 FXGX' `.DXFXFX(.DXFX/ @ DXDXDXDX$XSX8 DXDX` DXSX`.DXDXDX(.DXDXDXDX(.5 DXDXDXDX6 GX5 DX5 (.@ GXGX6 ` FXGXGX' FXFXFXFX' HX4 u u u 1 ) 4 JX1 4 3 2 / 5 FX) # DXHX( 2 2 3 JX( GX2 / 6 3 1 ) ' 5 ` 8 DX6 3 6 6 6 GX6 6 6 ' 5 2 6 6 / / 2 / 6 6 ' FX2 3 ) ( / / 6 ' 6 2 2 / 3 u u 4 2 4 u y r 2 ( KX3 2 FX5 ) HX/ 2 ' XXJX4 4 HXGX+ S.m.B.B.S.S.B.H.6 @ 3 4 4 4 S 4 4 S u c 1 u A q 3 GXGXGX# ) b.b.b.b.b.m.w.b.b.b.b.n.q.e.: u r r q q A 1 S c * 1 u c q y q A c u u c c 1 c q q 4 V.&.7.7.7.i.7.5.*.E E ....u...*.*.*.5.Z.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ ).rX0X0X0XqXsXv.p.G 7.8.&.*.7.7.7.&.&.^ +X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X_.mX_.#X#XSX#XSXSX_.mX#X_.SXSX$X$XSX_.SX_.SXmXSXSXSX_.SXmXSXSX$X$XmXSX$XSX_.SX$XSXSX$X`.DX$XSX$X$X$X`.DXDXDXDXDXDX6 HXHXHXHX2 FXDXDX` FXFXFX6 ' DXDX5 FXDXo $XDXDXDXSX`.6 FXDXDXDX] SXDXDX5 ` DX$X5 FX' FX` DX8 DX' FX` ` DXFXGX2 2 GXGXGX2 2 FX3 A u 1 q KXS u u 4 HXJX2 2 ( ( / 2 3 2 2 3 3 GXGX/ 2 3 3 ) u 3 5 ` 5 ' 4 q ( FX' 5 5 6 ( 3 2 FX6 2 2 6 6 6 6 FX6 2 2 2 / 2 6 6 6 6 6 GX2 2 3 4 4 3 2 6 FX3 1 S JXHXS u 2 3 q 3 3 ) HX# FXHX3 3 2 HX2 S m.B.B.B.V.S.B.H.A.y 1 2 3 M M 3 3 2 3 : y 0 1 ' GX2 2 2 3 w.9.b.b.w.b.f.v.m.b.n.n.q.n.c u r y y y * c * c q q y y y y y * u u c 1 u u u c 1 q &.9.p.i.3.*.&...*.u.R u...E E ..*.*.| w.BXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ _ 1XqX0X4XqXg.@.8.8.8.7.5.&.7.7.7.3.Z.+X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#XSX#XSX#X#X#XmX#XSX_.#X#X#XSXSXSXSX_.SXSX$XSXmXSX#X_.SXSX_.#XSXSX_.SXSXSXSXSX$XSXSXSX`.SXSXSXSX$X] $XSXDXDXDXDX$XDXDX`.SX$X(.FXGXHX3 HXFXGXFXDX5 DXFXFX@ ` GXFX`.8 SX` DXSXSXDXFXDXDXDXDXSXDXDX5 DXDXDXDXDXFXFX5 DXDX` FX6 FXDXDXDX6 / GXGXFX6 2 2 GX6 2 JXGXHX/ 3 S q 1 A ) 3 KXS u 3 3 2 2 FXFX( 2 FX2 2 HX) JX3 4 ) 6 ` 2 4 q y 3 5 6 FX` ' 3 JX2 ' 6 GX/ FX` 5 6 ' 2 ( 2 GX6 2 6 GX6 FXGX( M 3 ( 2 DXFX2 6 FX2 S u u u JXJX3 u r KX4 u HX2 ( ( 3 3 JX4 # Z.m.V.B.B.B.B.V.B.m.A & 3 S 4 3 2 2 3 FX3 0 r 6 6 GX2 HX6 # V.n.b.b.b.b.n.v.n.b.n.n.n.c.b.q 1 c * A A A q q q k k y y q q A c c c u A 1 c q * A 7.0.9.&.O.u.3.3.&.&...u.....u.E ..*.U b.@XVX#X#X#X#XmX#X).AXmX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_ $XuX4X4Xk @.7.=.8.8.3.E 7.7.&.3.Y.+X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#XSX#X_.#X#XSX#XSX#XSX_.mX_.mXSX$X$X$X`.$XSXSXmX_.mXSXSX_.mXSX$XSXSXSX$XSX_.SXo SXSXSX$Xo $XDXDXDX$XSX$X$XSX$XDXDXDXSXDXDXGXGXGX2 HXHXFXDX`.` FX` FX' 6 DXSXDXGXDX] DXDXDXDXDX8 $XDXDX` (.DX] $XDX` FXFXDXDX5 FXGX' 5 DXDXDX6 # 5 5 DX5 GX2 GXFXFXFX@ ' 6 2 GX2 JXq q 4 S oXu S ( GX' FX2 HXGX/ 2 ( 3 3 3 3 HX3 ( 3 3 2 u A 3 6 6 5 5 2 4 ( 2 6 ' 6 5 6 : 2 6 6 6 GX/ 6 6 GX6 / 2 GX/ 6 HX/ 6 / 6 6 6 ' 3 4 4 ) S 1 3 6 3 3 3 u 3 KXu / 6 6 / HXGX3 FX/ B.m.V.m.m.B.B.B.B.B.Y.JX4 S 3 2 A y u q 0 4 FXGXGXFX6 3 4 u w.n.b.b.b.b.b.n.b.b.n.n.c.c.m.* q q q q y q A y k y y r y q c q r y y y q q q u u q.7.+.q.S.*.s.H.&.7.8.*.u.....E 5.5.| c.@XVX#X#X#X#X_.D D _ ).mX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X. iX4XqXg.@.8.8.8.8.7.*.7.&.&.3.B.BX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#XSX#X_.mX#X#XmX_.mX#X#XSX_.#XmX_.SXSX_.SXSXSX$X$X$X$XSXSX_.SXmX_._.SXSXSX_.SXSXSXSX$XSX$XSXSX`.SXSXSX$X$XSXSX`.DX$X`.$XDX`.DXDX`.`.@ FXGXHX3 ( # FXHX6 DXDXDX' FXDX6 / FXDXDX` ` `.] $X8 DX5 DXDXSXSXDX` @ 5 ` DXDX5 FXFX5 ` DXDXFX' FXFXFXFXDX5 /.2 GX` GX2 GX2 6 FXFXFX# 4 u 4 S KX1 JX4 HXS A ) HX/ 3 / GX3 / FXFX( 3 3 GX2 4 KX2 6 ' ' 3 4 3 6 6 # 5 5 ' 3 S 2 FX' 6 2 2 / 6 FX6 / 2 ( 6 ' GX2 2 6 ` 6 / 3 4 ) ( 2 FXGX( 4 3 ) 4 3 JXu u KXHXy r HXHXJXHX2 S.w.m.B.B.m.m.B.B.m.b.Y.4 q q y r k k k y 2 ( 3 GX' / & JXA m.n.n.n.b.n.n.g.c.b.b.n.n.c.n.q q y y q q y q q q q q q q q q c q k k q c A A 1 > m.7.&.=.B.=.i.-.8.7.i.&.R E *...t.t.O.=.#X@X#X#X#X#XZXaXfXdXAX).#X#X#X#X#X#X#X#X#X#X#X#X_.mXBX@X] rXJ.7.&.7.=.=.8.7.7.7.&.&.3.w.7XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X% #X#X_.mX_.#X_.mX_.SX#XmX_._.mX_.mX_.SXSXSXSXo `.DXSXSX_.SX#XSX$XSXmXSXSXSXSX$XSXSXSXSX$X$XSXSX$XSX] $X`.DXDX$XSXSX$XDXDXDXDX@ DX`.`.DXGXHXJXHX3 3 FXDXFXFXFXOX' GXGX` DXFXFXDXDX] DXDXDXDXSXDXFX5 5 FX` DX8 DXFXFXFXDXDXDXDX' GXFX` DX5 DX6 2 ' @ 5 / 2 ( ) GX6 / (.6 6 4 A A q y 1 u KXHXq S OX2 2 FX2 ( 2 / HX3 ( 3 3 M HX2 3 2 / 2 4 1 ) 2 / ' 5 FX6 3 4 / ' 6 6 6 6 6 6 ' 2 GX6 2 6 6 6 6 2 FX$XFXGXHX4 3 2 / DX' 2 2 2 2 4 u S KX4 u S k 0 2 JXu JX= Y.s.w.w.m.m.m.m.m.m.b.b.e.q r r r r k 0 u GXJX( / 3 S O Y.T.m.b.b.q.n.n.n.c.f.v.n.n.q.c.c.b.q q q q q q q q q A c q q A c u S r r q y c u u 3 Y.@.7.&.3.7.=.&.=.8.i.8.5.u...5.t.t.O...`.. @X@XAX#X_ dXkXlXjX_ SX#X#X#X#X#X#X#X#X#X#X#X#X+X` =.7.p.8.3.7.7.=.7.=.7.7.7.+.&.3.b.7XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X% _.% #X_.#XSX#X#XmX#XmX_.#X#XmX#XSXmX_.SX_.SX$XSX$X_.SXSX$X`.`.$XSXSXSXSXSX_.SX$XSX_.SXSX$X$XSX$X`.SX_.$XDX$XSXSX$X`.`.DXDXDX`.DXDX$X$XDXDX$XDXDXDXGX( 3 ) 3 GXHX6 DXFX@ ' GXFX5 GX/ DX8 `.5 ` DX] $X' 6 DX(.5 DXSX`.` FXFX` DXDX` DXFXFX5 DXDXDXFX2 GXDXDX` 2 3 3 2 GX2 ( HX2 ' HXq 1 u S u S 1 KXy 1 3 ) GXu u 4 3 2 ) 2 2 HX2 / # ( 2 ) 3 XXHXu 4 2 2 6 ' ' 3 S HX6 GX6 ' 5 6 HX6 ' 6 6 / / 2 2 6 5 ' 6 / 2 2 2 ( / / 6 6 2 ( 2 3 3 ) S 4 4 ( GX3 1 1 ( JXKXu + ;.b.m.w.b.w.w.m.w.b.w.b.b.e.y y y k 0 k 1 4 S 3 ) q r q b.T.B.B.b.n.q.c.c.c.c.l.v.c.g.c.c.v.w.q q A c c c c q q q q q q q c S q y A r r * c 1 q b.8.8.7.&.7.=.8.8.8.=.&.5.E u.4.E R t.e.3 S / @X+XCXrXpXuXgX_ ).#X#X#X#X#X#X#X#X#X#X#X@X#X=.| *.8.i.+.*.&.&.=.7.7.*.&.&.&.3.n.CXZXmX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X_.#X#X#X_.mX#X#X#XSX#X_.#XmX#XSX_.mX_._.mXSXmXSXmX_.SXSXmXSXSX$XDXDX`.SXSXSX#XSXSX$XSX_.SX$XSXSX$X$XSXSXSX`.DXSXSX$XDXo o DXDXDXDXSXSX`.8 DXDXDXDXDX$XSXDX' GXJX) ( JX6 DX`.FX6 FX(.GXGX5 `.SXGX6 DX8 DXDXDX` @ DX] DX5 @ 5 DXDXDXDX5 FX' FXFXDXDX' / GXFXDXDXFXFXGX6 FX5 FX3 3 / FXDXGXHX2 GX6 S q 1 q y u u JXu q 1 ( GX2 5 FXHXGX6 / HXHX3 4 3 4 ) ) 4 2 6 6 2 1 1 5 FX6 5 5 FX6 3 / 6 GX6 6 FX6 ' 6 ' 2 2 / HX2 / GX2 / # ' FXGX3 ) 3 ( 2 2 2 / FX6 ) S u 4 JX4 JXS m.B.S.b.b.m.b.b.b.b.b.n.9.m.y r r r r y y r r y r r e.T.b.T.g.v.n.c.c.c.c.v.v.l.v.c.c.c.v.n.A * q q c q q y y y r y y r y q q A q q y y q y * * f.@.8.8.7.7.7.7.=.=.=.*...*.u.R E t.v.* q y u / _ iXpXuXkXjX. VX#XAXD _ _ _ D AX).AXCXZ.| 3.*.=.q.&.&.+.*.&.&.=...5.&.&.+.l.jXCX).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#XSX#XmX_.#XSX#X#X#XmX_.#X#X#XSX_.mX#X_.SXSX_.#XSXmXSXSXSXSXSXSX$Xo DXDX`.SXSXSXSXSXSX`.o SXSXSX$XSXSX$XDX$XSXSXSX`.SXSX`.o $X$X$XDXDX`.DXDXDXDXDXDX`.DXDX(.2 4 3 JX4 HX6 JX6 DXFXFXGXFXDXFX( 2 DXDXDXFX` DX`.8 DX5 (.5 (.DXSXSX5 FXFXFX5 DX5 FXFX6 FX5 DX8 5 (.FXFX' ' FX' ( 3 GXFX' GX2 2 / 3 3 6 / 1 1 1 1 KXHX4 S 4 GX2 S S 3 HX2 m 2 3 ) 3 2 3 JXJX3 6 3 ) u u GX5 5 ` DXDX/ 3 2 6 6 6 5 / 6 6 FX6 2 / 6 2 / 2 6 6 / 2 GXGX/ 3 / FX2 2 2 2 6 6 2 4 u u u 1 JXO KXV.m.V.V.V.H.m.b.b.b.b.b.n.n.m.r r r r r r r k k k r A T.m.B.m.c.c.c.c.v.l.l.c.v.l.v.v.v.c.q.e.c c q q q q q y y q y q q y y y q q q A q y q q q k u.S.7.*.7.&.&.&.&.=.&.*.&...4.R :.v.> c c q y c X xXpXpXhX] _.@XmXyXaXaXaX$XAX#XAX. C.5.*.5.5.l.*.7.&.3.*.*.&.&.u.*.+.&.=.xXrX_ D mX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X_.mX#X#X#XSX#X_.mX#XSX#X#XSX_.#XSXSX_.SXSXSXSX_.SX_.SX$X$X$XSX$XDXDX`.$XSXSX#XSXSXSXSXSXSX$XSXSX$X8 $XSXSXDX`.SXSXDX8 `.SXSX@ DXSX$XDXDXDXDX` @ DXFXFXDXDX' HX( 4 3 4 ) FXDX` 6 FX' GX2 2 FXDX` 6 6 DXDXDXDXDX` 5 DX] FXGXFX` 5 5 DXDXFX5 ' FX` DX5 FXGX2 GX' FX6 FX5 HX( 2 6 6 HX2 GX2 FXFXGXGXGX) 1 1 A KXq u u 1 A y u ( HX( 2 FX2 4 FXDXJX3 2 ( ) ( JXu S 2 FX5 DX6 q q ( 6 ' FX5 6 3 3 ( ' FXGX2 2 GX6 / GX6 GX/ 2 2 2 HX6 / 2 GX2 / / ) 4 4 ) 3 S S ) 4 u V.m.m.B.V.V.V.m.b.b.n.n.n.n.c.w.y r r r y y y r r k I.B.m.V.Y.C.m.c.n.w.c.l.l.v.c.v.v.c.v.v.c.r y q q A q q c q q q q q q c q q q q y y y y y q q d.*.Y O.+.&.*.3.*.7.&.*.&.4.X.} ..u 4 u u u c q c c c u c u S c q q j S 1 c q q A q dXsXfXpXkXkXkXzXtXB.3.9.S.T 9.7.i.7.3.*.*.....E &.7.+. S S * q q q c c c u c S 4 x x u ;XgXxXfXsXzXpXgX9.+.| 9.9.7.p.*.4.5.5.5...Y ..&.K .>.>.f.u y r y q r q y q q A 1 u c 1 S > 3 HX3 c j x 3 ( : hXsXzXd.@.&.&.&.8.=...4...&.*.&.d.E *.+.l wXsXfXdXD D #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X_.mX#XSX#XSX_.SXSX_.mX#XmX#XSX_.mXSXmX_.mXSXSX_.SXSX$X$XSXSXSX$X$XDX$XSXSXDXDXDXDX$X$XSXSXSXSX$X$XSXSXDXSX$X8 `.] SX`.DXDXSXSXDXDX$X8 DXDXFX(.DXSX$X`.DXDXFXFXFXFX' FXGX( KX4 u 4 4 S # ` DXFXGX' 6 2 3 ( FX5 ` ' GXDXDXDXDXFXFX5 FX5 8 SXDXFXFXFX' FX` 5 ' 6 6 6 6 5 DX` 6 GXGXFX/ # ' ' 3 JXHXGX6 GXGX2 2 u HXFXHXu y 1 A KXKXq u S 4 2 ' FX/ 4 3 2 2 JX3 3 2 3 JX( ) 3 2 6 2 4 q 4 6 / FX5 DX' 2 4 3 FX6 6 6 6 6 / # 6 GX/ HXHX3 2 GX2 HX3 2 FX(.( 3 ) u 1 1 A m.m.b.b.n.q.c.v.d.f.c.n.n.v.c.q.b.0 k q y y y r S.H.B.m.w.w.B.m.m.B.V.V.m.m.V.d.k.l.l.z.v.A q c c y y y 0 0 r q y q q q q y q c A y q 2 6 / ( 3 3 ) 4 ) + KXr r g.y e.q u u c r 0 0 k y y q A 1 c c S u u u 4 ( 3 S S HXN N m z 3 q J.3.@.&.7.7.*.5.*.&.7.&.&.=.l.E +. S c 4 2 2 JX3 2 HX2 3 JXM M & q q.+.+.+.&.=.*.3.&.&.&.&.v...K gX4XqXsXfXfXaX_ mX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#XmX#XSX#XSX_._.SXSXmX_.mX_.SX_.#XSXSXSX#X_.SX$X_.mXSX$X$X] SXSX$X$X`.$XSX$X$X`.@ (.(.DXDX$XSXSX$X`.SXSX$XDXDX`.SXDXDXDXSXSX$X5 DX$XDX] DXDXDXFXFXFXDX`.DXDXDXDX` 1XFXFX` @ ' HX) JXu 4 3 u 2 (.GX` FX2 6 ' GX3 HX5 DX8 6 HXDXDX8 `.2 2 FXFXFX' ` SXDX6 ' 6 FX5 DX` FX' / 6 FXFX5 FXFX2 3 / 5 5 6 3 ) S u 2 2 ) GX2 2 2 k r q y q u A 1 HXy r u u HX2 2 FX6 4 3 6 FXHX3 3 S HX/ S 1 ( 5 5 FXm y r u 6 6 5 5 6 6 ( 4 ( 6 6 / 2 2 2 2 2 6 6 2 3 HX3 ( HXu u 1 1 V.T.m.b.n.c.c.l.v.c.c.v.l.v.c.c.f.l.q.c.h 0 0 L k y r H.C.Y.H.S.V.V.B.B.m.m.m.m.T.c.j.M.d.r y r 0 h h 0 k k r y q q c q r y r r k r m FX2 2 2 2 2 / /.HX2 HX2 HX2 GX/ 2 2 2 ( ( 2 M c r r y y y q r r y q A 4 / 6 / 2 HX3 ( 3 ( HX( S S JXKXe.S.S ) GXS q.=.3.3.+.=.f.K xX4X4XqXeXuXgX_ ).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X% #X#X#X_.mXSX#XSXSXSXSXSXSX#XmX_.SX_.SX_.mXSXSX_.SXSX$X$XSXSX$XSXSXSXSX$X] o DXDXDXDXFXFXDX`.SXSX$XSX_.DXDX`.SXSX`.DX$XSX`.DXDX$XSXSX$XDXDX] DXDXDXDXSX$XDXDXDX@ ` FXFXDX` DXDX' GXHXu u S u 2 FXDXGXHX6 OX' ( HXFXDX`.6 M 5 DXDXDX6 5 ` FX5 DX8 @ ' FXFX' 5 DX5 FXFX6 GXFX' 5 ` 5 / ( ( 6 DXDX' 3 4 M 3 2 ( 4 4 3 HX2 1 q KXS ) 3 u y q q q q u GXHX2 3 S 4 3 HX2 ( 3 JX4 > ) 4 3 3 / 2 3 4 1 q A 6 6 ' FX5 GXJX4 ( 6 6 / 2 / ' 6 GXGX/ HX( 2 ( 2 3 S S u c e.m.V.V.T.c.f.c.l.v.c.c.v.c.n.f.v.l.l.c.k 0 L LX0 y 0 k B.V.V.V.S.S.B.m.w.w.m.m.m.d.j.z.g.r k k 0 0 0 H 0 r y y e.q c q k 0 k k r : FX2 ( 2 / 2 HX( 3 3 3 ( 2 2 6 2 3 3 3 JX3 3 3 3 3 S > 4 > M 4 c 4 3 1 1 HXGX6 GX/ 2 ( HX2 3 3 3 3 4 S 3 # # @ @ 6 # = 4 A q.&.&.*.+.xX0X4XqXsXsXqXiX_ #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.SXmX_.SXSX$XSXSXSX_.mXSX#XSXSXSXSX#XSXSXSXSXSXSX$X$X$X$XSXSX$X`.DXDXSX$XDXDXFX(.DXSXSXSXSX$X`.DX$XSX$XDXSXSXDXDXDXDX$XSX@ DXSX$XDXDXDXDXFX5 FXFXDXDX@ (.DXDXFXFXFXFX6 GX3 KXS u A 4 2 u ) @ FXFX6 2 6 ` 5 ( 4 GXDX5 ` 6 ' DX5 DX8 FX/ 6 5 FX5 DX8 DXFX6 6 6 6 FXDXFXGX( 2 2 ' 5 5 GXGX2 GX5 6 2 3 4 4 2 DXDX6 HX2 3 ( 2 u y 1 u y u u A u q y u ) 2 3 ( 2 ( 3 HX3 2 ( JXHX4 4 3 4 y q 2 GX6 DXm u u ) 6 6 6 6 6 FX2 ) 2 6 GX2 2 HX3 3 ) > 3 4 A B.B.S.C.H.n.n.V.b.l.d.v.v.v.n.l.z.d.z.d.w.1 r 0 0 r 0 0 f.v.d.f.g.w.m.m.b.b.T.S.n.X.z.f.k k k k k 0 h '.0 y y y y q y r k r q A 2 #X6 HXHX6 GX/ 2 2 2 2 3 3 3 GX6 GXGXGX/ 2 HX2 2 2 3 GXGX2 5 5 / GXGXN ' 2 3 ( HX6 6 FXGX2 2 4 u u ) 2 GXGXGX2 6 FXFX1X6 2 2 2 4 w.v.*.xXfXfXqXsXsXfXgXAXD #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmX#X#X_.mXSXSXSX$X$XSXSXSX_.SX_.SX_.mX$XSX_.SX$XSXSXSXSXSX`.DXSXSXSX$XDX$X`.DXDXDXFXFXDX`.SXSXSX$XSXSXDXDXSX$XSX$XDXDX$XDX` DX`.SXDX` DXDXDXDXDXFXDX] DXDXDXDXFXFXFX6 GXFX1X` HXJXKXu 4 u 1 2 FXFX' 2 GXGX/ 3 M ( 5 FX5 HX2 8 DXDXDX6 FXFX6 5 DX] DX' 6 6 ' 6 FX` FX6 GX6 GX6 FXDX6 / ' 3 N GX2 GX6 6 4 u GXGX/ 2 3 3 3 ( 6 / 2 ) 4 S 1 y u KXy A GXGXM 2 FX2 JX2 GXGX4 3 ( 3 HX) S S S 3 / FXN u q S 2 GX6 FXFXFX' ) 4 2 6 2 HX( 2 / 2 2 3 2 3 A V.S.S.B.m.V.C.S.H.m.l.l.v.f.c.c.d.z.z.d.g.q * S > y 0 l k v.v.c.v.v.n.b.w.w.V.T.z.j.z.l r r r k 0 0 0 0 0 r r r y y k 0 h A @ / 6 FX6 / FX' 6 GX6 2 ( 2 / 2 2 / / / 2 GX/ 2 2 2 2 / / / 2 / ' GX2 / 6 2 6 GX3 ) 4 2 ' GX4 q 1 1 q A 3 GXFX2 2 6 / / 6 ' 6 2 HX3 GX= > A 4 O X gXuXqXsXuXaX_ mX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXSX_.SX$XSXSXSXSXSXmXSX#XmXSXSXSXSX#XSX$XSXSX$XSX$XDX$XSXSX$X$X`.DXSX$X$XDXDXFXFX` 1XDX8 SXSXSX`.$XSXSX$XDXDX`.SXDXDXDXSXSXDXFXDXDX`.DX$XDX` FX(.DX(.@ FX5 DXFXDX` 5 DXFXGX2 JX1 1 1 A ( HXu 2 FXHXGX2 3 2 GXFX6 M 3 FX` 8 ' / DX5 FXDX8 ( M 2 6 FX' FXDX5 6 6 6 6 6 FX5 6 2 3 JX2 GX/ 6 6 FXGX4 4 ( 6 GX) 3 2 3 ( 6 6 HXHX2 2 4 A q A r y 4 u HX3 u u 4 3 / 3 KX( 3 3 3 S HX2 JX3 3 2 4 S A u 2 / 5 5 DX5 5 3 4 GX6 / 2 2 ' GX2 GX6 / GX) S.C.S.m.m.V.C.V.B.S.m.g.v.v.v.b.c.d.l.v.w.q A q y r r y y k v.q.n.q.v.v.n.m.v.k.j.j.h.0 k k k k k k 0 k k k k k r k 0 0 H 4 ' HXGX' ' 5 5 5 GX/ HX4 3 2 GXGX/ 6 2 2 2 2 2 ( ( 2 2 2 6 6 2 ( HX3 M 3 3 M 2 2 ) 4 4 u 4 3 u q q 1 u ) GXGXGX2 FX6 6 6 2 2 2 2 2 6 6 3 2 o ] n V N hXsXfXuXdXD ).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXmX_.SX$XSX$X$X`.SX_._.SXSXSXSX_.SX$XSXSXSX$X$XSXSX$X`.DXSXSXSX$X`.DXDX(.DXDXDX6 ' DX$XSX`.8 $XSXSX` DX`.SX$X`.DX`.SX`.DX` DXDXSXSX` DXDXFXFXFX5 DXDX`.DXDXDXFXFXFXFXDXDXFX/.KXJXKX1 u u S 6 ' FX` HX/ GX6 2 ) 3 5 ` DX# 3 FXDXDX8 GX4 6 ' FXFX5 ` SXDXGX' 6 GX6 5 FX/ GX/ HXFX' 6 5 ` ' 3 3 2 6 ' 6 ( 3 ) u 3 / ( JX( 3 ( GX1 k r k r 1 1 u HXq q 4 S 3 3 3 6 GX3 S 2 FX3 HX2 M 3 GX4 q u 6 5 5 DX5 3 A q ) GX6 6 GX' 2 4 2 2 FX6 # M S.S.V.m.B.V.m.B.S.V.m.w.n.c.c.T.n.f.c.v.q u q r k r r r k r v.v.c.c.v.v.c.n.d.X.j.X.j.k k 0 k r 0 0 k k k k k 0 0 0 0 0 k u JX3 GXGX5 DXDX5 FX6 4 u ) ( / 2 6 6 6 6 6 6 GX2 2 m 2 6 ' 6 2 3 3 ) HX2 3 4 M 4 4 3 ( 3 HX/ 2 S 4 /.3 2 6 6 6 FXDX/ 2 / 3 4 M 2 / 2 / HX6 ' 5 6 2 v v v X gXuXiX_ #XVX).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXSXSXSX$XSXSX$X$XSXSXSXSX_.mXSXSX$XSX_.SXSXSX$X$XSX$XDX`.SX`.$X$XDXDX@ $XSXDX(.FXFXFXDX$XSXSXSX$XDXDXDXSXSXDXDX8 $XDX@ DXDXSXSXDXFXDX`.DX` DXDXFXFXFXFXFXDXFXFXFX` DXDX5 5 FXGXJXy q S A q 2 FXHX) 6 GXGX2 3 2 ' DXDX/ u 6 DX` DXN GX5 FX' # ` DX' GX' FX' FX5 FXFX6 GX2 6 ' 6 5 5 6 3 3 ) 2 6 FX5 2 4 u 4 ( 3 3 JX3 ) 3 2 1 r q q 1 S A q u 1 u u 1 S 2 6 ' 2 4 4 FXDX3 ( HX4 ( GXKXS HX2 6 5 2 S q r q 3 6 6 ' FX6 ( XX( 3 6 GXGX( S.V.m.b.B.V.S.H.Y.B.n.m.T.b.w.B.v.k.l.k.0 y k 0 k r y y q 1 1 I.v.v.c.c.v.c.v.k.X.X.0 r 0 0 0 r k k r k r k k k k r q 4 JXu A u 3 GX6 / 4 1 S 4 KX3 ) 2 GX/ 6 FX' 6 6 2 2 ' 6 2 GX6 6 6 GX/ 2 2 FXDXFXFXGX2 2 / 2 6 FX6 / / 3 ( 3 ) JX2 6 ` 5 ( 4 4 S u 4 FXDX6 / 6 6 6 / 6 GX/ 2 m v v ;XjX_ #XDX5 SX@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.SXSXSX$X] o `.$X$XSX#XSXSX$XSXSXSXSXSX_.SXSX$XSXSX$XSX`.DXDXSX$X`.DX`.DXDXDXFXFXFXDXDX$XSX`.8 `.`.SX`.DXDX$X`.DXDXDX`.SXDXFXDX] SXDXFXDXDX` 5 FXOX5 DXDXDXDXFXFX' FX' GX/ 2 JX4 1 1 q q 4 1 q 2 FX6 FXHX( 2 FX' 3 S 2 DXFX5 6 ( 5 ` 5 ` DX6 3 6 FX6 FX` DX` FX6 2 / 6 6 FX6 / ( 3 HX3 6 FX` 2 3 ( 2 6 6 GX3 4 4 3 ( ( HX( 3 ( HXGX4 y r 1 oXr A u 4 3 1 q KX( 2 2 3 JX3 ) ) 3 M JX4 S 2 / ) S 1 q y 4 GX6 5 5 6 HXHX4 HX2 / 2 6 A.B.B.m.m.V.H.C.Y.m.n.m.m.T.B.b.k.j.j.h 0 0 0 0 r q ) 2 GXHX3 & u I.f.v.v.f.v.d.L L h k h h 0 k g.r k 0 k k k 0 u ' 2 JXS u 1 A 4 3 ) KX1 y q S ( ( 3 OX6 6 FX5 2 / 3 ) HX3 2 6 6 6 / 2 / 6 6 / GX6 GXFX6 6 GX6 2 HXm 3 3 3 4 S 4 S KX) 2 GX2 3 4 KX4 JX2 FXFXFX' 6 / 6 2 2 6 GX/ 2 2 2 v 2 @ @ 2 3 GXDXSXAX@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmXSX$XSX$XSX$XSX] $XSXSXSXSXSXSXSX$XSX_.mX`.SXSXSX$XDXDXDX$XSX`.`.DXDXDX`.$X`.DX(.# ' FXDXDXDXSXSXSX`.DX$XSXSX$XDXDXDX`.@ ` DXDXSXo FXFXDXDXDXFXFX5 DXDXDXFXFXFXGX' # GXGXFXDXDXHX) JX1 1 u q A / ' 6 ( 2 GXHX3 4 4 ) 6 ' 5 / 4 FXDXDXDX5 GX6 5 6 6 5 8 SX5 ' / 6 6 GX' 5 GXGX2 GX/ / ' DX6 4 HX2 / / / GX( 2 3 ( FXGXHX2 GX3 3 2 3 ) 4 4 u r y KXq u q y u 4 JX2 ) ( 6 3 4 3 OX6 3 ( XX4 FXGX3 A y S / 6 6 5 4 1 S 3 2 2 2 6 FX# C.V.B.B.B.B.V.S.S.m.B.V.B.B.k.X.2.L 0 k r q c 3 GXHXHX/ 2 ( S 3 4 k f.d...f.r 0 9XL 0 h 0 h 0 r r r r r r k r 6 FX3 KX) 4 u JX2 HXJX4 4 4 1 1 3 2 HX2 6 6 DX6 6 GX4 JX3 4 2 DXFX2 2 GX2 2 2 2 2 2 2 2 / 6 6 2 ( 2 ( 2 / 2 / 2 ( 3 3 3 3 3 3 ( 2 2 3 2 / ' 5 FXFXFX2 / 2 2 / 2 N / 2 / / 2 ' 6 6 6 2 M 3 2 FXSX@X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.SX$XSXSXSX$Xo `.DX$XSX_.SXSXSXSX$XSXSX$XSXSXSX$X`.`.SXSXDXDXo `.$X$XDXDXDXDXFXFXFXFXGXFXDXDX$X$XDXDX`.SXDXFXDXDX$X8 DXDXDX`.SXDXFX5 $XDXDXDX5 (.FXFX' GXFXDXFXFX` 5 FXFXFXFX' GXHX4 u 1 1 q A 3 u 1 6 GX2 GXm M HXGX' 6 3 ) 6 ` 5 8 ( 2 DXFXFX` 8 ' 3 3 GX6 FX' 5 5 ' 6 2 / 6 GX6 5 5 2 3 3 M 2 6 GXGX2 ' 3 4 2 HXGX2 3 ( 2 4 3 $XDX2 3 ( u 1 q q q y q S JX3 3 6 6 3 KX( 6 GXJXHXGX3 / HX) 4 4 4 2 / 6 / A q JXGX/ 2 6 FX' # HXY.;.A.R.;.T.B.B.m.T.B.B.l.1.k.z.k c c ) DX/.3 JX3 2 ( 3 4 4 u A 1 q k I.4 2 2 u k 0 h L L h k 0 H h y r k r ( 2 ( HXHX) S 4 / GX3 4 ) 4 KXu KX( 2 GXGX6 GX3 2 ( 4 ( 3 2 GXFX' 2 6 6 / 2 2 3 3 m 6 / / 6 6 GX6 / 6 (.FXFX6 GX# / 6 FX2 2 / 6 6 / N 6 3 2 FX5 DX` 6 2 6 6 6 N 2 2 2 GX6 6 2 / 6 / / 6 2 3 4 3 / DX_.VXAX#X#XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXSX$XSXSX`.o ] DX`.$X$X$XSXSXSXSXSXo $XSXSX$XSX$X$XSX$X`.DXDXSXSX`.DXDXDXFXDX$XDXFX6 FXFXDX8 ] $XSXSXDX5 DX`.SX$XDXDXDX$XDX@ (.DX] DXSX` FXDX` FXFXFX5 SXSXDXDX(.FXFXFXGX' FXFXFX6 JXoXu 1 u u q ) ' / FXDX3 / GXGX3 S 4 GX5 ` 8 u S 8 5 DXDX6 u 2 6 6 6 6 5 DXDXFX/ / 6 GX6 DXDX' HX( 4 HX6 FX` 6 6 / 3 ) 3 6 6 ( 4 3 ) S 2 6 / / HX2 2 JX1 y y y r u u oXHXS A S 4 3 HXS 4 3 3 3 4 S 4 / ( ( 3 3 HX3 u q u / 2 6 5 ` FX5 3 KX2 # # # I.l.T.g.d.f.v.k k y 1 2 GXHXHX/ 3 4 ) 6 FXGX3 ) 4 u u JX3 3 # @ / 6 8 c q r r 0 L L 0 '.F y q k y 3 ( JX4 4 4 4 KXJXHXJX2 2 JX4 S 4 ( 2 3 3 3 M u q 1 GXGX2 / ' FXFX5 5 6 6 / M S 3 2 FX6 2 6 / / 6 / GX/ 2 / 6 6 GX6 ' 6 / 6 6 / 2 2 GX5 ( u 4 6 2 2 6 3 3 2 4 u M ( 2 ' FX6 / 2 2 2 2 6 6 6 GXm 3 M 3 FX` 6 5 SXAX@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.$X$XSX$XSX$XDXDXDX`.SXSXSXSX$XSXSXSX$Xo _.SXDX`.SXSX`.$X`.DXDXDX`.`.DXDXDXDXFXFX' # ' FXDXDXSX$XDX`.DX8 $X] DXDXDX`.DX` 5 DX`.SXDX# DXSX8 FXDXDX` FXFX6 GX5 5 FXFX6 FXFX' FX5 FXGX3 1 q q A q u / ' 3 4 2 / GX2 ) 4 2 5 5 DXS u 5 5 ` DX3 2 `.6 6 ' FX5 8 DX6 2 6 GX6 5 DX5 FXGXHX2 ' 5 ' 5 FX6 3 3 3 GX' 6 6 HX4 u u ( 2 4 HX# ) 3 6 y 0 r r l y u u u KXy 1 u u 2 4 JX6 / JX4 3 / GX2 o ( 4 3 4 ) q 1 ( 6 FXDX6 2 u A 4 2 2 ( @ S l.c...%.M.k 1 c q 4 JX4 JX( ( 3 3 3 GXGXOX3 JX( 4 3 2 ( HXGX2 3 6 6 S u u > q k * 5 # 1 y y 1 q u 2 3 6 DXGXS KX( HX( FX6 HX( 3 JX3 3 HXJX4 4 1 y 1 2 2 2 6 5 5 ` 8 ` / 6 GX3 ) 4 GXFX2 2 6 2 2 / 2 2 2 2 2 GXN / 6 / 2 3 ( ( 3 3 ( 3 3 3 4 S 4 A 4 2 ( 3 u u S 3 GXGX# 6 ' 5 ' / 2 2 / GX6 N 2 2 2 ( 2 / / 2 ( 2 FX#X@XAXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX$X] SX$X$X`.`.DXDX$X$XSXSXSX$XSX$X] SX_.$XDXSX$XDXSXDX@ DX$XSXSXDXDXDXDXDXDXDXDXFXGXGXFXDXDXDXDXDX$XSX`.DXDXSX8 `.DXDXDX8 DXFXFXDX`.8 DXFXDX5 FX5 OXGXFXDXDXFXFXFXFX' GX6 GX2 HX3 ) u A q y A 4 q q / 6 GXFX2 3 ( ' 5 / u u 6 FX5 5 2 2 5 FX' 5 DXDXFX6 / ' 6 6 5 ` ' 6 6 2 2 6 6 ' 5 GX/ 2 ) 3 3 FXDX5 GX3 M ) 3 3 4 u ) 3 S 4 ( 1 r y r r q 1 q 1 oXq A 1 u HX( 6 5 3 S 4 3 2 3 3 2 3 S 4 JX4 u 4 ) 6 5 ' 4 A r y 4 GX2 6 5 5 A w.I.X.k.q q y q u 4 4 S 4 ) HX2 ( 3 HX2 3 ( 3 3 2 HX2 / 2 2 6 ' S u 3 3 1 A > 2 2 ) 3 4 KX/.q y KXGX4 q q ) 3 2 3 2 GX2 3 XXOX3 u HXFXHX) 3 S q 1 ( 2 / ' 6 GX` FXGX6 FX2 HX3 3 6 6 2 ' 6 6 2 2 2 2 2 2 2 m 2 DXDX' 6 / 2 3 3 2 3 3 4 ) 3 3 2 HX2 2 2 2 3 3 2 GX6 6 6 5 DX6 2 6 6 2 2 2 / 6 2 2 ' 6 6 FX6 / 2 M > 3 FX#X@XAX#XVX).VXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.o $XSXSX$XDXDXDXDXDX$XSXSXSX$XSX$XSXSXDXDXSXSX$XDXDX`.$X$XDXDX`.DXDX`.DXDXDX1XFXFXFX5 FXFX5 DXSXSX$XDXDXDXSX`.DXDX@ (.DX` FX5 ` o SXDX' FXDXDXDX` 5 FX` FX(.FX(.FXGXGX6 GX( GXFXDXFX3 JXu q 1 q y u / 6 FX2 3 2 HX2 3 S u 3 FX6 5 ( S 5 DX5 DX8 FXm GX' FX5 FXDX8 FX6 2 2 GXGX/ 6 DXGX( 3 HX2 2 ' 5 ' 6 GX3 2 6 6 6 3 u 4 4 ) 3 / GX4 u 2 3 S 1 q y q 1 u S u 3 OXu q u 4 ( HX3 HX( JXKX4 ) 4 ) 4 4 2 6 u 1 u q r 1 GX6 6 FX5 DX# O q k y q q A 1 S 3 3 ) 3 3 2 ( ) 2 / 3 HX3 ( 2 2 6 ` GX2 2 3 S S 3 2 3 3 3 ( 3 S S 4 4 HXoXy q HXh ; h 2 3 3 ) ( HX( 3 3 3 4 4 OX/ 4 3 3 3 ( KXS 4 2 2 ( 2 4 A A u u 4 2 HX3 / 2 6 5 6 6 6 6 2 3 m 6 2 ( 6 ` 5 6 GXDXFX/ 6 GX/ 2 2 2 ( 2 FXFX2 / / 6 / 2 3 3 HX6 FXDX5 / ) 3 ) 4 4 2 6 GX' ' 6 6 ' 6 6 6 / 2 ( M S 3 DX#X#XDXFXDX$X#X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.#XSX$XSX$X`.$X`.DXDX$X`.`.SXSXSX$XSXDX`.$XSX$XDXSX$X8 $XDXDXDXDX$X$XDXDX@ (.FXDX$XDXFX' GXFXDX] DXDXDXDXSXDXGX(.DX8 `.DXDXDXDXSX8 FXFXDXDX` DXDXDXFX6 / # FX@ ` ' FXDXFXFX` FXFXFXGX( ( KXq y q y 1 ( u A 3 GX3 ( 3 4 4 3 6 6 6 > 1 / DX` DXDX6 6 FX6 6 5 DX] DX6 ( 2 6 / 6 FXFXFX6 2 HX/ GX6 FXDX6 FX1X2 GX6 / FXGX4 ) 3 4 GXDX2 3 / GX3 2 q k q 1 q r q 1 A KXq y S u JX2 3 ( GX2 4 3 3 2 3 4 KX3 4 S 3 ( u r q 2 GX/ 6 ' 3 4 ) ( q y q q 1 u S ) 4 3 2 / 2 3 ( HX2 ( ( 3 ( ( 2 GXGX6 ( 3 4 4 S 4 ( 6 GX2 2 2 3 4 ( 4 KXJXu u u y ,.h / S KX4 3 3 HX2 2 ( 4 3 HX3 3 / 2 JX4 4 S 1 u 3 3 3 4 u q y A 3 FX/ ) HX6 ' FX` 2 / 2 ( 3 3 ( 2 6 FX6 6 6 6 GX6 GX6 6 / GXFX6 / 2 2 2 2 2 3 2 3 3 M ) 4 3 / / HX2 3 S 4 ) 3 6 FX6 5 6 / 6 6 6 N 6 GX6 6 2 2 > 4 ( 6 6 2 m m 2 FXSX@X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXSX$X] o SXDX` DXDXDXSXSX$XSXSX$X$XSXSXDX$XSXDXDXo `.DX$XSXDXDXDXDX` DXDXDX$X@ (.6 GXGX/ FXo DX] $XSXDX5 @ DX`.SXDX(.DX] DXFXFXFX` DXDXSXFXGX5 FX6 GX6 FX@ ` @ DXFX@ FX6 ' GX2 FXDXFX( 1 S 1 q q q q 1 ' / HX6 2 M 2 / / 3 S u 3 FX5 5 ' 2 FX5 5 5 DXDX3 2 ( 2 6 6 GXFXDX' / GX2 6 6 6 FX5 ` 6 ) 4 ) 2 2 2 ( 6 6 / 4 1 3 6 HXHX3 3 ) 2 1 y HX2 JXu q 1 y 1 1 k q 4 3 3 ( 2 ' 3 4 ) 2 GX( 4 ) JX3 3 3 4 1 S 1 3 2 2 DX2 y q HXS q y y q A u u q 1 4 / 6 2 HX( 2 HX2 2 2 2 2 2 2 6 GX2 HX3 M ) 3 GX6 / / 6 / 3 3 2 S A u 4 4 S 2 r 0 S JXJXu u 3 6 5 5 FXHX( 3 3 GX# FX3 4 3 JXS 3 HX( HX2 3 u 1 q 4 GX3 2 / 6 6 DXDX' 2 3 3 4 4 3 2 6 6 6 / / 2 2 6 6 / 6 / 2 6 ] FX6 2 ( 2 3 2 2 ( 3 3 3 3 ) M 3 3 ( 3 M 2 3 3 GX6 FXFXFX5 6 6 / 2 2 2 GX6 6 2 2 2 2 N FXDXFX/ 3 > m 6 DX#X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#XSX`.$X8 `.DXDXDXDXDX$X`.$XSXSXSX$X$XDX$XSXSX`.DX$X$X`.DXDX(.FXDXSX$XDX` DX(.DXDXDX@ ' GX6 FXDXo `.DXDXDXDXSXDXFXFXDXDXDX` FXFX` DXSX5 GX5 `.DXFXFX` DX6 2 6 GX' FXFXGXGXGXFXDXDXFX5 6 HX) y r q q y q ( 6 5 4 4 2 HX/ 3 S 4 2 5 5 FX6 4 2 DX` DXDXS S FX6 GX6 ' 5 5 8 FX2 2 / GX/ 6 5 FX6 GX3 3 4 M 6 6 / 6 2 HX3 S 3 2 6 ( 4 4 3 3 3 / 6 / GXHX3 S q y y q q u ) u 4 3 u 1 S 4 2 HX3 4 JX( 3 3 4 u 3 2 KX3 / 2 2 u q q ) u A q A c 1 c y y HX2 6 GX2 2 2 3 ( 6 GX6 GX/ ( ( ( HX/ ( 2 HX2 / / 2 GX6 2 2 3 3 ) 4 4 u 4 3 2 6 5 3 1 3 HXKX1 ( 3 y [.0 3 HX) JXm FX1XHX3 HX3 3 / GX2 2 3 4 ) ) 1 u 2 2 HX2 6 5 FX3 ( 3 ( HX3 / FX6 6 6 2 / = 2 2 / 6 FX/ 2 2 5 DX' ' GX2 / FXDXGX2 6 GX6 2 2 2 2 / 2 2 6 6 6 2 N 6 FX5 ` 5 5 / 6 6 2 2 / 2 m ( 6 ' 6 ' 6 5 FX6 6 2 3 4 > ( 5 #XVX).VXAXVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXSX$X$XSX`.DXDXDXDX5 `.SXSXSX`.SX$X] SXSXDXDX] SXDXDXDXFXDX$XDXDXDXDX@ 5 DX$XDX` DXFX2 2 GXFXDXDXDXDXDXSXDXFXDXDXSX`.DXDX` DX8 ` OXFXDXDX8 DXFXFXFXFXFX6 HX' 5 DXFXFXFXFX' 6 GXGX/ 3 3 1 A q q y r y 4 1 y u 6 2 2 GX4 4 ( FX5 6 3 A 3 DX5 ` 5 4 2 5 6 6 6 ' ` DX8 6 2 6 6 / 6 FXFX6 6 / ' FXHX2 ' FX6 FX/ 3 / 2 HX6 6 ( ) 3 ) u u 2 ( 3 HX4 2 3 0 r y y S S S A y 1 3 2 GX6 GX/ 2 GX/ 3 GX6 6 3 2 FX3 2 GX2 2 2 2 2 GX6 ' 6 ( 3 3 4 4 ) 2 ( 3 2 ' 6 6 5 3 S KXu KXu A r k 0 1 ) 4 1 4 2 ( 3 3 ( 3 3 4 ( HX2 HX2 ( 3 3 4 ) 2 3 3 GX6 S q q S GX/ 2 5 FX6 FX6 6 ' 6 6 N 3 GX' 3 / ' ' 6 6 6 6 6 6 FXFXFX6 6 ' DXFX/ 6 / 6 6 GX6 GXN 6 6 / 2 6 FX8 (.6 6 / 4 S > ( 2 6 GX' 6 6 / / N GX6 N 2 2 2 3 M ( 6 DXDX' 5 #X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX`.$XDXDXDXDX(.@ `.$XDXDXSXSX$XSX$XDX`.$XSX`.DXDXDX`.o ` FX` DX`.DXDX` @ FXFXGXFXOX6 2 HX' ` 8 $X8 DXDXDXDXSXDX` DXFXDXDX5 FXFX5 DXSXDX6 6 FXDXDXGX6 ' FXDX5 DXGXFXFX2 / GXHX3 HXFXFXGXu 1 1 y q q y y ) 6 / 5 2 S 3 2 2 m S A 4 5 5 6 ' 2 2 ' FXFX5 5 DX6 2 / GX6 ' 5 5 DX` 6 / GX2 ( 2 GX6 ' 5 6 2 3 3 ( 6 6 2 6 2 HXS 1 u HXJXS 4 KX3 / q h k k k q u A q .Xq q u u S JXM / ` 2 KXHX3 6 OX) 3 3 3 OXOXGX1 y u 1 S 4 > S A y y u JX2 2 6 6 6 ' 2 S 1 3 6 ' 2 FXDX2 2 2 2 / 2 HX2 / 6 6 / 2 GX/ 3 3 ( 2 2 2 GX6 6 6 ' 3 1 1 1 1 1 JX(.6 2 u 4 ( u u GX2 2 ' 6 2 4 JXHXHX( FXGX3 3 3 JX3 2 ) 4 3 4 u u q 4 6 2 2 GX6 FX' 5 DX5 5 ' 3 u 4 ) 2 FX6 GX6 GX6 / 6 6 6 N 6 / 6 6 6 2 6 / 2 2 / 2 2 2 2 ( : HX4 3 3 ( # / 4 S S 4 ( 6 ' 2 6 5 6 6 6 2 2 2 6 FX6 FX6 6 2 3 2 / 2 2 2 6 DXAX@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXo `.DX`.DXDXFXDXDX5 `.SXSX$X$X`.DXDXSXSXDX$XSXDXDXDX`.DXFXDX`.DXDXDXFXFX' ' DX`.@ OX2 2 6 FXDXDXDXDXDXDXSX6 / FX` DXDXDXDX5 ` DX] FXGX' DXDX5 FXFXFXFX/ 6 GX3 FXFXGXGX6 ' GXGXFX' FX/ ) KXA y y q r r 4 2 4 u 3 2 JX) 3 u u u GX6 6 6 : 4 ' 5 5 5 DXGX> / 6 6 / 6 5 DX` 2 2 6 2 3 2 6 6 GX6 / 3 ( 4 ) 2 ' 6 GX' 3 JX( 2 2 2 3 u S 4 4 4 HXu q q S 4 KX1 A q 1 1 y 1 u ) HX2 & A u 2 3 GX2 4 JX4 ) 3 3 3 A KX4 q u u S q y y r y 3 2 2 6 ' 6 6 3 S 3 4 6 6 / GX2 2 HX( 2 GX6 6 6 2 HX2 2 ( ( GXFX( 2 GX2 GX6 2 2 3 S u 4 m u 1 ) FX@ 2 4 4 3 oXu u ) GXGX/ 2 KX3 GX2 4 ( @ OX2 HX( 3 3 3 2 2 3 ) 3 u q 1 3 2 2 / ' 5 5 8 ] 8 DX3 A 1 S 3 6 ' 6 6 / 6 2 2 6 / 2 2 / 6 6 6 / 6 6 / 2 ( ( 3 M 3 3 ) 4 4 4 ( 3 4 2 2 4 3 2 2 FXFXGX2 ' ' 5 FX6 6 2 2 DXFXN 6 2 2 / 6 FX6 6 6 6 m 3 2 FX#X@XVX#X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXDXDX`.DXDXDX` (.DX$X`.`.SXSX$XSX$X`.DXSXSX`.DXDXSXDXFX`.DXDXFX(.FXDXDXDX(.@ ` ' GXHXHX2 / 5 DX`.SX$X8 DXFXDXDX] $XDX5 FXDXDXFXFX6 (.o ` `.DXGX' FX6 GX/ GX' 8 `.6 (.FXFX6 # 6 / 2 2 / 3 KX1 q q r q S y r ) GX3 3 2 3 > 3 ( 2 6 2 S u 6 ` 5 DX5 3 2 FX6 6 FX5 DX8 FXS 2 6 ( 2 / 6 ' 6 6 2 2 2 ( GX6 / GX` 2 4 / 6 / 6 FX6 JX4 JX4 ) ( GX2 3 ( ( / 1 y y r y l y u 1 HXKXr y 4 4 4 3 3 3 ( 3 ) 4 KX4 2 3 JX4 A q c u 4 u r k 3 / 6 ' 5 6 GX2 HX) S 2 GX/ 6 GX/ 2 2 2 6 FX6 GXFX2 3 / 2 2 6 GX2 2 2 6 FX6 2 3 4 4 4 ( 6 2 3 3 3 ) ) ) 4 4 KXKXu q 4 1 0 h r GXHX4 1 ( 6 2 3 3 3 3 4 ( GXHXJX3 JX4 ) S 4 ( GX6 6 ' 5 GX3 4 ) S 1 S ) / ' 6 / 6 ' 6 6 / 2 2 m 2 / 6 / 2 6 FXFX6 / 2 2 m 2 2 2 2 2 m HX3 2 2 2 / / / 2 2 DXGX3 2 FX5 8 ' 6 ' : 4 3 M GXFXFX/ 6 6 6 N 6 ' 6 / 2 3 > ( ' `.@XVX#XAX#XAX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX$XDX`.SXDX(.@ ` 5 FXDX$XSXSXDX`.DXDX`.SXSXDX1X$XDX@ DXDXOXFXDXDXDX$X@ FX(.@ FXFXFXFXGXHX2 ' FXDXSX` DXDX` DXDX8 FXFX5 DXDXFX5 FX5 DX8 8 ' GX5 DXDXGXFX5 FX5 FXGX6 ' FX' 6 GX2 / FXFX' 5 GXJXKXq y q A r q 3 / 2 FX6 S ( HX2 ( S u u 2 FX5 5 6 M 6 5 ' 5 DXDX6 2 3 4 6 / 2 6 6 6 FX6 GXGX2 ( 6 6 6 2 5 DX2 JX2 / 2 / 6 / 2 6 4 1 3 2 2 3 3 3 JX2 3 h r JXKXq y 1 A A 1 q y q S ) HX3 ( / 6 3 3 4 ( ' JXHXGXHXu 4 HX) 4 q y 4 / / GXFX' S 1 4 3 HX2 / 6 6 6 ' ' ' / 2 6 2 / FX/ 2 2 2 / 6 2 2 2 / 5 FX6 GX/ ( 3 S 4 3 2 FXFX2 2 2 2 3 3 4 KX) u u u l N.r 6 ) S KX2 HX3 HX3 4 S JXGX( 4 ( ' 2 ( 3 S S S 3 ( 3 3 4 u 1 A y 1 4 3 2 6 6 / 2 ' 5 5 5 ' 3 4 3 2 ' = 3 / ' FX6 6 ' ' 2 GXFXGXGX6 GXGX6 GX6 6 6 6 2 / / 2 3 4 ) 2 6 6 # GXM ) 4 u u 2 ' DX5 ' ' 6 6 6 6 6 GX6 6 ( 3 3 4 > 6 SX#XDX' FX5 #X@XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXDX`.DXDXDX` FXFXDXSX$XDXDXSXSX`.SX`.(.DXDX$XDXDX5 FXDX$XDX5 (.DXDX@ ` DXDXDX` FX6 HX) 3 GX5 (.5 DXDX`.$XDXFX5 DX`.DXDX` FX5 DXDXFXGXFXDX8 DXFXFX5 FX2 GX2 3 GX' FX' 6 GX6 6 / GXGX6 / 3 KXr r y y r y S 2 3 A 1 2 3 ( 3 4 S u 2 ' FX6 N u 3 DX5 DX8 6 S 1 M 6 GX2 2 ' FX5 DXFX6 m 2 2 / / GXFX6 2 3 3 ) 3 2 # 2 2 GX6 3 u 4 2 2 2 JX4 S 3 2 q 4 AX# ( 4 u u q q 1 r r u ) HXHXHX2 3 ) JX4 GX2 4 ) JX( ( 3 ) 4 u 4 3 u 3 / 2 ' 2 r q 3 2 6 / 6 6 6 FXFX/ 3 ) 4 / GX6 6 2 2 2 2 2 2 2 ' ' 6 / 6 ' 6 GX3 ) 3 ) 2 6 FX6 / 6 6 2 2 m 1 1 ) JX) 3 1 L l 6 JXKX4 4 ) 6 ` DX' 4 / DXHX4 FXDX/ 3 4 HXHX4 4 HXOXGXJX3 ) KXS u 4 ( 2 / 2 2 6 FXDXFX2 / ) 4 4 4 3 m / ' 6 5 ' 6 6 6 GX6 6 / 6 6 6 / / 6 / / / 2 ( 3 2 ( 3 M 4 3 HX3 4 2 4 3 3 3 2 FX' 6 ' 5 ' FX6 6 6 N 6 / 6 2 2 2 2 ( 3 3 6 6 2 m 3 2 5 $XAX@X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X$X`.DXDXDXDXDXFXFXDXFX` ] $XSXo `.DXDXDX`.SXDX` $XDXDX`.DX(.@ (.DX] DXDX(.FXFX# / 6 GX/ HXJX2 FXDX8 SX8 DX(.` DX8 DX` DXFXFXDX5 ' 6 FX` DX] FX6 FX' FX5 ' 2 6 6 DXFXFXGXGX' GXHX2 2 3 4 ) JXu A q y r r 1 q k y 2 2 2 GX3 S 4 M FX5 2 4 q S 5 5 ` 5 6 u u 6 FX6 2 6 6 DX` FX6 / HX/ 6 6 2 5 DXGX2 ( JX4 ( 6 FX6 / 2 3 3 / 2 2 2 2 u 4 3 4 u 2 FXHX) JXM GXq l y y 1 r q u u OXu q A u ) u ( HX4 KX) 3 3 ) 4 u 4 2 3 4 ( 2 ( 6 4 q q 4 / 6 GXGXFXDX' 5 3 S 4 3 6 / 6 2 2 GX/ / 2 2 ' FX5 2 2 2 / 2 m 3 GXFX2 / 6 ' 6 6 / m ( ( M S S 4 3 3 3 2 > 1 S 3 HXKX1 4 2 u u u 3 GXGXJX4 6 GXHX( GXFX2 ) 2 GXFXFX2 3 4 S S S ( ( ( 2 2 / 6 5 5 / FX3 S 3 4 2 GXGX6 6 5 5 ' 6 6 6 6 / 2 2 N / 6 ' 6 6 2 2 2 2 3 2 2 2 2 ( 3 3 3 3 3 ( ( 3 3 2 / 2 2 2 5 5 5 5 ' 5 6 / 6 2 2 / 6 N 2 6 6 / 6 FX6 6 / 2 3 3 2 FXDX#X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmX`.DXDXDXDX` 5 5 FXFXDXSXSX`.8 DXDXDX$XSX(.DXSXDX` DXDXFXDXFXDXDXDX` @ FXFX' GX(.$XDX6 2 3 HXGXDXDXDX5 FX` `.SXGX2 FXFX` DXFXFXFXFX5 ] $X' GX6 5 5 FXFXFXFXFX/ 2 GXGX6 GX2 2 2 HX( JX/ FXFXFX) 4 1 y y y r r u 2 2 / 6 3 4 M 3 2 M 1 A u 6 ' 6 6 ' 4 ) ' 6 6 ' FXDX/ > 3 / 2 2 GXGX6 5 FXFXGX2 2 3 2 6 ' FX' ' 3 ) 3 2 2 (.@ / 3 2 JX1 q 4 ( 4 4 JX4 6 1 '.k y y k r 1 A 1 u A r 1 S 1 JX( 4 4 / 6 3 S S 4 ( HX( GXHXu 4 2 S S y 1 2 GX/ ' 8 5 3 / S KX2 / / 6 GX2 / 6 5 5 5 ` FX6 / 3 2 2 2 GX/ 2 FX6 / 2 2 DXDXFX6 2 3 ) 4 3 2 ( 3 2 FXDX` 5 M 4 JX( u u KXr L L r GX4 u 4 ( 2 2 HX3 2 ( 3 2 2 GXHX3 3 ( 3 4 4 4 ( 2 2 HX2 6 ` 2 ) > u 4 3 3 `.mX6 / FX6 / 6 6 5 5 5 5 ' 6 / 2 6 5 FX' 6 6 GX/ 2 6 GX/ / 2 2 GX/ GX' 6 / / / 2 2 2 2 / GX5 DXDXDX5 2 GXGX4 M 2 / GX/ 6 6 FXFX6 FX6 ' DX' 2 3 > M 2 FXSX@XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X$XDXDXDX`.DXFX5 FXFXDXFXDX$X$X] `.DXDX@ DXSX$X5 (.DXDXDX`.DXDXFXOXFX` DXDXFXFX` FXGX/ HX( 3 3 ' DXDXDXDX8 DX' GXFX5 DXDXDX` 5 ` DX8 FX6 GX(.DXFXDX5 FX6 GX( ( 2 2 GX6 DX6 GXDXGX' FXGX6 6 2 ) S u y k r r r A 3 3 M S 3 2 S 4 4 u S u 2 6 / 6 2 u 3 6 5 ' 5 5 5 M 4 6 / 2 6 6 6 5 SX5 / 6 2 3 ( 2 6 FX' 6 2 3 ) 4 3 2 DXFX6 6 JXS u 4 3 ( 4 u S 4 4 2 1 k k k r 1 u q q 1 A q KXu u 4 3 ( 6 DX( 1 S S 3 2 3 3 2 HXS 4 4 4 u q u 3 / 5 5 ] S q q y 3 @ / 6 6 6 6 6 FX2 3 3 2 6 FXFX2 / / / GX/ 2 2 2 / 6 GXDXDXDXDXGX3 3 M JX2 6 ( / 5 FX2 ' 6 S u 4 3 KX1 4 1 q 1 4 u ) S 4 / 2 ( 2 6 3 ( ) JX( ( 2 GX6 3 3 2 3 3 2 3 HX/ 6 HX4 A q 4 2 HX2 5 FX6 FX5 6 ' 5 6 ( ( 3 ( 6 5 / 6 6 6 6 6 6 GXFX6 / 6 6 6 6 6 6 6 6 6 FX6 6 6 6 6 6 2 6 5 3 2 ' 6 6 HX3 4 u 1 4 ( 6 GX6 2 6 5 6 6 6 6 6 5 ' 2 2 2 3 M > 3 / DX#X#XAXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#XAX#X#X#XDXDXDXDXFXDXFXFX6 ' 8 SXSXDXDXDXDXDX] SXDXFXDX`.DX@ DXFX# (.DXDX`.DX5 FXFXFXFXFXFXFXGXHXHXGX6 FXDX`.DX5 ` FX5 DX8 FX' FXDXDX5 ' GX6 5 FX` $X` 2 GXFX5 GX/ GX6 FXDX6 FXDXGXFXGX/ GX2 3 3 FXFXHX1 q q y y A q r y 2 2 S 3 3 4 S 4 GX/ 6 6 S A u 2 FXFX5 5 ' 3 6 6 2 / 6 ' ` SX3 4 6 6 2 ( / 6 / 6 DXGX/ @ 4 ) 2 6 6 6 6 2 ) ( 6 2 / ' 3 1 u 4 4 3 / 3 u 1 4 3 HXu y y q .Xq q u S KX3 ( 4 q 1 JX4 / 2 3 ) HX3 ) 4 S KX3 JXS S 6 FXDX: y q y r 4 GX2 2 6 FX' ' 6 4 4 S 4 6 DX5 6 / 2 2 / 2 / 2 2 FXFX6 6 / 2 / 3 3 2 ( 2 6 2 / 6 6 6 / 2 3 u S M u u 4 HX6 6 2 S JX2 S 1 HX6 FXSXDX6 2 ) JX3 GX2 6 2 HX' OX3 ) M 4 ( 3 3 4 S 1 A 3 6 2 2 ' 6 ' 5 FXDX8 FXN 4 4 HXu S 2 6 6 6 ' 6 6 6 6 6 6 6 / 6 / 6 GX6 6 / / 2 / 6 6 ' 6 2 6 ' 6 ( 3 4 ) 6 3 u u u S M GX' GX2 / FX6 5 ' 6 6 ' 6 6 6 6 6 2 / GXm > m 6 / ` #X).VXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#XDXDXDX(.5 DX` ' GX@ DXDX` DX$X`.DX`.SX(.FXDXDXSXDX' FXFXDXDX@ (.@ (.DX5 FXDXDXDXFXFX' HX4 3 2 ' DX` 5 DX5 DX] DX( GXFXDXDX` FXFX6 FXDX8 5 GX/ FXDXDX6 ' FX5 GX) ( 2 2 6 ' 6 2 2 3 2 FXDXFXFX6 ( 4 A k k y q r q 2 / 3 6 2 S M 2 3 2 M u c q ( 6 ' 5 ] 3 q FX6 / 6 ' 5 FX2 y 1 ' / 2 2 6 ' 6 6 FX6 6 GX( 2 / GX/ FXN HX1X6 2 2 GX5 FX4 S ) ) HXGXGX2 HX) JX2 4 y y y y k r q u q q q y y u 4 JX2 ( ) 3 3 ( 3 S 4 4 HX2 4 S 3 N 2 u 1 u u r q 2 2 / 6 FX5 6 2 HX) S 3 5 FX6 / 2 2 / / 6 6 6 6 FX' 2 2 2 FXFX( / / 2 GX6 GX6 6 ' / 2 4 u u 3 2 u 1 ) 2 ( 3 S 4 3 JXKXu u 2 3 r r y S / GXHX2 2 GX2 2 2 HX3 3 S HXGXJXKX4 3 3 u u 2 ( 2 GX6 5 5 DXDXFX6 ' u ) 2 ) 4 / ' 6 6 6 GX6 6 5 5 ' 6 N 2 6 6 6 N / 6 6 2 2 6 / / 2 3 3 > 4 3 ( HX3 HXS 4 FX2 2 6 ' FX6 / 6 5 5 ` ' 6 2 3 3 2 N 6 6 6 6 2 / (.FX/ 6 2 / 6 DX#X@X@X#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X`.@ ` DXDXFX' FXFX6 FXDX`.SXDXDXo ` @ DX`.SXDXFX8 DX` DX` FX6 FXDXDX`.DX5 FXFXFX2 ( 2 GX/ 3 HX6 FXFXDXDXDXDX5 5 ` DX8 DXDX5 FX5 DX5 GX/ 6 5 ` DX5 GX6 ' / 2 ' 3 JXFXFX5 GX2 GX6 FX/ GX2 2 m 4 4 r k k y r l r 4 2 GX4 1 2 3 3 2 4 u S S 2 / 6 5 DXq r 6 5 FX5 DX6 1 q S 6 / 2 2 GX6 FX5 GX6 / 3 3 GX6 6 2 6 ` GX3 ( HX3 ( 2 2 / 6 2 3 1 S OXGX3 ( 4 ) 3 2 y h A JX4 u q 1 A y 1 q k y S JX/.2 3 ( 6 6 4 4 ) ( FX2 ) 3 3 3 u 3 GX2 S y q ) 2 / 6 ' DXM 1 ( 3 JX3 ' 6 6 6 6 6 6 6 ' 6 5 ' / 2 / ( 2 DX' 2 GX2 2 2 / 6 ' FX6 2 3 3 ) 4 4 2 2 2 2 2 3 ) 4 M 4 3 /.KXA KX1 h N.0 4 3 HX4 3 2 / 2 3 JXM 3 4 4 / GXHXJX3 ( ( 3 3 KXS 6 2 ( 6 FX6 ( S S S u u 4 3 2 6 6 FXGX/ 6 / 2 / N 2 ' 5 FX6 6 6 / 6 ' 6 / 2 ( 2 3 3 m 3 4 4 4 3 2 2 3 3 ( ' 6 2 ( HX2 2 ' ` ` DX' 6 2 4 1 u M GX6 2 / / / 5 DX6 6 6 6 m M 3 2 6 DX@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X$XDXDX(.@ DXFXFXFX6 DX$XSXDXDX`.DXDXDXSX`.FX`.SXDX(.DX` FXFXFXDXDXDX(.@ FX' GX3 GXSXDXGX/ 3 ) / 6 DX8 DX` FX5 DXDX`.2 6 FX' DXDX5 6 GX6 FXDXSX5 / GX2 6 DXFXHX2 6 ' DXFXDXFXHX6 / ( 2 HX4 S 4 M M S y y y r r u 1 r y m 2 3 ( 2 u 4 4 S 2 5 ` : q q M 5 5 5 5 6 A 4 5 6 2 2 6 6 FX8 DX2 2 HX( 2 / 6 6 6 6 2 ( M ) 4 JX6 / 3 2 / 2 3 u ) 2 6 2 ) 4 4 ) 3 4 q GX6 2 HX( KXA y 1 u r y 1 JXOXHX3 GX/ q u JX3 6 GXHX3 HXJX3 3 HXGXJXu S ) 4 3 2 6 5 5 q y 2 `.2 2 2 6 6 ' FX' 6 6 3 3 5 GX/ 6 6 2 6 / 2 6 6 / / / 6 ' 5 FX6 / 2 ( 4 S ( 2 2 FXFX6 / 2 2 2 2 3 u u 4 S ) q h r 3 JXHX4 KX2 2 HX2 3 ) 4 S 3 HXHX( 2 6 2 3 4 4 4 KX3 ( 3 2 2 3 4 1 y q u 4 2 ( 2 6 6 6 6 6 6 ' 2 4 4 4 4 3 6 5 5 / 6 5 ' 6 6 2 2 ( 2 FX' ' 6 GX2 m ( 2 2 6 6 2 6 / 3 4 S S 2 5 ` 5 6 2 S S 4 4 4 2 ' ' 6 6 FX6 2 6 ' 6 6 / 6 2 M 4 4 6 #X@X#X#XAX#XAXVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.#XDXDX`.` FXFXFXFX5 ' FXDX8 $X] DXDXDXFXDXSXSXDXFXFX$X$X5 DX` FXGX' @ DXFXFXFX(.FXFX2 3 4 4 ( 3 6 DX5 ` ` DXDX8 3 3 FXFXDXDX(.5 FX' FXDXDX' 2 2 FXDXFX6 / 6 GX6 2 2 FX3 JX6 2 3 2 3 ( 3 JXGX6 ' 2 u A q r r y y k y 2 / 2 ' 3 u 4 JX) 2 / 1 q q S ' ' ' 5 M 1 2 FX6 2 GX6 5 DX6 m 2 / 2 2 GX/ 2 GXFXGX2 3 HXHX) 2 FX' 6 6 GX3 JXGXGX2 6 6 4 4 4 S 4 S ( HX3 HXHX3 2 r r A q y y y S S 1 HX4 y q ) ) 4 ( 3 JX3 4 3 3 3 3 3 4 ) 3 2 ) 3 6 / / 4 q q 3 FX2 / 6 6 ' 5 ' 5 6 1 ) 3 6 5 6 GX/ / 2 2 2 6 ' 6 # ' 6 6 6 6 / GXGX( 3 / FX/ 6 ' 6 6 ' 5 6 2 6 3 A 1 S 3 3 : u u ) 3 ( S 1 3 2 / / HX2 4 ) 2 / 6 HX' FXHX3 JX3 ) 4 S 2 2 JX4 ) ( 4 JXHXS 3 2 3 GXGX2 / 5 5 DX5 ( M ( 4 u S S 2 / 2 ' ' 6 6 6 6 2 2 FXFX6 FXDX` DX' 6 ' 6 6 6 6 6 6 6 3 4 JX3 ( 3 2 6 4 4 GX2 3 3 2 FXFX' 5 FX' 6 6 6 / N ' 5 / 2 2 m > 2 DX#XAXDXFXFXDXAX@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XDX@ DX` FXDXFX6 GXGXDX`.SXDX` DXDXDXDX`.SXDXFX` ] 8 FX5 FX6 GXDXDXDXDXDXFX6 FX' GX/ GX2 HX4 3 6 FXFXDX8 DXDX6 6 FX` DX8 DX5 FXFX` DX' GXGX/ DXDX' DXFX2 6 / 3 HXHXM HX6 5 GX3 GX5 GX( GXGX2 2 3 u q r k r y r l q 3 3 2 4 S 3 3 S 4 3 u u q S 6 6 6 6 3 A 4 5 6 6 6 ` 5 u 1 3 GX2 2 6 ' 6 FXFX6 6 2 HX( 3 2 GX' FXFX' 6 3 3 / 2 / 6 GX2 ) HX3 1 A 4 ) 4 ) ) S / ) 0 0 y r l k 1 u q KXKXy r u 4 u 3 3 3 4 3 / 2 4 ) 3 3 3 2 3 3 2 m # 2 S S q A 2 / 6 6 6 ` DXDX8 4 A 3 HX6 GX6 ' 2 6 6 / 6 6 5 ` 5 ' 6 2 2 ( 3 2 2 3 2 6 2 2 ' 6 6 6 / 2 / 2 3 4 4 4 4 4 ( 2 6 ' N ) 4 oXu 1 ( ` 6 6 2 3 HX2 2 JX2 FXGX2 HXGX/.3 4 3 FXFXGX3 2 2 4 3 4 1 2 3 ( 6 2 2 6 FX` ` FX2 HX3 S 4 u u 3 / 6 6 FX6 6 / 2 2 2 N N 6 6 ' ' GX6 ' 6 6 GX/ 2 2 / 2 ( M 3 / 2 ( HX4 S 6 6 GX2 2 6 6 6 5 FX5 5 ' 6 6 2 2 6 6 2 / / 2 2 3 > / ' 6 6 2 2 GXFXSX).@X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#XAX#XSXDX(.FXFX` FX6 / FXDXDX` @ DX] $XDXDXSX` FXDXDX$XDXFXFX' FX`.@ (.FXFXFXFXFX6 (.@ ` 5 ' 2 ( S 3 3 6 `.` ' 5 (.FX` DX`.2 / ' FXDX5 6 FX/ 6 5 5 DX8 GX( GX' FX2 m GX6 FXSX2 ( FX6 6 GX/ GX2 JX) 2 2 3 S q y y r r A S y r 4 m 3 4 3 2 M c S 4 > / / / 2 q u ' 5 FX5 ` 2 u m ' 2 ( / 6 ' 5 8 5 / / 2 3 3 2 6 6 FX6 6 2 JX3 4 4 ( 6 6 6 6 M 4 ) S S S 3 S S 4 u 4 GX1 0 r r l r q 1 y u OXq y q q u OX2 3 ( DXFXu 4 GX( 2 GXHX3 HX3 JX(.GX( 4 r y 3 6 GX6 ` 8 5 2 S q 4 3 2 2 / 6 6 FX' FX5 FX6 ' FX6 6 2 2 FXGX2 GX6 / 6 / 2 6 6 GXFX6 2 3 3 3 S u M 2 ( 3 3 6 FX6 6 6 m JXKXu KX4 u k r 4 2 ( 3 u 3 6 2 ( ( ( 3 3 4 3 6 GX2 JXHX/ ( JX4 3 3 HX2 2 2 / 6 ' 5 3 4 3 3 JX3 4 4 3 6 ' 6 6 6 6 6 6 6 6 / 2 2 2 / 6 6 6 6 GX2 2 2 2 m 3 2 / 2 2 2 2 ( 3 2 3 3 ( ( m 2 2 2 2 FXDX5 DX' 6 ' 6 6 N / 6 6 6 6 2 2 6 6 / 6 FX' 6 2 3 M 3 GX5 DX#XVX).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X$X5 FX` 5 ' FX' FXGX/ FXDX`.SXDXDX`.FXFXDXDXSXDX' DX` DXDX5 FX' FXFX` DXFXFXFXOXFXGX( 3 4 4 ( 3 HX6 FXFX5 5 DXDXDX/ 6 FX` DX5 FX5 6 6 (.DXDX6 ( / 5 DX` 6 GX' 6 6 2 HXHX3 / 6 6 2 2 3 4 2 FXGX/ 6 2 3 u y k r u y k y 2 ( ) 3 6 6 S u S 3 ( 2 2 4 q 1 6 ' 5 ` FX4 S 5 6 2 2 6 6 DX8 GX> 6 6 2 ( 2 2 / 6 ' / 2 3 3 ) 4 2 / 6 ' / ( 4 u 3 GX2 2 FX) 1 u S 4 4 ( ( 1 q q u 4 4 A A A u XX1 y 4 JXS GXFX( S y 4 2 3 2 / ( 3 ( 3 ) 3 JX3 u 1 u 3 ( 6 5 5 ` A y y q M HX2 6 6 / 6 5 FX/ 3 4 1 4 / 6 ' GX` DX/ / 6 GX6 ' 6 / 6 2 ' DX` FX6 2 M 3 ( 3 2 6 / / ' FX6 6 5 / u u S u 1 ) u u M 3 4 JXu S / HX3 HX3 ( 3 ) 3 GX2 3 3 / GX2 M ) 3 ) ( 2 3 GX2 2 2 2 1 q A 2 ' 2 3 2 5 ' 6 FX' ' FX6 6 6 ' 6 / / 2 6 2 6 5 5 ' 6 6 / / 2 2 6 6 GXGXGX/ 6 GX2 6 / 2 2 2 2 / / 2 6 FXDX] 5 6 2 6 5 ' 2 m 2 N 2 2 6 GX6 6 6 6 6 6 6 ' 6 2 3 M 3 : ' SX@XVX#X#X#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X$XDX$XFX` DXFX' 6 GX6 DXDXDX` DXDXDXDXDX] DXFX5 SXDXFX5 DXFX# FX6 DXDX(.FX5 GXGXGX3 2 FXFX6 3 4 4 2 6 FX`.8 DX5 5 FX5 DXDXDX5 ` ' GX5 5 6 GX2 GX5 DX` ' GX6 5 HX3 / 3 4 HX/ ' ' 2 GX2 2 / ( ( HX2 2 M u r l k r r r q 3 2 / ` 3 q u 3 ( 3 3 S 1 1 A 2 6 5 5 ` q y FXGX6 ' FX5 ( N u 1 / 6 GX/ 2 6 GX6 6 6 2 HX3 3 2 / GX6 6 FX3 ) HX2 6 2 FXDX3 1 S 4 JX2 HX2 ( ( GXGX2 6 y r u y u y y S A q HXKXy q 1 4 ) 4 2 2 3 ( HX3 ) 4 4 4 ) 2 2 ) 3 / GX6 4 y A q r 1 2 2 GX6 5 ` 6 6 2 u 4 4 3 6 FX6 6 GX2 2 6 / / 6 ' FX5 GX6 6 6 / 2 2 3 HX6 6 / 6 6 / 6 6 5 6 / 2 4 u 4 u u FXDX5 6 3 ) 3 GX+ S 3 2 ( ( 6 6 2 3 3 HX3 JX/ 5 FXGX2 GX2 ) 4 3 3 HX3 ) 3 ) S 1 1 ( 6 2 3 2 6 GX5 ` 5 DX5 ' FX5 6 m m 6 ' 6 6 5 ' 6 ' 6 6 6 6 GX6 6 6 6 6 6 6 6 FX' ' 6 6 6 6 6 6 6 2 2 2 6 / 6 6 GX6 2 S u S 3 2 6 GX6 6 FX' 6 6 6 / 6 FX6 ' FX2 2 ( 3 ( 6 `.#XVX#X#XAXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X#X`.5 DXDXFX6 FX6 GX6 2 6 DXDXDXDXDXDXDXFXDX] $X5 FXFXFXDX5 FX(.5 # GXFX6 FX/ GX' FX5 ' 2 HXS u ( 2 5 DXFX5 FX6 5 DXDX( 2 5 GX6 ` FX' 6 GXGXFX` ] 5 3 6 2 / ' FX6 2 2 2 5 DX' 6 HX2 / 2 3 3 2 4 S S u q q y r r k y 4 3 u r k u 6 2 4 / S 1 u A 2 ' 5 DX2 r q 6 ' FX5 5 2 A 1 c 2 GX/ 2 2 6 FX5 5 6 GX2 ( 3 2 / 2 / / FX5 2 3 GX/ 2 ( 2 6 2 2 ( 3 3 ) HX2 2 3 GXOX) 6 A '.k q q q A q 1 1 q q q y q 1 ) 1X2 3 3 2 6 ' ( HXJX4 2 / JX3 ( 3 3 6 4 S 4 u y y 2 2 / 6 5 5 6 FX/ ) 2 4 3 5 ' 6 6 / 2 / ' 6 6 6 / ' 5 6 / 6 2 3 GX2 ( 6 6 / / 6 GX6 6 6 GX2 3 4 4 3 2 : 4 HXGXFXGX3 4 M 2 /.u 4 5 6 FX8 8 ' 3 2 2 4 4 2 FX6 2 GXFXGXJX) 3 S JX2 2 3 u 1 A u 2 2 HX2 6 GX5 DX5 DXDX' GX` 2 S 4 4 3 6 GX6 ' 6 6 6 6 6 / / 6 / 6 / 6 ' ' 6 ' 6 6 6 2 GX' GX6 GXN 6 ` 2 S q 4 5 ' 3 u u 4 4 ) 6 DX' 2 GX5 5 2 N 6 2 2 6 6 ' 6 6 / / 6 2 3 3 6 5 6 / DX#X@XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#XAXDXFX` 5 ' FXFX6 GX( 2 DXDXSXDX5 DXDX` (.DXSXDX' FXDXDXFX(.FX6 GX6 OX` SX5 FXGXGXFXGX( 3 JX) 4 4 4 ' DX5 FX5 DX] @ 3 4 GX6 FXDX5 6 6 6 6 FXDX8 GXGXHX/ DXFX6 6 GX' 6 2 2 2 HX( / GX3 3 3 4 4 S u 2 6 6 2 u 1 y k y q y k 0 y 2 / 3 GX6 S u S 2 ' 5 6 A q q m 5 5 5 5 2 u 1 2 ' 6 2 2 / GX5 DXFXGX6 / 3 2 / 6 / 2 FX6 2 ( 4 4 4 4 2 2 2 HX6 6 ) S 4 GX/ HX4 S 4 4 ) GXy k 2 GXHX) 4 S 1 y q q r r A 3 HXJX( 2 GX5 1 u 2 M 3 (.GX) ( HX3 ) ( 3 3 4 u 1 A 4 2 GX6 ' FX6 ( 4 4 3 3 / 5 FX6 GX/ / 6 FXFX` 5 FX6 6 2 GXFX/ / FX/ 2 6 GX6 6 / 6 DXFXGX2 3 ) 4 3 3 2 6 2 M GX6 HX3 4 3 4 JXJX1 u 3 ( y r q 3 HX( ) KX( GX2 ( HX( 3 3 3 S 3 GX2 HX4 4 4 4 3 2 2 2 2 2 ' 5 5 SXSX8 5 5 6 u u 4 3 S 3 FX6 ' 6 6 / 6 / 6 6 N 2 2 2 6 6 6 6 ' 6 6 GX2 2 / 2 2 2 ( 6 6 3 3 3 HX6 2 S S 3 ( 2 6 FXFX6 HX' 5 ` ' 6 ' 5 6 6 6 6 6 N 6 6 6 2 6 ' 6 6 ' N 2 / ' `.@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX$XFXFX' 5 ` GX2 GXFXFXFXFXFXDXDXDXDXDXSXDXGXFXDXDXDXFX6 GXGXFXFX5 (.@ ' FX6 6 6 6 ' FXFXGX3 4 3 / GXGXDXDXDX5 ' 6 ' FX` DXDX5 FX' 5 DXDX6 GX6 2 5 FX' 5 ' GX/ 2 4 S 3 ) & 2 6 ' 2 3 6 / : GXGX2 / 6 HX3 u y k k r y r 0 q 4 3 6 6 S 1 3 3 3 6 u q u c 4 6 ' ' 5 3 y M 5 GX2 2 GX6 ` 5 6 M ( 6 2 m 2 6 GXGXFX' / DX(.3 3 4 / 6 6 6 / 2 3 4 3 2 GX6 2 ) 4 4 4 3 3 3 6 6 2 2 HX/ 3 k r r y A q q 4 u u HX2 M u r 1 2 ) 2 DXOX4 3 3 3 ( 3 ) 3 4 S ) 3 4 M 2 GX6 ' 2 y q ( 2 2 2 6 5 FX' 6 FX' 2 2 6 6 5 FXGX/ 6 / GX6 6 / 6 6 / 2 6 6 5 ` ' GX2 ( 3 M S S M HX/ 6 N 2 ( 2 2 / 2 GXHXu q 1 u r L k 2 JX3 4 u 3 / 2 3 2 2 3 m ) 4 OXGXHX3 HX/ 2 ( ) S S S ( 6 6 GXFX6 4 u 2 2 1 u S 3 3 3 GX' 6 6 6 ' 5 6 6 FX6 6 6 6 2 2 N 6 6 / 6 ' 6 6 2 ( 3 3 3 2 3 M ) m 2 2 2 M 4 ( 2 3 6 6 6 6 / ' 5 ` 5 / 2 6 ' 6 2 / 6 N 2 2 6 / 2 / 6 ' DX5 ' 6 2 3 3 FX#X@XVX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@XSXFX' FXFX6 FX' 6 6 2 2 ' DXDX`.DXDXDXFX' FXDXDXSX' GXFXFXFX5 FXFX' FX5 FXFXFXDXFX6 GX6 / 3 u A 4 3 / DX` 6 6 5 6 6 ` ] 6 ) 6 6 FX` FX6 GX2 / FX6 5 SX6 3 3 2 6 6 2 ( 2 2 FX8 ( HXSX6 / FX2 2 / HXM S 3 HX1 A q r y r 0 q S 1 y q 4 3 3 S 3 1 c 1 q 4 GX= 6 ' : y 4 5 6 6 6 5 DX6 u S 3 6 / 2 2 6 GX6 5 ' 6 6 ' GXHX3 2 GX6 5 FXFXGX) 2 GX6 6 6 ' 2 4 4 3 3 1 q JX3 3 OXGX) 6 k h q r q ;Xr q 4 u 1 KXq y 1 S 3 S ( / 3 3 3 3 2 3 ) 3 ( S 4 3 3 ) 3 2 6 2 6 M y q 3 HX( 2 6 ' FX5 5 8 FXM 3 u ) FX' 6 6 2 2 6 6 ' 6 ' ' 6 6 6 6 FX6 6 6 / 2 3 4 3 2 / 2 6 5 FX6 6 6 6 / 3 4 u 4 3 ) 3 2 y q 3 (.OX4 u 4 6 ( 2 2 2 2 2 JX2 GX( 3 2 GX2 3 4 4 4 KX4 ) 2 2 GX2 u q q q q A 4 3 ' HX2 6 6 6 6 DX5 ' 5 FX' 6 2 / 5 ' ' ' / 2 6 ' FX6 GX6 GX2 2 / 2 ( 2 2 3 3 ( 2 2 FXFX6 2 / 2 3 3 2 5 DX8 2 3 3 3 4 S 3 3 3 2 / FX' GX6 / 6 5 6 6 6 6 2 2 3 M 2 FX$XAX@XAX#X#XVXAXVXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX`.SXFX' DXFX/ GX/ HX6 DXDXDX5 DXDX` @ ` DXSXDXGX` SX` FXFX` 6 GXGX' ` DX` FXFXGXGXGXHX4 4 JX( ( 4 2 6 FX6 5 FX` DXSX2 ) 6 6 5 ` 5 ' 6 2 2 6 DXDXFX2 ( 2 FXDX' 2 6 6 6 2 4 4 HX/ 2 2 GX2 HX2 3 4 3 FXFXFX6 2 4 A y 0 r 1 y l r ) 2 ) S 3 2 S u u S 3 2 / / 2 A 1 FX5 FX5 5 ' 4 q 3 6 GX2 2 6 ' 6 DXDXGX6 / / 2 3 ( / 2 ' FX6 6 2 > 3 ( ( 2 GX6 ' 2 OXGXA q u ) 3 JX4 4 4 2 6 r 0 k r r l y 4 1 q A u q r 1 4 u 3 2 3 ( ) / ` 2 S 4 3 HX2 JX3 HXHXN 3 4 / 4 u q u 2 2 6 ' 6 FX` 5 GX2 M u u ( 5 FX6 6 GX6 GX6 6 FXFX5 5 FX6 / 6 6 / 2 ( 2 2 ( GX' GX6 6 ' 6 6 ' 6 / 2 3 ) S u ) 2 ( ( m 4 ) 2 4 KX4 u 2 ' 6 ' % ' 4 HXGXGX3 ) ' 6 GXGX( 3 3 3 3 3 3 HX( 3 3 3 S u A A 4 GXFX2 3 / 6 2 FX` 5 FX2 2 6 ( 4 3 / FXFX2 2 6 5 5 5 ' 6 6 6 / GX' 6 6 6 6 / 6 2 / FXDX5 6 6 6 2 ( 4 JX2 2 3 GX' 6 4 4 3 3 3 3 6 ` 5 6 FX6 6 5 6 6 6 6 6 6 2 2 2 3 3 3 2 FX$XAX#XDXFXDXSX#X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XVX@XSXFX' 5 5 6 ' 6 / 6 / GX' ` DXDXDXDXDX] FX' DXSXDX# 5 FXGXFXFXFX5 FXFXFXFX6 / GX3 4 FX$X6 2 3 4 u 2 GX/ 8 DXDX5 ' 6 FX5 ` DXDXFX5 6 GX5 DX' 2 HX2 6 5 5 FXGXGX/ 6 3 S ( 3 u GXFX6 2 3 3 3 ( 6 6 GXFX2 2 / 3 1 0 0 r q r l r M 2 4 3 5 3 u 4 S 3 m 2 2 4 q q m ' ' 5 5 / 4 4 5 6 2 2 / 6 FXDX8 ( m GX/ GX3 3 / 6 6 ' 6 FXGX3 / 4 4 3 2 ' 5 ' 6 2 ) 4 M 3 3 2 4 4 S 4 4 3 ( y r r r q u S u q q u q q u A u S 3 2 2 ' SX& y / 3 4 FXGX( HX2 2 3 S HXGXJXS r y ( 6 5 ' 5 ` 8 6 u A 1 4 2 FX5 6 FX' 6 6 6 6 ' 5 5 DXDX6 2 2 2 2 GX3 / FX2 2 6 6 6 GX6 6 6 / 2 2 ( 3 3 3 4 3 ( 2 HXM HX6 6 2 M 3 HX1 A 3 5 ( y r u 2 GXFXGX3 GXGXGXGX2 HX( 2 2 3 GX2 ( 3 3 ) S u q q 3 2 2 3 3 2 2 6 5 5 DX5 6 ' HX4 4 3 3 2 M 4 6 FX6 ' 5 ' 6 ' 6 / 6 GXGX6 GX6 6 6 N 6 6 / / 6 6 2 / / 3 3 3 KXu / 6 M 4 ' 6 2 2 / FXFX6 ' 5 5 DX5 6 ' / N / / 2 FX6 2 2 m 3 M 2 ' 6 N / 2 / / FXSX@X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#XAXSX5 FXFX6 6 FXGX/ HX3 / 5 `.SXDXFXFXDXFXFXDXDXSX` ' GXFX] 5 FX5 6 GX2 2 FXFX6 / GXFX(.GX6 JXS 1 A 3 3 / ` 5 FX' ' FXFXDXDX3 m FX6 6 FX5 6 2 2 2 GX' 5 8 GX2 6 ( 3 6 5 2 S GX6 6 FX2 / / 2 / 2 2 / HX( 3 4 M 1 q r r y r 0 k 1 3 6 2 q q > 3 3 HX( 4 1 u A 3 6 6 5 5 2 y S DX6 2 6 6 ` 5 / M A 3 6 2 2 2 2 6 ' # 6 6 DXGX6 OX) 2 GX6 ' FX2 3 3 ) 2 6 / 6 6 2 u u 4 ) 4 2 GX) 1 u S S 2 u y 1 q 1 u y q u u KX3 ( 3 3 y y OX3 3 6 2 ( 3 3 3 ) JXGX3 JXKXu u HX' ' 5 FX` FX1 q q u HX6 FXFX6 ' FX5 5 5 6 6 2 2 ' 6 6 FX/ 2 FX6 2 ' ' GX6 / / 6 6 6 GX6 6 2 HX( 3 ) ) 3 2 2 m GX2 6 6 ' 6 5 HXKXu 1 u u q l r 4 2 ) JXHX( / / 2 2 2 3 3 2 ) ( 6 2 2 HX2 3 S 4 4 ) 4 ( 2 ( 2 2 2 ' FX5 6 2 8 6 S S 4 JX4 3 2 6 6 6 ' 6 6 6 6 6 6 ' 6 6 6 N 2 6 / 6 @ ' 6 2 2 2 ( 3 2 2 2 M m / 2 3 3 S 3 6 / 2 2 6 / 2 6 ` 5 5 DX5 6 6 6 2 2 2 2 ' GX2 2 / 6 6 / : / @ ` FX2 m 3 3 6 DXAX@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X` 6 GX' FXGXHX2 / FX@ DX5 ' FXDXDXDX5 DXSXDXGX' DXDX@ ' FXGX2 HXFX5 ] DX@ ' GX/ GXGX) 4 4 S 4 4 1 2 ` ' 5 FX5 5 DXDXS 1 / / 6 ` 5 ' 6 GX6 / ' DXDX2 ( 3 3 6 FX6 ' 6 2 2 ' 6 6 2 3 HX( ( 3 3 2 ( 4 3 GXFX6 M 1 q q y 0 0 q u y 0 r ) 2 3 ( / 4 1 S u 3 ' 6 FXDXS r u 5 ' ' ' DX2 1 A y u 2 / GXGX2 GX6 FX5 6 GX2 2 2 3 2 GXN GX6 6 GX) ( 2 ' 6 2 ' DX( 4 3 ) 4 2 / HXHX6 FXHXJX2 3 l y 1 y r l y KXu A A KXq r q 4 3 ( HX( 2 ( JX( 3 3 4 ) ) u S 2 HX4 2 FX5 : 2 4 y A A u 2 GXN 6 / 6 5 5 5 6 / ( S S 3 / 5 FX6 6 DXFX6 6 6 6 6 6 / / 6 / 6 ' 6 6 / 2 3 3 2 6 2 2 6 DXFXGX' 5 ' 5 3 u 4 ( 3 1 ) 6 2 M ( 4 u 4 4 GX2 3 2 / ( 3 4 4 3 OXGXJX2 ( HX2 2 3 3 3 3 ) 2 2 2 2 GX6 6 1 q ) ) 4 3 ( ( 2 ' 5 ' / FX6 N 6 6 6 2 6 5 5 ' 6 6 6 6 2 5 ] @ DXDX6 2 2 2 2 6 / 2 2 2 ( m 2 2 m 2 2 ( 2 2 2 2 2 / DX] DX' 3 3 6 N 2 2 N 2 N 6 6 2 GX6 6 6 5 ' FXFX6 / 2 m 3 3 / DXSX#X@XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).#XDX' ' FX6 / 6 2 6 / 2 ( GX5 DXDXDX5 DXSXFX/ FX5 DXDXFX6 GX2 GXDXFX6 6 FX' GX6 / ( GXFX1X5 GX3 4 u 3 6 ( 6 DXDX5 5 2 3 6 6 5 ` DXDX5 6 / 6 5 DX6 2 3 3 ' ` 6 6 FX/ HX6 / 4 3 ) S 2 GX2 3 ( HX4 4 6 DX$XFXGX6 3 ) q y 0 k y r k k u / ( 3 2 2 4 u u 3 6 ' 5 2 y q A 2 ' FX5 5 > A u 4 2 6 GX2 2 6 FX' DX` 6 / 2 2 3 ( GXGX6 6 GX' FX3 4 3 / 2 ) m 2 HXGX' 2 3 3 3 HX/ HXGX/ 3 ( ' y '.y u 1 A 1 q 1 1 q 1 1 y r q M 3 JX2 ( 3 2 2 FXGXS 4 M 4 3 GX3 S 2 / 3 S 3 4 S S 1 q 3 2 GX6 6 5 FX5 ' 6 FX4 S 3 2 FX' ' 6 6 6 / / 6 / 6 5 FX6 ' 6 / GX6 / 2 GXGX3 2 ' GX2 ' ' FX6 6 5 FX6 m 4 4 > 3 u 4 FXDXHX4 3 3 3 3 4 3 2 2 6 2 2 ( 3 ( 4 2 ( 3 ( ( / GX/ 3 ) 3 3 4 2 / 3 4 ( ( ( u q 1 S 2 GX/ 3 6 5 FX6 5 5 6 FX' ' 6 6 2 3 ( 2 2 5 5 6 6 5 FX' 5 FX6 / / GX6 6 FX@ ` FX6 6 / 6 GX/ 2 / 2 / 6 6 6 2 2 ' 8 / 2 2 GX6 3 4 3 2 N 2 / GX' / 6 FX6 6 6 6 6 6 / / 2 m : 3 m 2 FXSXVX@X#XAX@XAXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XmX#X#XSXmXDX/ FX5 / / / 2 ( 2 ` DXSXDXFXDX` 6 FX5 (.DX8 6 GX` FX' 5 FX6 / 2 GX6 FXFXGXFX' 6 GX6 3 ) S y u 4 4 ' ` FX6 6 FX' FXFXDX5 3 / 6 / ' DX' 2 / 3 2 5 FX6 ` ' 3 2 2 3 3 m S 4 HXFX/ 6 2 3 2 / 6 6 GXGX/ 3 3 3 4 A y r k r r 0 l 1 2 2 6 / u u > HX3 2 6 u u u y M 6 ' 5 5 2 u 4 6 6 / / 2 / 6 5 8 ] 2 HX6 / 2 2 2 / 2 6 ' FX2 3 3 ) JX4 4 6 GX2 GX6 6 2 ) S ) 2 6 ( 3 3 3 3 3 2 y y DXFXFX3 S 3 1 y y XXu k y u 4 ( HX3 2 ' 8 S q 3 ) 4 2 ' FX3 HX6 JX4 HXHX3 ( u y q M 2 2 / 6 / FX5 2 4 4 S 3 4 2 ' 6 6 6 ' ' 6 6 / 2 ' 5 ` 5 5 GX2 6 2 m 2 ' 6 2 6 6 2 6 ' 6 6 6 ' FXN 3 ) 4 4 3 m 4 u 3 FXGX3 S S 3 3 u A S 6 FX5 8 8 FX3 JXGX( 3 3 2 6 6 # 2 2 HX) 3 2 3 JX( 3 3 4 S 1 u 4 HX2 2 2 2 ' 6 FXDX5 DX5 6 5 5 ( 4 u ) 3 2 6 6 6 ' ' 6 6 6 6 ' 6 6 6 6 6 ' FX` FX' 6 ' @ 5 6 6 6 6 6 6 6 6 ` 3 q 3 ' 6 6 M u 4 S S ) 3 GX6 6 6 2 FX6 ' 6 / 6 N / = 6 6 6 / 2 2 2 3 2 / DXSXDX5 $X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#XAX@X#XFX' DX5 6 2 GX6 2 6 FX' 6 FXDXDX5 DX(.DX] FXGXFXSX5 GX(.DX' HX2 HXGXDX` 6 ' FX/ 2 / 3 S S 4 ) 2 4 S 2 ' 6 6 6 6 5 5 8 2 1 2 GX6 5 5 6 GXGXHX2 ' FX` 5 GXM 3 HX6 FX2 3 2 ( 2 / / 2 GXSXHX3 GX2 3 3 ( 3 S 4 u 1 1 y r r r 0 0 A S A r y S 3 3 u 3 ) A 4 S y 3 5 6 6 5 3 q u / 6 FX6 GX6 5 5 HXS u 2 6 GX/ 2 6 6 / / FXDX6 2 ( 3 3 4 2 5 ` 6 2 ' 2 JX4 3 6 ' 2 3 4 4 3 ) 4 4 4 / FXGX2 3 HX/ y r A q 1 y r q JX) u KX/ 2 ( r q / 3 4 2 GX( 3 HX2 ) 3 ( 3 3 3 A q S KX4 2 6 2 6 5 DX4 q S 2 GX4 3 6 ' 6 6 6 ' 5 5 5 5 ' 6 6 ' 6 3 ' $XGX2 6 6 6 ' 6 ' 6 GX6 ' FX' 6 2 2 3 4 M 3 2 6 2 2 ) 3 HX4 S 4 3 3 JXKX1 1 3 4 y y A 4 2 /.3 ) 3 / GXGX2 3 ( 3 3 3 4 S 2 # 2 3 4 u 1 u 2 GX3 ( 2 / 2 6 DX5 DXDX5 5 DX' 1 u S 4 ) 3 ( ' FX6 6 6 / 6 GX6 6 ' 6 / 6 6 6 6 6 6 6 ' 6 GX6 6 6 GX6 ' / 2 6 / 4 S 6 6 4 u 3 HX3 3 2 / FXFX' 6 FX` DXDX5 2 m 2 2 2 GX6 FX6 2 ' `.5 2 3 / FX6 m 6 ] #XVX).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#XFX' FXFX/ / 6 / 2 ( 4 3 6 5 DXDXDXFXFXDX' GX5 DXDX6 GXFXGXFXFXGX' FX6 GX2 6 / 2 HX3 3 2 FX5 2 ) S 1 u / 2 6 5 DXDX` N 2 6 6 5 DXDX' 6 ' 6 2 ' 5 ' 2 3 JX2 FXDX` 2 2 / GX' 2 4 3 6 HXu 3 / 3 4 3 3 4 S u u 3 / 2 S q q q r y q r k r S m 3 4 ) 3 S c u S ) 2 2 GX6 m q q GX5 6 ' FX5 DXS q A 3 6 2 2 2 / ' FX5 5 6 FX/ 2 HX( 3 / 6 GX5 FX' ' 3 4 3 GX6 GX2 / 3 S ) 3 4 1 S GX2 3 3 GX3 / 3 h k q q y k y 1 u 1 KXHX1 y 1 3 3 4 S 2 HX3 JX2 3 3 3 3 ) 3 S S 3 JX4 > ( 2 / FXm 6 1 q 3 / HX3 2 6 6 ' 6 6 5 5 6 / 6 6 2 6 5 6 GX5 5 6 GX6 6 GX6 5 6 / 6 6 5 5 ' 6 2 2 3 3 ) 4 ( 6 / 6 / GX2 3 3 3 M 3 OXXX1 y q q k L r 3 JX4 ) 4 4 / 2 2 ( HX3 3 3 ) S JXHX/ ( ) 4 3 ) 3 / 2 2 3 2 2 6 5 5 DX8 5 2 2 5 m u ) 4 ) 3 ) 2 6 FX' 6 / 6 6 2 / 6 N / 6 / 6 ' 6 ' 6 6 6 6 6 / / / 6 6 2 2 2 3 4 GXGX( 3 1 S / / 2 2 GX6 6 6 6 6 DX8 5 3 3 ' 6 2 N / 2 N 2 6 / 6 FX/ 2 6 5 ' 6 6 2 2 2 / DXVX@XAXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX` 6 6 / 6 ' 6 ( 4 3 GX` DXDX5 6 FXDXFXFXFXDXSXDXGX/ 6 DX` 6 FX6 GX2 HXHX/ DX2 ) FXGXGX' HX3 & A y u 3 ( 5 ` 5 FX' 6 GX' FXDXFX/ 5 5 2 / FXFX/ 2 ( ( 2 5 5 5 6 HX2 FX6 4 4 3 3 u S 3 2 / ( 2 ) 3 2 3 3 6 2 2 6 4 u A y 0 r q r k y 4 3 4 4 GX6 S u 4 4 ) 2 6 m 3 A y 3 5 FX5 5 5 2 u u 6 6 GX2 2 6 6 6 5 DXFX' 6 6 2 2 3 ( / 6 FX5 6 6 2 4 ) 3 ( 3 / $X5 6 6 ) 4 u A 4 2 4 S JXHX3 HX' y 0 y y r k k q 1 A 1 u oXq y y 4 S u 2 ( ) 3 3 ( / 3 4 3 3 S 2 2 3 FXGXM 2 ' 2 4 3 S 1 3 2 ( 2 6 GX5 5 5 ` 5 GX( 3 JXS / ` ' ' ' 6 GX6 6 6 / 6 6 ' 6 5 ` ' ' ' 6 6 GX' 2 ( 4 S S 3 2 6 DXFX2 / 6 6 3 ( 3 S u u q q A k q ( ) ) 4 4 4 2 2 3 2 6 ( 3 ( M 4 ( 2 2 3 ) HXGX2 ( 4 S ) 4 3 6 ' 2 / 6 3 u q q q q 4 S JX2 ( 2 6 6 5 ' 6 6 ' 6 6 / 2 m 3 2 6 6 6 ' 5 5 / 6 ' 6 2 2 2 : ( m m HXm 3 M 3 3 M 4 3 2 2 2 2 / 2 2 2 HX5 ` ` / 3 M 2 6 3 3 : N 5 6 6 6 6 2 2 6 5 ' 6 6 6 6 / : 3 M 2 DX#X@X#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#XAX).#XDXGX6 6 ' 6 ( 2 / 2 6 6 6 6 GXFXDX` DX5 FX] DX/ GX5 (.5 # GXGX2 ( GXDX6 8 6 GXFX2 2 GX2 4 S u u u u S S 2 5 6 6 6 / ' ` DX4 A 3 6 HX2 5 6 6 2 2 2 2 6 5 `.5 3 2 / 3 M 3 3 3 ) : 2 6 8 GX1 2 FX' GXHX2 HX2 2 JX4 u y k 0 k r k 0 r 4 m 2 ' 4 1 S u 3 ) 2 3 4 u A y u 5 6 5 ` GX4 A 3 5 GX2 2 6 6 FX8 SXm 4 6 6 6 / 2 2 2 2 6 5 ' 2 2 M 3 3 ) 4 3 ' o DX' GX> u S 4 2 2 JXS S 4 4 M S 2 4 r r r k y 1 u A q 1 S q 1 u u u 3 OX2 2 3 / 8 # 4 4 ( 3 HX6 HX2 DXFX( 2 2 ) 3 ) 4 A S 2 2 / 6 5 ' 5 5 8 DXM 4 3 S u 2 6 FX6 6 6 6 / ' ' 6 6 6 6 5 DXDX6 6 6 6 ' 6 / 2 3 3 2 2 m 6 ' 5 ' / 6 FXN 3 / 3 1 S 2 3 3 4 S 1 u 3 HXHXS S 4 3 / 8 ` 5 ` 2 4 OXFXHX2 ( 2 GX/ 2 3 4 4 4 4 S 3 2 2 HX4 u u u u r q ) 4 2 2 3 2 6 6 6 6 ` 5 FX6 5 6 M 4 3 : / 6 5 DX6 2 GXFX5 ' ' 6 / 2 2 ( 2 2 2 6 2 m 3 GX6 / 2 2 2 2 2 / 2 4 HX6 6 FX2 3 2 ) 4 4 u S 4 ( 6 FXFX' 6 FX5 / 6 6 6 GX6 6 / 2 m M M 2 DX@X@X#X#X#X#XAXVXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAXDXFX$XDX2 GX` 2 ( 2 3 3 3 6 5 FXDXDXFX5 DXFX2 6 FXFXDX5 / 2 HX2 ' FX' # ' 6 GX/ 2 / 2 3 2 GX' 6 ) S 1 u 6 ' 2 6 5 @ DX5 2 u S / / ' DXFX6 2 / 2 2 ' DXSX/ ) 3 4 2 FX` FX3 2 6 / 6 ` S q FX6 / 2 2 2 ( HX3 4 4 3 3 3 A y y y r 0 r u ) 1 k r u M 3 3 JX3 4 1 1 q u 6 6 FXDX6 A r > ` 6 2 ' FX5 FX2 2 u 1 ( 6 / 2 2 2 GX6 GXFX6 6 2 HXHX3 3 2 / 6 5 5 6 3 3 M 3 / 2 6 ' 2 S S 4 4 4 ( 2 3 u 1 u 4 u 3 S y y y q XXXXq u 3 4 ) GX2 2 6 A y 3 HX( 2 GX2 2 2 ( 2 3 S JXHX3 1 u 3 3 ( 6 FX' 5 FX] 6 u A S u u HX/ 6 6 6 6 / 6 5 5 5 ` 5 5 5 ' 4 : 2 2 GX6 2 2 2 m 2 FX@ ( 6 6 ' 5 6 6 ' 6 2 m : 4 u S S ) 3 3 3 4 u 4 4 ( + ) 1 S 2 3 u y u 3 HXFXGX( 3 2 6 6 / ( JX3 ( 3 3 u 4 2 6 GX3 ( 2 4 1 1 KXS 3 HX( ( 6 ' GX/ 5 8 ` / 2 / 2 3 3 3 3 2 ' 2 m 3 2 6 5 FX6 6 6 FX6 / 6 6 6 / 6 / / 5 DX` DXFX' 6 6 / 6 / 4 3 ( ) 3 / N 3 4 3 ( 3 ) ) 2 FX5 FX' 6 5 ' 6 6 6 6 6 6 6 N 2 2 2 2 3 3 / SX#X#X@X#XSX`.$X#X@XVXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).@XFXGX5 6 GX( ( 6 ( ( FXDXDX5 6 FXDX' 6 ' FXDX] 5 HX/ FXFX6 FX6 / GXGX6 6 ' # / GXFX/ 2 2 2 4 S 1 y S ) M 5 DX5 ' 6 2 GXGX6 5 5 ` FX' 2 / FX5 8 5 3 3 3 ( 6 5 ` 6 HX6 GX6 2 S 4 ( 3 2 HX2 GX( 2 3 4 4 / 6 6 GX6 2 ) KXq k 0 k q y k l q 3 2 ( 3 GX3 u u 1 4 6 6 5 ` 2 y r 1 ` 6 ' FX5 DXS q A c 4 2 GX2 2 2 / FXFX5 ' 6 GX2 2 3 3 2 2 6 6 FX' / / GX2 GX6 6 FXDXGX1 u 4 ) 3 2 ' (.GX2 3 ) 4 2 2 y q q y 1 y r q 4 u u KXS q q y 1 3 ( JX2 2 2 ( ( 3 2 3 4 3 3 ) u 3 ( ) : 6 6 ' 5 DX5 A r q u 4 3 / 6 / 6 ' 6 6 ' FX6 6 ' 5 DX8 3 4 2 2 ( 6 GXHXFX5 2 GX5 6 6 / 6 6 6 6 FX6 2 ( 3 3 3 M 2 3 2 6 2 3 2 6 N 2 3 GXoXu KXS k h L L r / HX3 ) 4 2 6 GX2 HX2 2 HX( 4 S / 6 GX/ ( 2 2 u A 4 JX3 ( : HX( GX6 2 6 DXDX5 6 6 6 ( GX2 ) JX4 3 3 3 / ' ' 6 FX5 6 6 6 / 2 GX6 6 6 6 6 FX5 FXFX5 6 6 ` FX/ m 6 6 3 3 3 3 2 FX/ 3 GX2 2 2 6 FX' ' 5 5 ` 5 5 5 ' 6 6 6 6 6 6 6 GXN / 2 2 M : 2 6 5 FX6 2 2 6 FXDX_.VX@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X#X#XFX6 FX5 2 ( GX2 3 2 / 2 / 6 5 DX5 5 (.5 DXDXGX/ DXSXFXGX6 FX/ ( / GX6 FX5 6 GXGX2 HX2 ( 4 1 1 q u > u ) 5 ` 6 2 6 6 / 6 5 DXGX> 6 2 6 5 ` ` 2 ( 3 3 2 GX` 5 5 / ( / 6 3 4 2 2 S S 3 2 6 FX2 3 ( ( GX/ 2 HX2 / 2 M 4 q 0 k y r k k r S 2 2 3 6 5 4 u S ( / 6 ' 5 u q q q GX5 FX5 5 6 S A 1 M 6 GX/ GX2 / 6 FX` DX6 / 6 / 2 2 / / GX6 6 ' 5 FX2 ( 3 / / 3 2 6 4 3 2 2 3 HX3 / @ GXm HX3 ) 2 / 1 l y y r r y A u 1 A y KX1 r q S 4 S 3 2 2 2 3 4 ( ( ) 3 3 4 S S 3 ( 3 ) 2 6 5 ' 6 S q 1 y q 2 3 / 6 6 ' 5 5 5 ` / 4 ) 3 4 2 2 2 ] SX6 2 6 GX/ 6 GX6 6 GX6 6 6 GX6 6 FX5 FXFXGX( 3 ) 4 3 2 / 2 ( 2 5 DXFX5 6 ) u KXS S 4 l L '.q 2 3 u S 4 ) 2 / 2 ( 2 ( 2 2 3 3 GX/ 2 2 HX2 4 4 3 4 ) 2 3 2 / 3 2 2 6 DX' 6 3 HX5 ` 4 4 ) 3 3 3 3 6 FXFX6 6 5 5 6 6 6 6 / 6 / N / N 6 6 6 / 6 6 / 2 2 6 2 2 2 2 2 m 2 2 2 3 HXJX3 6 2 ( 3 / 6 6 6 GX5 DX5 DXFX5 5 5 5 ' 6 N 6 N 6 6 6 N 2 HX2 / 2 2 6 6 6 2 3 M 3 6 DX#X@XVX#XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X_.DX/ / 2 / / 2 m 4 S 3 / FXDXDXDXFX6 DXFXGX# ` DXDX6 6 6 HX/ # GXFX' 2 ' ' 6 / ( ( 2 u u HX6 / 3 4 u u : 6 ( / ' 6 FX` DXm A 3 2 GXFXDX5 2 2 2 2 HX2 6 5 ] GX> 2 3 3 / FXFXm 4 2 / ' 8 3 GXGX3 6 / 3 ( ( 3 3 4 4 4 q y r k r r 0 0 A 4 3 / u 1 u S 2 3 3 / > q c A q 3 6 ' 5 ' 2 1 1 M 5 GX/ 2 2 6 ' FXDX8 6 2 GX/ / 2 2 / 6 ' FX6 ' 6 2 3 4 4 3 4 3 2 ( 2 / 6 ' 2 S u 4 HXGX2 3 3 ( 3 > 2 r 0 A KX) 3 3 1 S S y 1 A r r q 4 4 HX( / 3 4 2 2 6 3 4 ) 4 4 3 HX3 4 4 3 6 2 3 ( 4 S S q y 4 ( 6 ' 6 6 5 ` 5 6 2 4 3 3 4 u 4 ' DXDX' 6 6 2 / 6 6 / 6 6 / ' 5 6 6 ' ' 6 FX' 2 2 3 3 GX2 2 6 6 / 6 ' ' 6 6 5 m u S > 3 4 q r S 2 2 4 KXJX4 u ) GX3 ( 3 2 GX2 2 ( 3 3 ( 3 2 3 HX6 GX2 ( 3 3 3 3 2 2 ( 6 / 2 / u q 1 ) u 4 / 2 ( / FX5 ' 6 6 5 FX5 ' 5 ' ' 6 6 6 / 2 2 / N / 6 ' 5 FX6 6 2 2 2 3 m 2 / 2 2 2 m 3 m HX3 3 m ( 3 3 m 2 m / 5 8 DX' 6 / 5 5 2 4 ) 2 2 2 / 2 / FX6 6 6 ' 6 ' ' 6 6 6 6 ( M 3 2 FX`.@X@X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX@XDXGX2 2 6 ' HX4 ( 2 2 FXDXDX5 6 GXFX5 FXFXFXDX8 (.GX2 2 5 ` ' # 6 HXGXHX3 / GX2 S 4 2 6 @ HXm 4 u q y S 2 4 6 DX5 5 5 2 4 / 6 FX5 DX8 6 / 6 / 2 6 FX8 FX( 2 M JX6 ' 6 / GXFX6 / 2 S 3 DX3 JXGX2 HX3 3 ( 3 u u 1 1 4 4 u y r q k l A 1 y l y S 4 2 S 4 HXu 1 u q A 2 6 6 / 6 2 q q 3 ' 6 6 2 / FX5 8 / ( S 4 6 6 6 2 2 / 6 6 ' 6 6 ( ( GX3 OXGX3 / 6 6 6 / 6 2 4 u 3 ( 2 ' HX4 3 3 4 ) 3 3 u GX5 6 2 2 2 u r A y y q y y u 4 ) 4 3 3 2 ' FX' 4 3 HX4 3 / GX3 4 ( 2 2 4 3 HX3 HX4 q q 1 3 2 6 6 FX' 5 6 2 3 3 3 ) 3 4 3 5 5 5 6 6 / 2 6 ' 6 6 6 / 6 5 ` 5 6 6 6 6 2 / 2 ( 2 DXDX2 6 6 / 6 6 6 ' 6 6 2 2 u S S 1 1 S 2 6 3 3 3 HX/ 4 1 u 2 6 6 DX] SX5 2 ( 3 3 JX2 / ( 6 GX( 3 HXGX2 4 4 3 3 ( 2 ) ( 3 1 y y q 3 6 6 3 ( 6 ` FX6 6 ` 5 5 ' 6 6 5 DX5 6 5 5 6 6 6 2 / 6 ' 5 ` DXFXFXDX6 2 GX6 2 / / 2 2 2 / 6 6 5 DXFX/ 2 2 2 2 2 2 ' 5 6 2 2 6 ( ) u u 3 2 2 2 2 6 FX' 6 6 6 6 6 6 6 6 6 6 2 2 2 : 3 3 6 SX#X@XAX#X#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@XSXFX` ' 6 ( 2 6 3 2 2 2 3 2 ( 6 FXFX5 5 6 (.8 5 3 2 GX5 DX6 2 GX2 3 4 ( # 5 DX4 GXGXHX2 ( 2 u A q y r S S S / ' 6 6 2 2 6 6 FX` DXDX6 : / 2 6 FX5 FX2 ( 2 3 / FX6 GX6 2 DX2 3 M u ( JXu 2 2 3 3 4 3 3 S S S u HX6 2 6 4 q y q k l r r k l A M 3 S S 3 3 u c u 4 ( 3 2 2 6 m u q 4 2 ' ' 6 ' 5 5 S y * S 2 / 6 GX2 / 6 GX6 FX6 6 2 / 2 HX/ 2 2 / 6 FX' 6 6 ( 3 HX2 6 / 6 6 3 M 4 4 3 HXM 2 2 ( HXHX3 ( 3 0 l q y y y y y S KXA A 3 6 3 S A 4 3 ( M 3 2 ( 4 ) 3 3 4 3 ( 3 JXJX1 q q 4 ) 3 2 / 2 2 ' 6 4 A S u 3 HXHX2 ' 5 6 6 6 2 / 6 6 6 5 FX5 5 ' 5 6 2 / 2 m 2 DXFX3 6 FX2 / GX6 6 6 6 ' 6 / 6 3 4 4 3 3 1 u M 3 2 3 ) S M 3 KXu u KX2 ) q q A u 4 3 HX2 ) 2 HX2 GX/ 3 3 2 2 3 4 3 M 4 JX4 ) 3 S u q q 4 3 6 2 3 3 6 5 6 6 5 5 5 DX/ 2 6 n 3 4 3 4 2 5 5 5 2 / 6 6 6 FX' 6 ' ' / 6 6 / 6 6 6 6 6 6 2 / FXDX` 6 / / 2 6 6 6 2 : ( 6 2 2 S 1 u u 1 u 3 2 ( FX' 6 / 6 FX6 6 6 6 N / 6 6 N / 2 2 2 m M 3 / 5 SX#X#XSX_.#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X#X6 2 6 6 m m 3 4 ) 3 m 6 FX5 ` FXFX@ DX' HXGXFX5 DXFX2 / ( HX3 FX5 ' ' FX6 / 2 HX2 2 4 S 3 > 4 S S q A 2 6 N / N GX' 5 DXFX6 u 1 GX/ 6 FX5 6 / 2 3 ( 6 6 ' 5 ` GX3 3 m 3 JX3 4 ) ( 3 ' 6 3 ) 3 GX6 2 ( / 2 ( / 2 4 S 1 r 0 r y y k r 1 3 3 S 3 FX4 u S 3 3 4 2 2 m 3 u q u 2 ' FX5 5 5 3 q q M 6 6 / / / 6 5 5 5 DX' 6 6 / 6 2 2 3 2 6 6 ' ' FX5 FX2 3 2 6 6 2 6 6 / 3 4 ( 3 M JXHX3 2 ( GX( 4 2 2 l k q y r r y 1 4 q q 4 ) q y 1 4 3 ( 3 3 / 3 ) 3 2 3 ) 2 ( 3 ) 4 4 ( 3 ( 3 3 / 2 2 6 6 6 4 q S 3 GX/ 2 2 6 ' ' FXFX6 5 ' 2 2 ' 5 5 FX5 FX2 6 6 2 2 FXFX6 / 6 / 2 6 6 6 6 6 5 FX6 2 ( 3 4 M ( 6 N 3 4 ( ( 3 ) 4 3 3 JXKXKX1 KXq h 0 '.h q ) 2 GXHX( 3 2 GX/ 2 2 2 2 ( 3 3 ) ( # ( ( 3 4 4 u 3 S u ( 2 ( 2 / 6 6 5 DX` DX5 6 5 ` 3 1 ( 3 u ) / / 2 6 6 ' FX5 6 6 6 6 6 6 6 6 6 2 / 6 6 6 6 6 6 6 6 6 6 6 6 2 GX6 6 5 2 ) 2 6 ( S 4 4 3 3 ) 3 2 FXDXFX6 2 FX` 5 ' 6 6 2 2 6 6 6 ' 6 6 N / 6 2 : 3 2 ' 6 / 6 6 `.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#XAX#X#X#XSX_.#X#X$XSXSX#XSXSX_.#X#X#XSX_._._.mXSX_._.mX_.#XSXSXmX_._.#X_.SX$XSXmX_.SXSX_.$XSX#X).@X#X#XSX$XDX$X_.mXSXmX_.mX_.#XSX$XDX$XSXSXmX#X_._.mXSXSXSX#X_.mX#X#XSX$XSX$XSXSX$XSX#XSXSX#X#X_.$XSXVX#XSX_.SXmXSXmXSX_.#XSX1XDX] $X8 DXFXDXSXSXSX#X#XSX$XSXSXSXSX_.SXSX$XSX] $XSX_.mX_.#XSXSXSXSX#X#X_.mXSXmX#X_.#X#X_.SX#X_.SX_.SXSXSX_.#X_.#XmX#X#X_.SXSXSX_.$XSXSX_.#X#XSX_.SX$XmX#XSX$XSX#XSXSX$X@XSXFXSX$X$X$XDXDX$X$X$X$X$XDX`.$X$XSXSXSXSXSXSXSXmX_.SXSXSXSXSXSXSX_.#X#XSX$X_.mXSX#X_.SX_.$XDX$X_.SXSXSXSX$XSX#XmX_.#X#XSXSXSXSX$X_._.#X#XSX_.#XSX#X_.SX_.#XSXSX_.SX_._._._.mX_.SXSXSXSXSXSX#X_.mXSXSXSXSXSXSXSXSX$XSXSXSX$X`.SXDXSX5 ' `.SXSXmX_.o $XSXSXSX$XSX_.SXSXSX_.$X#X#X#XSXSXSX$X$X_.o DXSXSXSX_.SXSX_.#X_.#XmX_.#X#X#XDX$X#XSXSXSXSX$XSX#X_.mX#XSX_._._.SX_.mX#X_.mXSX#X_.SX_.SX_.SXSX$XSX_.mX_._.SXSXSX_.#XSXSX_.SXSX#X_.#X_.SXSX_.#XSXSX_.SX#XSX#X_.#X_.SX_.SX_.#XSX_.SX#X#X_.#X_.SXSX$XSXSXSX$XSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X#XAX).#XVX#XVX#X#X#X#X#X#X#X#X#X#XAX#X#X#X#X#XAX).#XVXAX#X#X#XAX#X#X#XVX#XVXAX@XAX#X#XAXVX).@X@XVX#X#X#X#X#X#X#X#X#XAX@X@X#X).#X#X#X#X#X).#XAX#X#XAX#X#X#X).VX).@X).VXAX#XVXAX#X#XAX@XAX#X#XVXAXAX).#X#XAXVX).VX@X@X@X@X@X@X@X@X).#X@XAX#X).VX).@X#X).#XVXAX).@X@XVXAX#X#X#X#X#X).@X@XAX#X#X#XAX#XAX#X#X#X#X#X#X#X#X#XAX#XVX#X#X#X#XAX#X#X#XAX#XVX#XVX#X#X#X#XAX@X#XAX@XAX#X).VX#XAX#X).VX#X@X+X@X@X@X@X@X@X@X@X@XVX).@X@X@XVX).#X).#X).#X@XAX#X).@X#X).#X).#XVXAXAX).VXAX#XAX#X#X#XAX@X@X@XAXAX#X).AX#X#X#X#X#X#X#X#XAX#X#XVX#X#X#X#X#X#X#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).#X).@X#X#X#X#X).).#X).#X@X).@X).#X@XVX).@X@X@X@X+X+XVX).#XAXAX).VX).#XVX).#XVX#X).#XVX).AX#XAX).#X).@XVXAX@X@X#X).VX#XAX#X#X#X#X#X#X#X#X#X#X@X).AX).#X@XAXAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X).#X#X@XVXAXAXAXVX).#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX#X#XVX).#X#X#X#X#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X_.#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#XSX+X. @XSX#X#X#X#X#X#X#X#XAX#X#X#X#XAX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX+X. AXmXSX@X. ZXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX@X. CXSXVX. . SX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSX. . SX#X#XAX#X#XSX. . AXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XSXCX. @XSX#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X_.ZX. BXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X% #X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#XZXu [.XXZX#X#X#X#X#X#XSX. . #XmX_.CX. AXSX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XZXGX[.HX+XZX_.[.1 ZX#X#X#X#X#X#X#X#X#X#X#X#X#X#XZXOX[.;XZXOXh y ZX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XAX+X[.l ZX#X+X. @X#XZXy [.DXZX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X@X1 [.FXZX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#XZXoXh oXZX#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X#X", +"#X#X#X#X#X. [. 1 . #X#X#X#X#XAX+Xl '.$XZX+Xbegin(); tab1->label("I/O"); @@ -767,6 +768,7 @@ void JobWindow::initialiseAutopickWindow() place("do_refs", TOGGLE_DEACTIVATE); place("do_log", TOGGLE_DEACTIVATE); place("do_topaz", TOGGLE_DEACTIVATE); + place("do_amyloid", TOGGLE_DEACTIVATE); place("continue_manual", TOGGLE_REACTIVATE); tab1->end(); @@ -886,7 +888,7 @@ void JobWindow::initialiseAutopickWindow() tab4->end(); tab5->begin(); - tab5->label("autopicking"); + tab5->label("Refs 2"); resetHeight(); place("threshold_autopick"); @@ -936,15 +938,51 @@ void JobWindow::initialiseAutopickWindow() place("helical_nr_asu"); place("helical_rise"); - current_y += STEPY/2; + group4->end(); - place("do_amyloid"); + guientries["do_pick_helical_segments"].cb_menu_i(); - group4->end(); + tab6->end(); - guientries["do_pick_helical_segments"].cb_menu_i(); + tab7->begin(); + tab7->label("Amyloid"); + resetHeight(); - tab6->end(); + place("do_amyloid_fom", TOGGLE_LEAVE_ACTIVE); + + current_y += STEPY/2; + + group5 = new Fl_Group(WCOL0, MENUHEIGHT, 550, 600-MENUHEIGHT, ""); + group5->end(); + + place("do_amyloid_tracing", TOGGLE_DEACTIVATE, group5); + + group5->begin(); + place("amyloid_threshold", TOGGLE_DEACTIVATE); + place("amyloid_length", TOGGLE_DEACTIVATE); + place("amyloid_width", TOGGLE_DEACTIVATE); + place("amyloid_gpu_ids", TOGGLE_DEACTIVATE); + place("do_amyloid_plot", TOGGLE_DEACTIVATE); + + current_y += STEPY/2; + + group6 = new Fl_Group(WCOL0, MENUHEIGHT, 550, 600-MENUHEIGHT, ""); + group6->end(); + + place("do_amyloid_carbon", TOGGLE_DEACTIVATE, group6); + + group6->begin(); + place("amyloid_carbon_threshold", TOGGLE_DEACTIVATE); + + group6->end(); + guientries["do_amyloid_carbon"].cb_menu_i(); + + group5->end(); + guientries["do_amyloid_tracing"].cb_menu_i(); + + + + tab7->end(); } void JobWindow::initialiseExtractWindow() @@ -1050,28 +1088,13 @@ Pixels values higher than this many times the image stddev will be replaced with group5->begin(); - place("helical_tube_outer_diameter", TOGGLE_DEACTIVATE); - + place("helical_tube_outer_diameter", TOGGLE_DEACTIVATE); current_y += STEPY/2; place("helical_bimodal_angular_priors", TOGGLE_DEACTIVATE); - - group6 = new Fl_Group(WCOL0, MENUHEIGHT, 550, 600-MENUHEIGHT, ""); - group6->end(); - - current_y += STEPY/2; - place("do_extract_helical_tubes", TOGGLE_DEACTIVATE, group6); - - group6->begin(); - - place("do_cut_into_segments", TOGGLE_DEACTIVATE); place("helical_nr_asu", TOGGLE_DEACTIVATE); place("helical_rise", TOGGLE_DEACTIVATE); - group6->end(); - - guientries["do_extract_helical_tubes"].cb_menu_i(); - group5->end(); guientries["do_extract_helix"].cb_menu_i(); @@ -1406,7 +1429,8 @@ void JobWindow::initialiseInimodelWindow() place("do_ctf_correction", TOGGLE_DEACTIVATE, group1); group1->begin(); - place("ctf_intact_first_peak", TOGGLE_DEACTIVATE); + if (is_tomo) place("ctf_intact_first_peak", TOGGLE_ALWAYS_DEACTIVATE); + else place("ctf_intact_first_peak", TOGGLE_DEACTIVATE); group1->end(); guientries["do_ctf_correction"].cb_menu_i(); // To make default effective @@ -1516,7 +1540,8 @@ void JobWindow::initialiseClass3DWindow() place("do_ctf_correction", TOGGLE_DEACTIVATE, group1); group1->begin(); - place("ctf_intact_first_peak", TOGGLE_DEACTIVATE); + if (is_tomo) place("ctf_intact_first_peak", TOGGLE_ALWAYS_DEACTIVATE); + else place("ctf_intact_first_peak", TOGGLE_DEACTIVATE); group1->end(); @@ -1555,7 +1580,14 @@ void JobWindow::initialiseClass3DWindow() // Add a little spacer current_y += STEPY/2; - place("do_blush", TOGGLE_DEACTIVATE); + // Blush group + group9 = new Fl_Group(WCOL0, MENUHEIGHT, 550, 600-MENUHEIGHT, ""); + group9->end(); + place("do_blush", TOGGLE_DEACTIVATE, group9); + group9->begin(); + place("blush_version"); + group9->end(); + guientries["do_blush"].cb_menu_i(); // This is to make the default effective tab4->end(); @@ -1613,21 +1645,15 @@ void JobWindow::initialiseClass3DWindow() group5->begin(); place2("helical_tube_inner_diameter", "helical_tube_outer_diameter", "Tube diameter - inner, outer (A):", TOGGLE_DEACTIVATE); place3("range_rot", "range_tilt", "range_psi", "Angular search range - rot, tilt, psi (deg):", TOGGLE_DEACTIVATE); - place("helical_range_distance", TOGGLE_DEACTIVATE); + place2("helical_range_distance", "helical_nstart", "Local averaging - range (box), N-start:", TOGGLE_DEACTIVATE); place("keep_tilt_prior_fixed", TOGGLE_DEACTIVATE); // Add a little spacer current_y += STEPY/2; - group8 = new Fl_Group(WCOL0, MENUHEIGHT, 550, 600-MENUHEIGHT, ""); - group8->end(); - place("do_apply_helical_symmetry", TOGGLE_DEACTIVATE, group8); - group8->begin(); place("helical_nr_asu", TOGGLE_DEACTIVATE); place2("helical_twist_initial", "helical_rise_initial", "Initial twist (deg), rise (A):", TOGGLE_DEACTIVATE); place("helical_z_percentage", TOGGLE_DEACTIVATE); - group8->end(); - guientries["do_apply_helical_symmetry"].cb_menu_i(); // to make default effective // Add a little spacer current_y += STEPY/2; @@ -1719,7 +1745,8 @@ void JobWindow::initialiseAutorefineWindow() group1->begin(); - place("ctf_intact_first_peak", TOGGLE_DEACTIVATE); + if (is_tomo) place("ctf_intact_first_peak", TOGGLE_ALWAYS_DEACTIVATE); + else place("ctf_intact_first_peak", TOGGLE_DEACTIVATE); group1->end(); guientries["do_ctf_correction"].cb_menu_i(); // To make default effective @@ -1739,7 +1766,14 @@ void JobWindow::initialiseAutorefineWindow() // Add a little spacer current_y += STEPY/2; - place("do_blush", TOGGLE_DEACTIVATE); + // Blush group + group9 = new Fl_Group(WCOL0, MENUHEIGHT, 550, 600-MENUHEIGHT, ""); + group9->end(); + place("do_blush", TOGGLE_DEACTIVATE, group9); + group9->begin(); + place("blush_version"); + group9->end(); + guientries["do_blush"].cb_menu_i(); // This is to make the default effective tab4->end(); tab5->begin(); @@ -1774,21 +1808,15 @@ void JobWindow::initialiseAutorefineWindow() group2->begin(); place2("helical_tube_inner_diameter", "helical_tube_outer_diameter", "Tube diameter - inner, outer (A):",TOGGLE_DEACTIVATE); place3("range_rot", "range_tilt", "range_psi", "Angular search range - rot, tilt, psi (deg):", TOGGLE_DEACTIVATE); - place("helical_range_distance", TOGGLE_DEACTIVATE); + place2("helical_range_distance", "helical_nstart", "Local averaging - range (box), N-start:", TOGGLE_DEACTIVATE); place("keep_tilt_prior_fixed", TOGGLE_DEACTIVATE); // Add a little spacer current_y += STEPY/2; - group5 = new Fl_Group(WCOL0, MENUHEIGHT, 550, 600-MENUHEIGHT, ""); - group5->end(); - place("do_apply_helical_symmetry", TOGGLE_DEACTIVATE, group5); - group5->begin(); place("helical_nr_asu", TOGGLE_DEACTIVATE); place2("helical_twist_initial", "helical_rise_initial", "Initial twist (deg), rise (A):",TOGGLE_DEACTIVATE); place("helical_z_percentage", TOGGLE_DEACTIVATE); - group5->end(); - guientries["do_apply_helical_symmetry"].cb_menu_i(); // to make default effective // Add a little spacer current_y += STEPY/2; @@ -1855,7 +1883,14 @@ void JobWindow::initialiseMultiBodyWindow() // Add a little spacer current_y += STEPY/2; - place("do_blush", TOGGLE_DEACTIVATE); + // Blush group + group9 = new Fl_Group(WCOL0, MENUHEIGHT, 550, 600-MENUHEIGHT, ""); + group9->end(); + place("do_blush", TOGGLE_DEACTIVATE, group9); + group9->begin(); + place("blush_version"); + group9->end(); + guientries["do_blush"].cb_menu_i(); // This is to make the default effective tab1->end(); tab2->begin(); @@ -2693,6 +2728,18 @@ void JobWindow::initialiseTomoAlignTiltseriesWindow() group5->end(); guientries["do_aretomo_ctf"].cb_menu_i(); // make default active + // Add a little spacer + current_y += STEPY/2; + group6 = new Fl_Group(WCOL0, MENUHEIGHT, 550, 600-MENUHEIGHT, ""); + group6->end(); + place("do_aretomo_reconstruct", TOGGLE_DEACTIVATE, group6, false); + group6->begin(); + place("do_skip_aretomo_align", TOGGLE_DEACTIVATE); + place("aretomo_VolZ", TOGGLE_DEACTIVATE); + place("aretomo_OutBin", TOGGLE_DEACTIVATE); + group6->end(); + guientries["do_aretomo_reconstruct"].cb_menu_i(); // make default active + // Add a little spacer current_y += STEPY/2; place("other_aretomo_args", TOGGLE_DEACTIVATE); @@ -2757,6 +2804,7 @@ void JobWindow::initialiseTomoReconstructTomogramsWindow() place("do_fourier", TOGGLE_DEACTIVATE, group2, false); group2->begin(); + place("do_skip_wiener", TOGGLE_DEACTIVATE); place("ctf_intact_first_peak", TOGGLE_DEACTIVATE); group2->end(); guientries["do_fourier"].cb_menu_i(); @@ -2867,12 +2915,12 @@ void JobWindow::initialiseTomoSubtomoWindow() tab1->end(); tab2->begin(); - tab2->label("Reconstruct"); + tab2->label("Extract"); resetHeight(); - place("binning", TOGGLE_DEACTIVATE); - place("box_size", TOGGLE_DEACTIVATE); - place("crop_size", TOGGLE_DEACTIVATE); + place("box_size_angst", TOGGLE_DEACTIVATE); + place("precrop_size_angst", TOGGLE_DEACTIVATE); + place("binned_size_pix", TOGGLE_DEACTIVATE); current_y += STEPY /2 ; @@ -2881,7 +2929,7 @@ void JobWindow::initialiseTomoSubtomoWindow() current_y += STEPY /2 ; - place("do_stack2d", TOGGLE_DEACTIVATE); + place("subtomo_format", TOGGLE_DEACTIVATE); place("do_float16", TOGGLE_DEACTIVATE); tab2->end(); diff --git a/src/gui_jobwindow.h b/src/gui_jobwindow.h index 25c5be6d1..43de02a56 100644 --- a/src/gui_jobwindow.h +++ b/src/gui_jobwindow.h @@ -56,7 +56,7 @@ class JobWindow : public Fl_Box Fl_Group *tab1, *tab2, *tab3, *tab4, *tab5, *tab6, *tab7, *runtab; // Groups - Fl_Group *group0, *group1, *group2, *group3, *group4, *group5, *group6, *group7, *group8, *queue_group; + Fl_Group *group0, *group1, *group2, *group3, *group4, *group5, *group6, *group7, *group8, *group9, *queue_group; public: // Constructor with x, y, w, h and a title diff --git a/src/gui_mainwindow.cpp b/src/gui_mainwindow.cpp index 28d9326c2..b6d1d574d 100644 --- a/src/gui_mainwindow.cpp +++ b/src/gui_mainwindow.cpp @@ -1432,7 +1432,11 @@ void GuiMainWindow::cb_display_io_node_i() command += " --black " + manualpickjob.joboptions["black_val"].getString(); command += " --white " + manualpickjob.joboptions["white_val"].getString(); - if (manualpickjob.joboptions["do_startend"].getBoolean()) + if (manualpickjob.joboptions["do_lines"].getBoolean()) + { + command += " --pick_lines "; + } + else if (manualpickjob.joboptions["do_startend"].getBoolean()) { command += " --pick_start_end "; } @@ -1466,7 +1470,6 @@ void GuiMainWindow::cb_display_io_node_i() if (manualpickjob.joboptions["fn_color"].getString().length() > 0) command += " --color_star " + manualpickjob.joboptions["fn_color"].getString(); } - } else { @@ -2566,9 +2569,9 @@ Please also cite relevant papers when you used external programs or their algori * Postscript plots are made using CPlot2D from http://www.amzsaki.com\n\n\ \ About the start up screen:\n\n\ -The map shown is the cryo-EM map of a fungal pheromone receptor STE2 dimer\n\ -without G proteins. Application of Blush algorithm improved the map\n\ -from the left to the middle panel and allowed automatic chain tracing by ModelAngelo (right panel).\n\ +The image shown is a cryo-EM model of the dynein-dynactin complex on a microtubule resolved by \ +the Carter lab (MRC-LMB) using signal subtraction and local refinements in RELION: \ +Chaaban & Carter, 2022 (PMID: 36071160), Singh et al., 2024 (PMID: 38547289).\ ") ShowHelpText *help = new ShowHelpText(HELPTEXT); diff --git a/src/helix.cpp b/src/helix.cpp index 56760c902..21f875e5d 100644 --- a/src/helix.cpp +++ b/src/helix.cpp @@ -829,7 +829,11 @@ bool checkParametersFor3DHelicalReconstruction( if (z_percentage_min > z_percentage_max) { if (verboseOutput) - std::cout << " ERROR! The range of Z percentage is invalid! To decrease the lower bound, make maximum rise smaller or box size larger. To increase the upper bound, make the particle diameter (along with the box size) larger and the outer tube diameter smaller!" << std::endl; + { + std::cout << " z_percentage_min= " << z_percentage_min << " z_percentage_max= " << z_percentage_max << std::endl; + std::cout << " particle_diameter_A= " << particle_diameter_A << " tube_outer_diameter_A= " << tube_outer_diameter_A << " nr_units_min= " << nr_units_min << " box_len= " << box_len < z_percentage_max) ) { if (verboseOutput) - std::cout << " ERROR! Z percentage is out of range under current settings!" << std::endl; + { + std::cout << " z_percentage_min= " << z_percentage_min << " z_percentage_max= " << z_percentage_max << std::endl; + std::cout << " particle_diameter_A= " << particle_diameter_A << " tube_outer_diameter_A= " << tube_outer_diameter_A << " nr_units_min= " << nr_units_min << " box_len= " << box_len <0 + // twist_1-start = (twist-360)/N if twist<0 + rise *= helical_nstart; + twist *= helical_nstart; + while (twist > 180.) twist -= 360.; + while (twist < -180.) twist += 360.; + +} + //#define DEBUG_HELICAL_UPDATE_ANGULAR_PRIORS void updatePriorsForOneHelicalTube( std::vector& list, @@ -4072,6 +4103,7 @@ void updatePriorsForOneHelicalTube( RFLOAT sigma_segment_dist, std::vector helical_rise, std::vector helical_twist, + int helical_nstart, bool is_3D_data, bool do_auto_refine, RFLOAT sigma2_rot, // KThurber @@ -4134,15 +4166,24 @@ void updatePriorsForOneHelicalTube( nr_wrong_polarity = nr_opposite_polarity - 1; // Change the polarity of the entire helix if psi_flip_ratio is larger than 0.5 - if (psi_flip_ratio > 0.5) - { - for (int id = sid; id <= eid; id++) - { - flipPsiTiltForHelicalSegment(list[id].psi_prior_deg, list[id].tilt_prior_deg, - list[id].psi_prior_deg, list[id].tilt_prior_deg); - list[id].psi_flip_ratio = (1. - psi_flip_ratio); - } - } + if (psi_flip_ratio > 0.5) + { + for (int id = sid; id <= eid; id++) + { + flipPsiTiltForHelicalSegment(list[id].psi_prior_deg, list[id].tilt_prior_deg, + list[id].psi_prior_deg, list[id].tilt_prior_deg); + flipPsiTiltForHelicalSegment(list[id].psi_deg, list[id].tilt_deg, + list[id].psi_deg, list[id].tilt_deg); + list[id].psi_flip_ratio = (1. - psi_flip_ratio); + } + } + else + { + for (int id = sid; id <= eid; id++) + { + list[id].psi_flip_ratio = psi_flip_ratio; + } + } // Calculate new distance-averaged angular priors // SHWS 27042020: do two passes: one normal and one with opposite distances and find out which one is the best @@ -4181,9 +4222,9 @@ void updatePriorsForOneHelicalTube( sum_ang_vec = this_ang_vec * this_w; // rotation angle all new KThurber - this_rot = list[id].rot_deg; // KThurber - this_rot_vec(0) = cos(DEG2RAD(this_rot)); - this_rot_vec(1) = sin(DEG2RAD(this_rot)); + this_rot = list[id].rot_deg; // KThurber + this_rot_vec(0) = cos(DEG2RAD(helical_nstart * this_rot)); + this_rot_vec(1) = sin(DEG2RAD(helical_nstart * this_rot)); sum_rot_vec = this_rot_vec * this_w; // for adjusting rot angle by shift along helix center_x_helix = list[id].dx_A * cos(DEG2RAD(this_psi)) - list[id].dy_A * sin(DEG2RAD(this_psi)); @@ -4237,13 +4278,15 @@ void updatePriorsForOneHelicalTube( // In the second pass, check the direction from large to small distances RFLOAT sign = (iflip == 1) ? 1. : -1.; - this_rot = list[idd].rot_deg + sign*(180./pitch)*(this_pos - center_pos - this_x_helix + center_x_helix); + this_rot = list[idd].rot_deg + sign*(180./pitch)*(this_pos - center_pos - this_x_helix + center_x_helix); } else - this_rot = list[idd].rot_deg; + { + this_rot = list[idd].rot_deg; + } - this_rot_vec(0) = cos(DEG2RAD(this_rot)); - this_rot_vec(1) = sin(DEG2RAD(this_rot)); + this_rot_vec(0) = cos(DEG2RAD(helical_nstart * this_rot)); + this_rot_vec(1) = sin(DEG2RAD(helical_nstart * this_rot)); sum_rot_vec += this_rot_vec * this_w; this_psi = list[idd].psi_deg; @@ -4275,12 +4318,12 @@ void updatePriorsForOneHelicalTube( { sum_rot_vec(0) = sum_rot_vec(0) / length_rot_vec; sum_rot_vec(1) = sum_rot_vec(1) / length_rot_vec; - this_rot = RAD2DEG(acos(sum_rot_vec(0))); - if (sum_rot_vec(1) < 0.) - this_rot = -1. * this_rot; // if sign negative, angle is negative + this_rot = RAD2DEG(atan2(sum_rot_vec(1), sum_rot_vec(0) )) / helical_nstart; } else - this_rot = list[id].rot_deg; // don't change prior if average fails + { + this_rot = list[id].rot_deg; // don't change prior if average fails + } // KThurber end new section if (iflip == 0) @@ -4370,7 +4413,7 @@ void updatePriorsForHelicalReconstruction( RFLOAT sigma_segment_dist, std::vector helical_rise, std::vector helical_twist, - int helical_nstart, + int helical_nstart, bool is_3D_data, bool do_auto_refine, RFLOAT sigma2_rot, @@ -4419,16 +4462,9 @@ void updatePriorsForHelicalReconstruction( if (helical_nstart > 1) { // Assume same N-start for all classes - // Shaoda's formula (which need to be inverted, as we want original N-start rise and twist back) - // rise_1-start = rise / N - // twist_1-start = (twist+360)/N if twist>0 - // twist_1-start = (twist-360)/N if twist<0 - for (int iclass=0; iclass < helical_rise.size(); iclass++) { - helical_rise[iclass] *= helical_nstart; - RFLOAT aux = helical_twist[iclass] * helical_nstart; - helical_twist[iclass] = (aux > 360.) ? aux - 360. : aux + 360.; + getNstartHelicalTwistAndRise(helical_twist[iclass], helical_rise[iclass], helical_nstart); if (verb > 0) std::cout << " + for rotational priors go back to " << helical_nstart << "-start helical twist= " << helical_twist[iclass] << " and rise= " << helical_rise[iclass] << std::endl; } @@ -4505,7 +4541,7 @@ void updatePriorsForHelicalReconstruction( // Real work... bool reverse_direction; - updatePriorsForOneHelicalTube(list, sid, eid, nr_opposite_polarity, reverse_direction, sigma_segment_dist, helical_rise, helical_twist, + updatePriorsForOneHelicalTube(list, sid, eid, nr_opposite_polarity, reverse_direction, sigma_segment_dist, helical_rise, helical_twist,helical_nstart, is_3D_data, do_auto_refine, sigma2_rot, sigma2_tilt, sigma2_psi, sigma2_offset); total_opposite_polarity += nr_opposite_polarity; if (reverse_direction) total_opposite_rot += 1; @@ -4520,7 +4556,7 @@ void updatePriorsForHelicalReconstruction( MD.setValue(EMDL_ORIENT_TILT_PRIOR, list[id].tilt_prior_deg, list[id].MDobjectID); MD.setValue(EMDL_ORIENT_PSI_PRIOR, list[id].psi_prior_deg, list[id].MDobjectID); MD.setValue(EMDL_ORIENT_PSI_PRIOR_FLIP_RATIO, list[id].psi_flip_ratio, list[id].MDobjectID); - MD.setValue(EMDL_ORIENT_ROT_PRIOR, list[id].rot_prior_deg, list[id].MDobjectID); // KThurber + MD.setValue(EMDL_ORIENT_ROT_PRIOR, list[id].rot_prior_deg, list[id].MDobjectID); // KThurber MD.setValue(EMDL_ORIENT_ORIGIN_X_ANGSTROM, list[id].dx_prior_A, list[id].MDobjectID); MD.setValue(EMDL_ORIENT_ORIGIN_Y_ANGSTROM, list[id].dy_prior_A, list[id].MDobjectID); if (is_3D_data) diff --git a/src/helix.h b/src/helix.h index 18af6483b..e537cabff 100644 --- a/src/helix.h +++ b/src/helix.h @@ -210,7 +210,8 @@ void extractHelicalSegmentsFromTubes_Multiple( RFLOAT Ydim, RFLOAT box_size_pix, bool bimodal_angular_priors = true, - bool cut_into_segments = true); + bool cut_into_segments = true, + RFLOAT tilt_prior = 90.); void convertHelicalTubeCoordsToMetaDataTable( FileName& fn_in, @@ -252,6 +253,8 @@ void removeBadPsiHelicalSegmentsFromDataStar( FileName& fn_out, RFLOAT max_dev_deg = 15.); +RFLOAT calculateTiltPriorFromPsi(RFLOAT psi, RFLOAT tilt_angle, RFLOAT tilt_axis); + void convertHelicalSegmentCoordsToStarFile_Multiple( FileName& suffix_coords, FileName& suffix_out, @@ -428,7 +431,7 @@ class HelicalSegmentPriorInfoEntry ~HelicalSegmentPriorInfoEntry() { clear(); }; - void checkPsiPolarity(); + void checkPsiPolarity(); bool operator<(const HelicalSegmentPriorInfoEntry &rhs) const; }; @@ -440,6 +443,11 @@ void flipPsiTiltForHelicalSegment( RFLOAT& new_psi, RFLOAT& new_tilt); +void getNstartHelicalTwistAndRise(RFLOAT &twist, + RFLOAT &rise, + int helical_nstart); + + void updatePriorsForOneHelicalTube( std::vector& list, int sid, @@ -449,6 +457,7 @@ void updatePriorsForOneHelicalTube( RFLOAT sigma_segment_dist, std::vector helical_rise, std::vector helical_twist, + int nfold_ambiguity, bool is_3D_data, bool do_auto_refine, RFLOAT sigma2_rot, // KThurber diff --git a/src/image.h b/src/image.h index 667e72aba..ca2a698ef 100644 --- a/src/image.h +++ b/src/image.h @@ -302,6 +302,16 @@ class fImageHandler fileName = fileName.addExtension(ext_name); } + // A ".gain" reference is a TIFF. RELION already assumes this in + // EERRenderer::loadEERGain (which appends ":tif" for .gain); make the + // generic image path assume the same, so a TIFF gain with a .gain + // extension also reads for non-EER (e.g. TIFF) movies and in Bayesian + // Polishing, instead of falling through to the SPIDER reader. + // See https://github.com/3dem/relion/pull/1346 and the CCPEM thread: + // https://www.jiscmail.ac.uk/cgi-bin/wa-jisc.exe?A2=ind2605&L=CCPEM&O=D&P=34021 + if (ext_name == "gain") + ext_name = "tif"; + isTiff = ext_name.contains("tif"); // Open image file diff --git a/src/jaz/scripts/BP_test.cpp b/src/jaz/scripts/BP_test.cpp deleted file mode 100644 index 10cd86d2c..000000000 --- a/src/jaz/scripts/BP_test.cpp +++ /dev/null @@ -1,374 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - -#define INPUT_PRECISION float -#define OUTPUT_PRECISION float - -int main(int argc, char *argv[]) -{ - const int s = 180; - const int sh = s/2 + 1; - const int num_observations = 100000; - const int num_shells = 5; - const int num_spheres = 2 * num_shells - 1; - const int num_threads = 6; - const double outer_radius = s / 2; - - const std::string tag = "100k_backward_noxg"; - - const double SNR = 1.0; - const bool forward = false; - const bool explicit_gridding = false; - const bool legacy_backprojector = false; - const bool wrap_voxels = false; - - std::vector sphere_radius(num_spheres); - std::vector sphere_scale(num_spheres); - - for (int i = 0; i < num_spheres; i++) - { - const double r = (i + 1.0) * outer_radius / num_spheres; - sphere_radius[i] = r; - sphere_scale[i] = 1 - 2 * (i % 2); - } - - BufferedImage observation(s,s); - - for (int y = 0; y < s; y++) - for (int x = 0; x < s; x++) - { - double sum = 0.0; - - const double xx = x < s/2? x : x - s; - const double yy = y < s/2? y : y - s; - const double r2 = xx*xx + yy*yy; - - for (int i = 0; i < num_spheres; i++) - { - const double r2s = sphere_radius[i] * sphere_radius[i]; - const double d2 = r2s - r2; - - if (d2 > 0.0) - { - const double l = 2.0 * sqrt(d2); - sum += sphere_scale[i] * l; - } - } - - observation(x,y) = sum; - } - - observation.write("observation_"+tag+".mrc"); - - BufferedImage> observation_FS; - FFT::FourierTransform(observation, observation_FS, FFT::Both); - - BufferedImage ctf(sh,s); - ctf.fill(1); - - BufferedImage> data(sh,s,s); - BufferedImage weight(sh,s,s), spreading_function(sh,s,s); - - data.fill(tComplex(0,0)); - weight.fill(0); - spreading_function.fill(0); - - BackProjector backprojector; - Image obervation_FS_legacy; - Image ctf_legacy; - - if (legacy_backprojector) - { - observation_FS.copyTo(obervation_FS_legacy); - ctf.copyTo(ctf_legacy); - - backprojector = BackProjector(s, 3, "C1", TRILINEAR, 1, 10, 0, 1.9, 15, 2, true); - backprojector.initZeros(-1); - } - - Log::beginProgress("Backprojecting observations", num_observations); - - for (int i = 0; i < num_observations; i++) - { - Log::updateProgress(i); - - const double phi = 2.0 * PI * rand() / (double)RAND_MAX; - const double psi = 2.0 * PI * rand() / (double)RAND_MAX; - const double tilt = (PI/2.0) * sin(PI * rand() / (double)RAND_MAX - PI/2.0); - - d4Matrix proj = EulerDynamo::anglesToMatrix4(phi, tilt, psi); - - if (legacy_backprojector) - { - Matrix2D A(3,3); - - for (int r = 0; r < 3; r++) - for (int c = 0; c < 3; c++) - { - A(r,c) = proj(r,c); - } - - backprojector.set2DFourierTransform(obervation_FS_legacy(), A, &ctf_legacy()); - } - else - { - if (forward) - { - if (wrap_voxels) - { - FourierBackprojection::backprojectSlice_forward_wrap( - observation_FS, ctf, proj, - data, weight); - } - else - { - ClippedPointInsertion clippedInsertion; - - FourierBackprojection::backprojectSlice_forward( - clippedInsertion, observation_FS, ctf, proj, - data, weight); - } - } - else - { - FourierBackprojection::backprojectSlice_backward( - observation_FS, ctf, proj, - data, weight, num_threads); - - if (explicit_gridding) - { - FourierBackprojection::backprojectSpreadingFunction( - proj, spreading_function); - } - } - } - } - - Log::endProgress(); - - - BufferedImage data_div_RS(s,s,s); - - - - if (legacy_backprojector) - { - Image vol_xmipp; - vol_xmipp().initZeros(s, s, s); - vol_xmipp().setXmippOrigin(); - - MultidimArray tau2; - - backprojector.reconstruct(vol_xmipp(), 10, false, tau2); - - data_div_RS.copyDataAndSizeFrom(vol_xmipp); - } - else - { - data.writeVtk("data_"+tag+".vtk"); - - BufferedImage data_RS(s,s,s); - - if (forward || !explicit_gridding) - { - std::cout << "Reconstruction::griddingCorrect3D_sinc2" << std::endl; - Reconstruction::griddingCorrect3D_sinc2( - data, data_RS, - true, 1); - } - else - { - Reconstruction::griddingCorrect3D( - data, spreading_function, // in - data_RS, // out - true, num_threads); - } - - Reconstruction::ctfCorrect3D_Wiener( - data_RS, weight, // in - data_div_RS, // out - 1.0 / SNR, num_threads); - } - - Reconstruction::taper(data_div_RS, 10, true, num_threads); - - data_div_RS.write("reconstruction_"+tag+".mrc"); - - - const int num_predictions = 10; - - BufferedImage predictions(s,s,num_predictions); - - for (int i = 0; i < num_predictions; i++) - { - BufferedImage> data_div_FS; - FFT::FourierTransform(data_div_RS, data_div_FS); - - Centering::shiftInSitu(data_div_FS); - - const double phi = 2.0 * PI * rand() / (double)RAND_MAX; - const double psi = 2.0 * PI * rand() / (double)RAND_MAX; - const double tilt = (PI/2.0) * sin(PI * rand() / (double)RAND_MAX - PI/2.0); - - d4Matrix proj = EulerDynamo::anglesToMatrix4(phi, tilt, psi); - - - BufferedImage prediction(sh,s), psf(sh,s); - - ForwardProjection::forwardProject_withPSF(data_div_FS, {proj}, prediction, psf, 1); - - BufferedImage predictionReal(s,s); - - Reconstruction::correctStack(prediction, psf, predictionReal, true, 1); - - predictions.getSliceRef(i).copyFrom(predictionReal); - } - - predictions.write("predictions_"+tag+".mrc"); - - std::vector radial_mean(sh, 0.0); - std::vector radial_count(sh, 0.0); - - for (long int z = 0; z < s; z++) - for (long int y = 0; y < s; y++) - for (long int x = 0; x < s; x++) - { - const double xx = x - s/2; - const double yy = y - s/2; - const double zz = z - s/2; - - const double r = sqrt(xx*xx + yy*yy + zz*zz); - const int ri = (int) (r + 0.5); - - if (ri < sh) - { - radial_mean[ri] += data_div_RS(x,y,z); - radial_count[ri] += 1; - } - } - - for (int r = 0; r < sh; r++) - { - if (radial_count[r] > 0.0) - { - radial_mean[r] /= radial_count[r]; - } - } - - std::vector radial_variance(sh, 0.0); - - for (long int z = 0; z < s; z++) - for (long int y = 0; y < s; y++) - for (long int x = 0; x < s; x++) - { - const double xx = x - s/2; - const double yy = y - s/2; - const double zz = z - s/2; - - const double r = sqrt(xx*xx + yy*yy + zz*zz); - const int ri = (int) (r + 0.5); - - if (ri < sh) - { - const double d = data_div_RS(x,y,z) - radial_mean[r]; - - radial_variance[ri] += d * d; - } - } - - for (int r = 0; r < sh; r++) - { - if (radial_count[r] > 1.0) - { - radial_variance[r] /= radial_count[r] - 1.0; - } - } - - double plot_mean = 0.0; - - for (int r = 0; r < sh; r++) - { - plot_mean += radial_mean[r]; - } - - plot_mean /= sh; - - double plot_power = 0.0; - - for (int r = 0; r < sh; r++) - { - const double d = radial_mean[r] - plot_mean; - plot_power += d * d; - } - - const double plot_scale = 1.0 / sqrt(plot_power/sh); - - - std::vector curves(3); - - for (int i = 0; i < 3; i++) - { - CDataSet& curve = curves[i]; - - curve.SetDrawMarker(false); - curve.SetDrawLine(true); - curve.SetLineWidth(0.5); - - } - - curves[0].SetDatasetColor(0,0,0); - curves[1].SetDatasetColor(0.5,0.5,0.5); - curves[2].SetDatasetColor(0.5,0.5,0.5); - - for (int r = 0; r < sh; r++) - { - const double mu = plot_scale * (radial_mean[r] - plot_mean); - const double sd = plot_scale * sqrt(radial_variance[r]); - - curves[0].AddDataPoint(CDataPoint(r, mu)); - curves[1].AddDataPoint(CDataPoint(r, mu - sd)); - curves[2].AddDataPoint(CDataPoint(r, mu + sd)); - } - - CPlot2D plot(tag); - - for (int i = 2; i >= 0; i--) - { - plot.AddDataSet(curves[i]); - } - - std::string title = tag; - - for (int i = 0; i < title.length(); i++) - { - if (title[i] == '_') - { - title[i] = ' '; - } - } - - plot.SetTitle(title); - plot.SetXAxisTitle("r"); - plot.SetYAxisTitle("mean"); - - plot.SetViewArea(0,-2,sh,3); - - plot.OutputPostScriptPlot("reconstruction_"+tag+".eps"); - - return 0; -} diff --git a/src/jaz/scripts/CMakeLists.txt b/src/jaz/scripts/CMakeLists.txt deleted file mode 100755 index e69de29bb..000000000 diff --git a/src/jaz/scripts/CTFPQ_test.cpp b/src/jaz/scripts/CTFPQ_test.cpp deleted file mode 100644 index 2fd136ff0..000000000 --- a/src/jaz/scripts/CTFPQ_test.cpp +++ /dev/null @@ -1,479 +0,0 @@ -#include -#include -#include -#include -#include -#include - - - - -void applyCTFPandCTFQ_original( - MultidimArray &Fin, CTF &ctf, FourierTransformer &transformer, - MultidimArray &outP, MultidimArray &outQ, bool skip_mask, - int newbox, int nr_sectors, bool is_reverse, - double angpix, double mask_diameter, double width_mask_edge) -{ - outP.resize(Fin); - outQ.resize(Fin); - float angle_step = 180./nr_sectors; - - for (float angle = 0.; angle < 180.; angle +=angle_step) - { - MultidimArray CTFP(Fin), Fapp(Fin); - MultidimArray Iapp(YSIZE(Fin), YSIZE(Fin)); - - // Two passes: one for CTFP, one for CTFQ - for (int ipass = 0; ipass < 2; ipass++) - { - bool is_my_positive = (ipass == 1) ? is_reverse : !is_reverse; - - // Get CTFP and multiply the Fapp with it - ctf.getCTFPImage(CTFP, YSIZE(Fin), YSIZE(Fin), angpix, is_my_positive, angle); - - Fapp = Fin * CTFP; // element-wise complex multiplication! - - if (!skip_mask) - { - // inverse transform and mask out the particle.... - CenterFFTbySign(Fapp); - transformer.inverseFourierTransform(Fapp, Iapp); - - softMaskOutsideMap(Iapp, ROUND(mask_diameter/(angpix*2.)), (RFLOAT)width_mask_edge); - - // Re-box to a smaller size if necessary.... - if (newbox > 0 && newbox < YSIZE(Fin)) - { - Iapp.setXmippOrigin(); - Iapp.window(FIRST_XMIPP_INDEX(newbox), FIRST_XMIPP_INDEX(newbox), - LAST_XMIPP_INDEX(newbox), LAST_XMIPP_INDEX(newbox)); - } - - // Back into Fourier-space - transformer.FourierTransform(Iapp, Fapp, false); // false means: leave Fapp in the transformer - CenterFFTbySign(Fapp); - } - - // First time round: resize the output arrays - if (ipass == 0 && fabs(angle) < XMIPP_EQUAL_ACCURACY) - { - outP.resize(Fapp); - outQ.resize(Fapp); - } - - // Now set back the right parts into outP (first pass) or outQ (second pass) - float anglemin = angle + 90. - (0.5*angle_step); - float anglemax = angle + 90. + (0.5*angle_step); - - // angles larger than 180 - bool is_sector_reverse = false; - - if (anglemin >= 180.) - { - anglemin -= 180.; - anglemax -= 180.; - is_sector_reverse = true; - } - - MultidimArray *myCTFPorQ, *myCTFPorQb; - - if (is_sector_reverse) - { - myCTFPorQ = (ipass == 0) ? &outQ : &outP; - myCTFPorQb = (ipass == 0) ? &outP : &outQ; - } - else - { - myCTFPorQ = (ipass == 0) ? &outP : &outQ; - myCTFPorQb = (ipass == 0) ? &outQ : &outP; - } - - // Deal with sectors with the Y-axis in the middle of the sector... - bool do_wrap_max = false; - if (anglemin < 180. && anglemax > 180.) - { - anglemax -= 180.; - do_wrap_max = true; - } - - // use radians instead of degrees - anglemin = DEG2RAD(anglemin); - anglemax = DEG2RAD(anglemax); - FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM2D(CTFP) - { - RFLOAT x = (RFLOAT)jp; - RFLOAT y = (RFLOAT)ip; - RFLOAT myangle = (x*x+y*y > 0) ? acos(y/sqrt(x*x+y*y)) : 0; // dot-product with Y-axis: (0,1) - - // Only take the relevant sector now... - if (do_wrap_max) - { - if (myangle >= anglemin) - { - DIRECT_A2D_ELEM(*myCTFPorQ, i, j) = DIRECT_A2D_ELEM(Fapp, i, j); - } - else if (myangle < anglemax) - { - DIRECT_A2D_ELEM(*myCTFPorQb, i, j) = DIRECT_A2D_ELEM(Fapp, i, j); - } - } - else - { - if (myangle >= anglemin && myangle < anglemax) - { - DIRECT_A2D_ELEM(*myCTFPorQ, i, j) = DIRECT_A2D_ELEM(Fapp, i, j); - } - } - } - } - } -} - - - -void applyCTFPandCTFQ_logged( - MultidimArray &Fin, CTF &ctf, FourierTransformer &transformer, - MultidimArray &outP, MultidimArray &outQ, bool skip_mask, - int newbox, int nr_sectors, bool is_reverse, - double angpix, double mask_diameter, double width_mask_edge) -{ - outP.resize(Fin); - outQ.resize(Fin); - float angle_step = 180./nr_sectors; - - outP.initZeros(); - outQ.initZeros(); - - RawImage(outP).writeVtk("initial_outP.vtk"); - RawImage(outQ).writeVtk("initial_outQ.vtk"); - - for (float angle = 0.; angle < 180.; angle +=angle_step) - { - std::cout << "angle = " << angle << std::endl; - - - MultidimArray CTFP(Fin), Fapp(Fin); - MultidimArray Iapp(YSIZE(Fin), YSIZE(Fin)); - - // Two passes: one for CTFP, one for CTFQ - for (int ipass = 0; ipass < 2; ipass++) - { - std::cout << "ipass = " << ipass << std::endl; - - bool is_my_positive = (ipass == 1) ? is_reverse : !is_reverse; - - // Get CTFP and multiply the Fapp with it - ctf.getCTFPImage(CTFP, YSIZE(Fin), YSIZE(Fin), angpix, is_my_positive, angle); - - Fapp = Fin * CTFP; // element-wise complex multiplication! - - RawImage(CTFP).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_CTFP.vtk"); - RawImage(Fapp).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_Fapp_0.vtk"); - - if (!skip_mask) - { - // inverse transform and mask out the particle.... - CenterFFTbySign(Fapp); - transformer.inverseFourierTransform(Fapp, Iapp); - - softMaskOutsideMap(Iapp, ROUND(mask_diameter/(angpix*2.)), (RFLOAT)width_mask_edge); - - // Re-box to a smaller size if necessary.... - if (newbox > 0 && newbox < YSIZE(Fin)) - { - Iapp.setXmippOrigin(); - Iapp.window(FIRST_XMIPP_INDEX(newbox), FIRST_XMIPP_INDEX(newbox), - LAST_XMIPP_INDEX(newbox), LAST_XMIPP_INDEX(newbox)); - } - - // Back into Fourier-space - transformer.FourierTransform(Iapp, Fapp, false); // false means: leave Fapp in the transformer - CenterFFTbySign(Fapp); - } - - RawImage(Fapp).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_Fapp_1.vtk"); - - // Now set back the right parts into outP (first pass) or outQ (second pass) - float anglemin = angle + 90. - (0.5*angle_step); - float anglemax = angle + 90. + (0.5*angle_step); - - // angles larger than 180 - bool is_sector_reverse = false; - - if (anglemin >= 180.) - { - anglemin -= 180.; - anglemax -= 180.; - is_sector_reverse = true; - } - - std::cout << "\tanglemin = " << anglemin << std::endl; - std::cout << "\tanglemax = " << anglemax << std::endl; - std::cout << "\tis_sector_reverse = " << is_sector_reverse << std::endl; - - MultidimArray *myCTFPorQ, *myCTFPorQb; - - if (is_sector_reverse) - { - myCTFPorQ = (ipass == 0) ? &outQ : &outP; - myCTFPorQb = (ipass == 0) ? &outP : &outQ; - } - else - { - myCTFPorQ = (ipass == 0) ? &outP : &outQ; - myCTFPorQb = (ipass == 0) ? &outQ : &outP; - } - - // Deal with sectors with the Y-axis in the middle of the sector... - bool do_wrap_max = false; - if (anglemin < 180. && anglemax > 180.) - { - anglemax -= 180.; - do_wrap_max = true; - } - - std::cout << "\tdo_wrap_max = " << do_wrap_max << std::endl; - - // use radians instead of degrees - anglemin = DEG2RAD(anglemin); - anglemax = DEG2RAD(anglemax); - FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM2D(CTFP) - { - RFLOAT x = (RFLOAT)jp; - RFLOAT y = (RFLOAT)ip; - RFLOAT myangle = (x*x+y*y > 0) ? acos(y/sqrt(x*x+y*y)) : 0; // dot-product with Y-axis: (0,1) - - // Only take the relevant sector now... - if (do_wrap_max) - { - if (myangle >= anglemin) - { - DIRECT_A2D_ELEM(*myCTFPorQ, i, j) = DIRECT_A2D_ELEM(Fapp, i, j); - } - else if (myangle < anglemax) - { - DIRECT_A2D_ELEM(*myCTFPorQb, i, j) = DIRECT_A2D_ELEM(Fapp, i, j); - } - } - else - { - if (myangle >= anglemin && myangle < anglemax) - { - DIRECT_A2D_ELEM(*myCTFPorQ, i, j) = DIRECT_A2D_ELEM(Fapp, i, j); - } - } - } - - RawImage(outP).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_outP.vtk"); - RawImage(outQ).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_outQ.vtk"); - } - } -} - -void applyCTFPandCTFQ_refac( - MultidimArray &Fin, CTF &ctf, FourierTransformer &transformer, - MultidimArray &outP, MultidimArray &outQ, bool skip_mask, - int newbox, int nr_sectors, bool is_reverse, - double angpix, double mask_diameter, double width_mask_edge) -{ - outP.resize(Fin); - outQ.resize(Fin); - float angle_step = 180./nr_sectors; - - outP.initZeros(); - outQ.initZeros(); - - RawImage(outP).writeVtk("initial_outP.vtk"); - RawImage(outQ).writeVtk("initial_outQ.vtk"); - - for (float angle = 0.; angle < 180.; angle +=angle_step) - { - std::cout << "angle = " << angle << std::endl; - - - MultidimArray CTFP(Fin), Fapp(Fin); - MultidimArray Iapp(YSIZE(Fin), YSIZE(Fin)); - - // Two passes: one for CTFP, one for CTFQ - for (int ipass = 0; ipass < 2; ipass++) - { - std::cout << "ipass = " << ipass << std::endl; - - bool is_my_positive = (ipass == 1) ? is_reverse : !is_reverse; - - // Get CTFP and multiply the Fapp with it - ctf.getCTFPImage(CTFP, YSIZE(Fin), YSIZE(Fin), angpix, is_my_positive, angle); - - Fapp = Fin * CTFP; // element-wise complex multiplication! - - RawImage(CTFP).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_CTFP.vtk"); - RawImage(Fapp).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_Fapp_0.vtk"); - - if (!skip_mask) - { - // inverse transform and mask out the particle.... - CenterFFTbySign(Fapp); - transformer.inverseFourierTransform(Fapp, Iapp); - - softMaskOutsideMap(Iapp, ROUND(mask_diameter/(angpix*2.)), (RFLOAT)width_mask_edge); - - // Re-box to a smaller size if necessary.... - if (newbox > 0 && newbox < YSIZE(Fin)) - { - Iapp.setXmippOrigin(); - Iapp.window(FIRST_XMIPP_INDEX(newbox), FIRST_XMIPP_INDEX(newbox), - LAST_XMIPP_INDEX(newbox), LAST_XMIPP_INDEX(newbox)); - } - - // Back into Fourier-space - transformer.FourierTransform(Iapp, Fapp, false); // false means: leave Fapp in the transformer - CenterFFTbySign(Fapp); - } - - RawImage(Fapp).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_Fapp_1.vtk"); - - // Now set back the right parts into outP (first pass) or outQ (second pass) - float anglemin = angle + 90. - (0.5*angle_step); - float anglemax = angle + 90. + (0.5*angle_step); - - // angles larger than 180 - bool is_sector_reverse = false; - - if (anglemin >= 180.) - { - anglemin -= 180.; - anglemax -= 180.; - is_sector_reverse = true; - } - - std::cout << "\tanglemin = " << anglemin << std::endl; - std::cout << "\tanglemax = " << anglemax << std::endl; - std::cout << "\tis_sector_reverse = " << is_sector_reverse << std::endl; - - MultidimArray *myCTFPorQ, *myCTFPorQb; - - if (is_sector_reverse) - { - myCTFPorQ = (ipass == 0) ? &outQ : &outP; - myCTFPorQb = (ipass == 0) ? &outP : &outQ; - } - else - { - myCTFPorQ = (ipass == 0) ? &outP : &outQ; - myCTFPorQb = (ipass == 0) ? &outQ : &outP; - } - - // Deal with sectors with the Y-axis in the middle of the sector... - bool do_wrap_max = false; - if (anglemin < 180. && anglemax > 180.) - { - anglemax -= 180.; - do_wrap_max = true; - } - - std::cout << "\tdo_wrap_max = " << do_wrap_max << std::endl; - - // use radians instead of degrees - anglemin = DEG2RAD(anglemin); - anglemax = DEG2RAD(anglemax); - FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM2D(CTFP) - { - RFLOAT x = (RFLOAT)jp; - RFLOAT y = (RFLOAT)ip; - RFLOAT myangle = (x*x+y*y > 0) ? acos(y/sqrt(x*x+y*y)) : 0; // dot-product with Y-axis: (0,1) - - // Only take the relevant sector now... - if (do_wrap_max) - { - if (myangle >= anglemin) - { - DIRECT_A2D_ELEM(*myCTFPorQ, i, j) = DIRECT_A2D_ELEM(Fapp, i, j); - } - else if (myangle < anglemax) - { - DIRECT_A2D_ELEM(*myCTFPorQb, i, j) = DIRECT_A2D_ELEM(Fapp, i, j); - } - } - else - { - if (myangle >= anglemin && myangle < anglemax) - { - DIRECT_A2D_ELEM(*myCTFPorQ, i, j) = DIRECT_A2D_ELEM(Fapp, i, j); - } - } - } - - RawImage(outP).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_outP.vtk"); - RawImage(outQ).writeVtk(ZIO::itoa(angle)+"_"+ZIO::itoa(ipass)+"_outQ.vtk"); - } - } -} - - -int main() -{ - const int s = 180; - const int sh = s/2 + 1; - - const bool skip_mask = false; - const int newbox = s; - const int nr_sectors = 2; - const bool is_reverse = false; - const double angpix = 1; - const double mask_diameter = s/2.0; - const double width_mask_edge = 3.0; - - CTF ctf; - ctf.setValues(8000, 12000, 30, 300, 2.7, 0.1, 0, 1, 0); - - - MultidimArray obs_xmipp(s,s,sh), obsP_xmipp, obsQ_xmipp; - - FourierTransformer transformer; - - BufferedImage obs = ImageNoise::generateSmoothFourierNoise(s, s/4.0); - - obs.writeVtk("obs.vtk"); - obs.copyTo(obs_xmipp); - - applyCTFPandCTFQ_logged( - obs_xmipp, ctf, transformer, obsP_xmipp, obsQ_xmipp, skip_mask, - newbox, nr_sectors, is_reverse, angpix, mask_diameter, width_mask_edge); - - RawImage obsP(obsP_xmipp); - RawImage obsQ(obsQ_xmipp); - - obs.writeVtk("obs.vtk"); - obsP.writeVtk("obsP.vtk"); - obsQ.writeVtk("obsQ.vtk"); - - (obsP + obsQ).writeVtk("obsPplusQ.vtk"); - - BufferedImage flatCTF = obs; - - RFLOAT bs = (RFLOAT)s * angpix; - - for (int y = 0; y < s; y++) - for (int x = 0; x < sh; x++) - { - const double xx = x / bs; - const double yy = (y < s/2? y : y - s) / bs; - - flatCTF(x,y) *= ctf.getCTF(xx,yy); - } - - flatCTF.writeVtk("obsCTF.vtk"); - - - MultidimArray Fctf(s,sh); - - ctf.applyWeightEwaldSphereCurvature_noAniso( - Fctf, s, s, angpix, mask_diameter); - - RawImage(Fctf).write("maskedCTF.mrc"); - - - - - return 0; -} diff --git a/src/jaz/scripts/add_subset.cpp b/src/jaz/scripts/add_subset.cpp deleted file mode 100644 index b4f471e3f..000000000 --- a/src/jaz/scripts/add_subset.cpp +++ /dev/null @@ -1,33 +0,0 @@ -#include -#include -#include -#include -#include -#include - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - if (argc < 3) - { - std::cerr << "usage: relion_exp_add_subset " << std::endl; - return -1; - } - - ParticleSet ps(argv[1], ""); - - std::cout << ps.partTable.numberOfObjects() << std::endl; - - ps.partTable.addLabel(EMDL_PARTICLE_RANDOM_SUBSET); - - for (int p = 0; p < ps.partTable.numberOfObjects(); p++) - { - ps.partTable.setValue(EMDL_PARTICLE_RANDOM_SUBSET, 1 + (rand()%2), p); - } - - ps.write(argv[2]); - - return 0; - -} diff --git a/src/jaz/scripts/add_tomogram_name.cpp b/src/jaz/scripts/add_tomogram_name.cpp deleted file mode 100644 index 0477c79e5..000000000 --- a/src/jaz/scripts/add_tomogram_name.cpp +++ /dev/null @@ -1,87 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - IOParser parser; - - std::string tableFn, inputFn, outputFn; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - inputFn = parser.getOption("--i", "Input particle set"); - tableFn = parser.getOption("--m", "Table mapping micrograph names (first column) to tomogram names (second column)"); - outputFn = parser.getOption("--o", "Output particle set"); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - std::map mic2tomo; - - std::ifstream ifs(tableFn); - - if (!ifs) - { - REPORT_ERROR_STR("Unable to read "+tableFn); - } - - std::string line; - - while (std::getline(ifs, line)) - { - std::stringstream sts(line); - std::string mic, tomo; - - sts >> mic; - sts >> tomo; - - std::cout << mic << " -> " << tomo << std::endl; - - mic2tomo[mic] = tomo; - } - - MetaDataTable opticsTable, particleTable; - - opticsTable.read(inputFn, "optics"); - particleTable.read(inputFn, "particles"); - - particleTable.addLabel(EMDL_TOMO_NAME); - particleTable.addLabel(EMDL_TOMO_TILT_SERIES_NAME); - - for (int p = 0; p < particleTable.numberOfObjects(); p++) - { - std::string mic = particleTable.getString(EMDL_MICROGRAPH_NAME, p); - - if (mic2tomo.find(mic) == mic2tomo.end()) - { - REPORT_ERROR_STR("Micrograph name '" << mic << "' not found in " - << tableFn); - } - - std::string tomo = mic2tomo[mic]; - - particleTable.setValue(EMDL_TOMO_NAME, tomo, p); - particleTable.setValue(EMDL_TOMO_TILT_SERIES_NAME, mic, p); - } - - std::ofstream ofs(outputFn); - - opticsTable.write(ofs); - particleTable.write(ofs); - - return 0; -} diff --git a/src/jaz/scripts/align_2d_classes.cpp b/src/jaz/scripts/align_2d_classes.cpp deleted file mode 100644 index a03a1a31e..000000000 --- a/src/jaz/scripts/align_2d_classes.cpp +++ /dev/null @@ -1,379 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - - -BufferedImage rotate(const RawImage& img, double phi); -BufferedImage flip_x(const RawImage& img); -BufferedImage correlate(const RawImage& img0, const RawImage& img1); -float max_correlation(const RawImage& img0, const RawImage& img1); - -int main(int argc, char *argv[]) -{ - std::string particlesFn, class_averages_filename, outDir; - double margin; - int num_threads; - bool flip_orientation, reorder, align_horizontally_only; - - - IOParser parser; - - try - { - IOParser parser; - - parser.setCommandLine(argc, argv); - - int general_section = parser.addSection("General options"); - - particlesFn = parser.getOption("--i", "Input file (e.g. run_it023_data.star)"); - class_averages_filename = parser.getOption("--ca", "Class averages stack"); - flip_orientation = parser.checkOption("--flip", "Rotate the initial alignment by 180°"); - align_horizontally_only = parser.checkOption("--horizontal_only", "Only align the biggest class horizontally, then exit"); - reorder = parser.checkOption("--sort", "Sort classes by descending cardinality"); - margin = textToDouble(parser.getOption("--m", "Margin around the particle [Px]", "20")); - - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - - outDir = ZIO::makeOutputDir(outDir); - - ObservationModel obs_model; - MetaDataTable particles_table; - ObservationModel::loadSafely(particlesFn, obs_model, particles_table); - - int max_class = -1; - - for (long int p = 0; p < particles_table.numberOfObjects(); p++) - { - const int class_id = particles_table.getIntMinusOne(EMDL_PARTICLE_CLASS, p); - - if (class_id > max_class) max_class = class_id; - } - - const int class_count = max_class + 1; - - if (class_count == 1) - { - Log::warn("1 class found"); - } - else - { - Log::print(ZIO::itoa(class_count)+" classes found"); - } - - - std::vector particle_count(class_count, 0); - - for (long int p = 0; p < particles_table.numberOfObjects(); p++) - { - const int class_id = particles_table.getIntMinusOne( - EMDL_PARTICLE_CLASS, p); - - particle_count[class_id]++; - } - - std::vector> particle_by_class(class_count); - - for (long int c = 0; c < class_count; c++) - { - particle_by_class[c].reserve(particle_count[c]); - } - - for (long int p = 0; p < particles_table.numberOfObjects(); p++) - { - const int class_id = particles_table.getIntMinusOne( - EMDL_PARTICLE_CLASS, p); - - particle_by_class[class_id].push_back(p); - } - - std::vector class_by_size = IndexSort::sortIndices(particle_count); - const int biggest_class = class_by_size[class_count-1]; - - - const int angle_samples_coarse = 36; - const int angle_samples_fine = 100; - - - BufferedImage class_averages; - class_averages.read(class_averages_filename); - - - std::vector angle_by_class(class_count, 0.0); - - BufferedImage template_slice; - - - // align biggest class to maximise horizontal symmetry - { - - - double best_phi_coarse = 0; - double best_phi_CC_coarse = 0; - - RawImage slice0 = class_averages.getSliceRef(biggest_class); - - - for (int ai = 0; ai < angle_samples_coarse; ai++) - { - const double phi = ai * 2.0 * PI / angle_samples_coarse; - - BufferedImage slice = rotate(slice0, phi); - BufferedImage flipped_slice = flip_x(slice); - - const double max_CC = max_correlation(slice, flipped_slice); - - if (max_CC > best_phi_CC_coarse) - { - best_phi_CC_coarse = max_CC; - best_phi_coarse = phi; - } - } - - double best_phi_fine = best_phi_coarse; - double best_phi_CC_fine = best_phi_CC_coarse; - - for (int ai = 0; ai < angle_samples_fine; ai++) - { - const double range = 2.0 * PI / angle_samples_coarse; - const double phi = best_phi_coarse + (2 * ai / (double) angle_samples_fine - 1) * range; - - BufferedImage slice = rotate(slice0, phi); - BufferedImage flipped_slice = flip_x(slice); - - const double max_CC = max_correlation(slice, flipped_slice); - - if (max_CC > best_phi_CC_fine) - { - best_phi_CC_fine = max_CC; - best_phi_fine = phi; - } - } - - if (flip_orientation) - { - best_phi_fine += PI; - - if (best_phi_fine > 2 * PI) - { - best_phi_fine -= 2 * PI; - } - } - - angle_by_class[biggest_class] = best_phi_fine; - - template_slice = rotate(slice0, best_phi_fine); - - slice0.write(outDir + "class_"+ZIO::itoa(biggest_class)+"_original.mrc"); - template_slice.write(outDir + "class_"+ZIO::itoa(biggest_class)+"_rotated.mrc"); - } - - - - if (align_horizontally_only) return 0; - - - BufferedImage class_averages_rotated = class_averages; - class_averages_rotated.getSliceRef(biggest_class).copyFrom(template_slice); - - - // align every other class against the biggest one - - for (int ci = 1; ci < class_count; ci++) - { - const int class_id = class_by_size[class_count - ci - 1]; - - Log::print("Aligning class " + ZIO::itoa(class_id)); - - - double best_phi_coarse = 0; - double best_phi_CC_coarse = 0; - - RawImage slice0 = class_averages.getSliceRef(class_id); - - for (int ai = 0; ai < angle_samples_coarse; ai++) - { - const double phi = ai * 2.0 * PI / angle_samples_coarse; - - BufferedImage slice = rotate(slice0, phi); - const double max_CC = max_correlation(slice, template_slice); - - if (max_CC > best_phi_CC_coarse) - { - best_phi_CC_coarse = max_CC; - best_phi_coarse = phi; - } - } - - double best_phi_fine = best_phi_coarse; - double best_phi_CC_fine = best_phi_CC_coarse; - - for (int ai = 0; ai < angle_samples_fine; ai++) - { - const double range = 2.0 * PI / angle_samples_coarse; - const double phi = best_phi_coarse + (2 * ai / (double) angle_samples_fine - 1) * range; - - BufferedImage slice = rotate(slice0, phi); - const double max_CC = max_correlation(slice, template_slice); - - if (max_CC > best_phi_CC_fine) - { - best_phi_CC_fine = max_CC; - best_phi_fine = phi; - } - } - - angle_by_class[class_id] = best_phi_fine; - - BufferedImage slice = rotate(slice0, best_phi_fine); - class_averages_rotated.getSliceRef(class_id).copyFrom(slice); - } - - class_averages_rotated.write(outDir+"class_averages_rotated.mrc"); - - - - for (long int p = 0; p < particles_table.numberOfObjects(); p++) - { - const int class_id = particles_table.getIntMinusOne(EMDL_PARTICLE_CLASS, p); - const double phi0 = particles_table.getDouble(EMDL_ORIENT_PSI, p); - - double phi1 = phi0 + RAD2DEG(angle_by_class[class_id]); - - if (phi1 > 360) phi1 -= 360; - - particles_table.setValue(EMDL_ORIENT_PSI, phi1, p); - } - - if (reorder) - { - std::vector new_class_id(class_count); - - for (int i = 0; i < class_count; i++) - { - new_class_id[class_by_size[i]] = class_count - i - 1; - } - - for (long int p = 0; p < particles_table.numberOfObjects(); p++) - { - const int class_id = particles_table.getIntMinusOne(EMDL_PARTICLE_CLASS, p); - - particles_table.setValue(EMDL_PARTICLE_CLASS, new_class_id[class_id] + 1, p); - } - } - - - - ObservationModel::saveNew( - particles_table, - obs_model.opticsMdt, - obs_model.generalMdt, - outDir+"rotated_particles.star"); - - - return 0; -} - - - -BufferedImage rotate(const RawImage& img, double phi) -{ - const int s = img.xdim; - const int m = s / 2; - - const d2Matrix A( - cos(phi), sin(phi), - -sin(phi), cos(phi) ); - - BufferedImage out(s,s); - - for (int y = 0; y < s; y++) - for (int x = 0; x < s; x++) - { - const d2Vector r0(x - m, y - m); - const d2Vector r1 = A * r0; - - out(x,y) = Interpolation::linearXY_clip(img, m + r1.x, m + r1.y); - } - - return out; -} - -BufferedImage flip_x(const RawImage& img) -{ - const int s = img.xdim; - - BufferedImage out(s,s); - - for (int y = 0; y < s; y++) - for (int x = 0; x < s; x++) - { - out(x,y) = img(s-x-1, y); - } - - return out; -} - -BufferedImage correlate(const RawImage& img0, const RawImage& img1) -{ - const int s = img0.xdim; - const int sh = s/2 + 1; - - BufferedImage img0_FS, img1_FS; - - FFT::FourierTransform(img0, img0_FS, FFT::Both); - FFT::FourierTransform(img1, img1_FS, FFT::Both); - - BufferedImage product(sh,s); - - for (int y = 0; y < s; y++) - for (int x = 0; x < sh; x++) - { - product(x,y) = img0_FS(x,y) * img1_FS(x,y).conj(); - } - - BufferedImage CC; - - FFT::inverseFourierTransform(product, CC, FFT::Both); - - return CC; -} - -float max_correlation(const RawImage& img0, const RawImage& img1) -{ - BufferedImage CC = correlate(img0, img1); - return Interpolation::discreteMaxXYV(CC)[2]; -} diff --git a/src/jaz/scripts/analyse_dual_contrast.cpp b/src/jaz/scripts/analyse_dual_contrast.cpp deleted file mode 100644 index cfdf3f059..000000000 --- a/src/jaz/scripts/analyse_dual_contrast.cpp +++ /dev/null @@ -1,822 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - -void compareAtomsByResidue( - const std::map>>& atoms_by_name_by_residue, - double coord_offset_pixels, - double pixel_size, - const RawImage& phase_map_RS, - const RawImage& amp_map_RS, - std::string out_path, - std::string tag, - bool images_are_premultiplied); - -void compareResidues( - const std::map>& atoms_by_residue, - double coord_offset_pixels, - double pixel_size, - const RawImage& phase_map_RS, - const RawImage& amp_map_RS, - std::string filename_out, - bool images_are_premultiplied); - -double computeShellAverage( - const RawImage& map_RS, - double r0, double r1) -{ - const int s = map_RS.xdim; - - double sum = 0.0; - double count = 0.0; - - for (int z = 0; z < s; z++) - for (int y = 0; y < s; y++) - for (int x = 0; x < s; x++) - { - const d3Vector r( - x - s/2, - y - s/2, - z - s/2); - - const double rl = r.length(); - - if (rl > r0 && rl < r1) - { - sum += map_RS(x,y,z); - count += 1.0; - } - } - - return sum / count; -} - -d2Vector computeUniformScaleAndIntercept( - const RawImage& phase_map_RS, - const RawImage& amp_map_RS) -{ - const int s = phase_map_RS.xdim; - - d2Matrix A(0,0,0,0); - d2Vector b(0,0); - - for (int z = 0; z < s; z++) - for (int y = 0; y < s; y++) - for (int x = 0; x < s; x++) - { - const d3Vector r( - x - s/2, - y - s/2, - z - s/2); - - if (r.length() >= s/2 - 10) continue; - - const double vp = phase_map_RS(x,y,z); - const double va = amp_map_RS(x,y,z); - - A(0,0) += vp * vp; - A(0,1) += vp * 1; - A(1,0) += 1 * vp; - A(1,1) += 1 * 1; - - b[0] += vp * va; - b[1] += va; - } - - d2Matrix Ainv = A; - Ainv.invert(); - - const d2Vector solution = Ainv * b; - const double optimal_scale = solution[0]; - const double optimal_offset = solution[1]; - - std::cout << "optimal scale = " << optimal_scale << std::endl; - std::cout << "optimal offset = " << optimal_offset << std::endl; - - return d2Vector(optimal_scale, optimal_offset); -} - -double computeUniformScale( - const RawImage& phase_map_FS, - const RawImage& amp_map_FS) -{ - const int sh = phase_map_FS.xdim; - const int s = phase_map_FS.ydim; - - double num = 0.0, denom = 0.0; - - for (int z = 0; z < s; z++) - for (int y = 0; y < s; y++) - for (int x = 0; x < sh; x++) - { - const d3Vector r( - x - s/2, - y - s/2, - z - s/2); - - if (r.length() >= s/4) continue; - - const dComplex zp = phase_map_FS(x,y,z); - const dComplex za = amp_map_FS(x,y,z); - - num += za.imag * zp.imag + za.real * zp.real; - denom += zp.imag * zp.imag + zp.real * zp.real; - } - - return num / denom; -} - -BufferedImage normalisePhaseByShell( - const RawImage& phase_map_FS, - const RawImage& amp_map_FS) -{ - const int sh = phase_map_FS.xdim; - const int s = phase_map_FS.ydim; - - std::vector num(sh,0.0), denom(sh,0.0); - - for (int z = 0; z < s; z++) - for (int y = 0; y < s; y++) - for (int x = 0; x < sh; x++) - { - const dComplex zp = phase_map_FS(x,y,z); - const dComplex za = amp_map_FS(x,y,z); - - const double rd = RadialAvg::get1DIndex(x,y,z,s,s,s); - const int r = ((int)(rd + 0.5) >= sh)? sh - 1 : (int)(rd + 0.5); - - num[r] += za.imag * zp.imag + za.real * zp.real; - denom[r] += zp.imag * zp.imag + zp.real * zp.real; - } - - std::vector ratio(sh); - - for (int r = 0; r < sh; r++) - { - if (denom[r] > 0.0) - { - ratio[r] = num[r] /= denom[r]; - } - else - { - ratio[r] = 0.0; - } - } - - BufferedImage normalised_phase(sh,s,s); - - for (int z = 0; z < s; z++) - for (int y = 0; y < s; y++) - for (int x = 0; x < sh; x++) - { - const double rd = RadialAvg::get1DIndex(x,y,z,s,s,s); - const int r = ((int)(rd + 0.5) >= sh)? sh - 1 : (int)(rd + 0.5); - - normalised_phase(x,y,z) = ratio[r] * phase_map_FS(x,y,z); - } - - return normalised_phase; -} - -std::vector extractCoords( - const std::vector& atom_positions, - const RawImage phase_map, - const RawImage amp_map, - double coord_offset_pixels, - double pixel_size, - d2Matrix transform) -{ - const int ac = atom_positions.size(); - - std::vector out(ac); - - for (int a = 0; a < ac; a++) - { - - const d3Vector pos = atom_positions[a] / pixel_size + coord_offset_pixels * d3Vector(1,1,1); - - const double vp = Interpolation::linearXYZ_clip(phase_map, pos.x, pos.y, pos.z); - const double va = Interpolation::linearXYZ_clip(amp_map, pos.x, pos.y, pos.z); - - out[a] = transform * d2Vector(vp,va); - } - - return out; -} - -void plotCloud( - CPlot2D& plot2D, - const std::vector& coords, - int marker_size, dRGB colour, bool filled) -{ - CDataSet data_set; - - data_set.SetDrawMarker(true); - data_set.SetDrawLine(false); - data_set.SetMarkerSize(marker_size); - data_set.SetDatasetColor(colour.r, colour.g, colour.b); - data_set.SetDrawMarkerFilled(filled); - - const int cc = coords.size(); - - for (int c = 0; c < cc; c++) - { - const d2Vector d = coords[c]; - data_set.AddDataPoint(CDataPoint(d.x, d.y)); - } - - plot2D.AddDataSet(data_set); -} - -void plotEllipse( - CPlot2D& plot2D, - const Ellipse& ellipse, int samples, - double line_thickness, - int marker_size, dRGB colour, bool filled) -{ - CDataSet perimeter; - - perimeter.SetDrawMarker(false); - perimeter.SetDrawLine(true); - perimeter.SetDatasetColor(colour.r, colour.g, colour.b); - perimeter.SetLineWidth(line_thickness); - - for (int i = 0; i < samples+1; i++) - { - const double phi = 2.0 * PI * i / (double) samples; - const double sp = sin(phi); - const double cp = cos(phi); - - const d2Vector c = - ellipse.mean + 2.0 * ( - cp * ellipse.axis0 - + sp * ellipse.axis1); - - perimeter.AddDataPoint(CDataPoint(c.x, c.y)); - } - - plot2D.AddDataSet(perimeter); - - - CDataSet centre; - - centre.SetDrawMarker(true); - centre.SetDrawLine(false); - centre.SetMarkerSize(marker_size); - centre.SetDatasetColor(colour.r, colour.g, colour.b); - centre.SetDrawMarkerFilled(filled); - centre.AddDataPoint(CDataPoint(ellipse.mean.x, ellipse.mean.y)); - - plot2D.AddDataSet(centre); - - - CDataSet centre_outline; - - centre_outline.SetDrawMarker(true); - centre_outline.SetDrawLine(false); - centre_outline.SetMarkerSize(marker_size + 1); - centre_outline.SetDatasetColor(0, 0, 0); - centre_outline.SetDrawMarkerFilled(false); - centre_outline.AddDataPoint(CDataPoint(ellipse.mean.x, ellipse.mean.y)); - - plot2D.AddDataSet(centre_outline); -} - -std::map> mergeElementClouds( - const std::map>& name_to_cloud, - const std::map>& element_to_names) -{ - std::map> element_to_cloud; - - for (std::map>::const_iterator it0 = element_to_names.begin(); - it0 != element_to_names.end(); it0++) - { - const std::string element = it0->first; - - for (std::set::const_iterator it1 = it0->second.begin(); - it1 != it0->second.end(); it1++) - { - const std::vector& coords0 = name_to_cloud.find(*it1)->second; - std::vector& coords = element_to_cloud[element]; - - coords.insert(coords.begin(), coords0.begin(), coords0.end()); - } - } - - return element_to_cloud; -} - -Ellipse fitEllipse(const std::vector& cloud) -{ - const int ac = cloud.size(); - - d2Vector mean(0,0); - - for (int a = 0; a < ac; a++) - { - mean += cloud[a]; - } - - mean /= ac; - - Tensor2x2 cov(0,0,0); - - for (int a = 0; a < ac; a++) - { - const d2Vector d = cloud[a] - mean; - - cov.xx += d.x * d.x; - cov.xy += d.x * d.y; - cov.yy += d.y * d.y; - } - - cov /= ac; - - return cov.getEllipse(mean); -} - -double fitSlope(const std::vector& cloud) -{ - const int ac = cloud.size(); - - double num = 0.0; - double denom = 0.0; - - for (int a = 0; a < ac; a++) - { - num += cloud[a].x * cloud[a].y; - denom += cloud[a].x * cloud[a].x; - } - - return num / denom; -} - -void plotAllAtoms( - std::map> element_to_names, - std::map> coords_by_name, - std::map element_colours, - double ellipse_line_width, - bool plot_window_set, - d2Vector plot_start, - d2Vector plot_end, - const std::string& out_path, - const std::string& tag) -{ - std::ofstream element_angles_file(out_path+"element_angles_" + tag + ".txt"); - element_angles_file << "element slope angle [degrees]\n"; - - CPlot2D all_atoms_plot(""); - - std::map> all_element_coords; - - for (std::map>::iterator it = - element_to_names.begin(); it != element_to_names.end(); it++) - { - std::string element = it->first; - std::set& names = it->second; - - std::vector& all_coords = all_element_coords[element]; - - for (std::set::iterator it2 = names.begin(); - it2 != names.end(); it2++) - { - const std::string atom_name = *it2; - const std::vector& coords = coords_by_name[atom_name]; - all_coords.insert(all_coords.end(), coords.begin(), coords.end()); - } - - dRGB full_colour = element_colours[element]; - const double fade = 0.67; - dRGB faded_colour = (1 - fade) * full_colour + fade * dRGB(1,1,1); - - plotCloud(all_atoms_plot, all_coords, 1, faded_colour, true); - - const double slope = fitSlope(all_coords); - const double angle_deg = RAD2DEG(atan(slope)); - - element_angles_file << element << ": " << slope << ' ' << angle_deg << '\n'; - } - - for (std::map>::iterator it = - all_element_coords.begin(); it != all_element_coords.end(); it++) - { - std::string element = it->first; - std::vector& all_coords = it->second; - - Ellipse ellipse = fitEllipse(all_coords); - - dRGB colour = element_colours[element]; - - CDataSet line; - - const double m = fitSlope(all_coords); - const d2Vector optimal_ratio_spot = ellipse.mean.length() * d2Vector(1,m) / sqrt(1 + m*m); - - - line.SetDrawMarker(false); - line.SetDrawLine(true); - line.SetDatasetColor(colour.r, colour.g, colour.b); - line.AddDataPoint(CDataPoint(0, 0)); - line.AddDataPoint(CDataPoint(optimal_ratio_spot.x, optimal_ratio_spot.y)); - line.SetLineWidth(1.5); - - all_atoms_plot.AddDataSet(line); - } - - for (std::map>::iterator it = - all_element_coords.begin(); it != all_element_coords.end(); it++) - { - std::string element = it->first; - std::vector& all_coords = it->second; - - plotEllipse( - all_atoms_plot, fitEllipse(all_coords), 100, - ellipse_line_width, 12, element_colours[element], true); - } - - all_atoms_plot.SetTitle(tag); - all_atoms_plot.SetXAxisTitle("phase"); - all_atoms_plot.SetYAxisTitle("amplitude"); - - if (plot_window_set) - { - all_atoms_plot.SetViewArea(plot_start.x, plot_start.y, plot_end.x, plot_end.y); - } - - all_atoms_plot.OutputPostScriptPlot(out_path+"all_atoms_" + tag + ".eps"); -} - - - -int main(int argc, char *argv[]) -{ - IOParser parser; - - std::string in_phase, in_amplitude, in_model, out_path, tag; - double filter_freq, high_pass_frequency, sigma_scale, psModel; - d2Vector plot_start, plot_end; - bool plot_window_set; - int boxModel, boxOut, number_of_threads; - bool normalise_by_shell, normalise_uniformly, write_filtered_maps, write_ratios, subtract_solvent; - - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - in_phase = parser.getOption("--phase", "Phase map"); - in_amplitude = parser.getOption("--amp", "Amplitude map"); - in_model = parser.getOption("--pdb", "Atomic model"); - filter_freq = textToDouble(parser.getOption("--res", "Resolution [A]", "3.0")); - high_pass_frequency = textToDouble(parser.getOption("--hp", "High-pass frequency [px]", "-1.0")); - sigma_scale = textToDouble(parser.getOption("--sc", "Region width for scale adaptation [px]", "7.0")); - - boxModel = textToInteger(parser.getOption("--box_model", "Box size of the map corresponding to the PDB file")); - psModel = textToDouble(parser.getOption("--angpix_model", "Pixel size of the map corresponding to the PDB file")); - boxOut = textToInteger(parser.getOption("--box_out", "Box size of the map to be compared")); - - subtract_solvent = parser.checkOption("--zp", "Zero solvent phase"); - normalise_uniformly = parser.checkOption("--nu", "Normalise phase map uniformly"); - normalise_by_shell = parser.checkOption("--ns", "Normalise phase map per shell"); - - write_filtered_maps = parser.checkOption("--write_maps", "Write out filtered maps and their difference"); - write_ratios = parser.checkOption("--write_ratios", "Write out ratio maps"); - number_of_threads = textToInteger(parser.getOption("--j", "Number of threads", "6")); - - std::string plot_window = parser.getOption("--window", "Area to plot (format: ,,,)", ""); - - plot_window_set = plot_window != ""; - - if (plot_window_set) - { - for (int i = 0; i < plot_window.length(); i++) - { - if (plot_window[i] == ',') plot_window[i] = ' '; - } - - std::stringstream sts(plot_window); - - sts >> plot_start.x; - sts >> plot_start.y; - sts >> plot_end.x; - sts >> plot_end.y; - - std::cout << "plotting from " << plot_start << " to " << plot_end << std::endl; - } - - out_path = parser.getOption("--o", "Output path"); - tag = parser.getOption("--tag", "Output tag", ""); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - if (out_path[out_path.length()-1] != '/') - { - out_path = out_path + "/"; - } - - std::string command = "mkdir -p " + out_path; - int res = system(command.c_str()); - - Image dummy; - dummy.read(in_phase, false); - const double pixel_size = dummy.samplingRateX(); - - std::cout << "pixel size: " << pixel_size << std::endl; - - - BufferedImage phase_map_RS(in_phase), amp_map_RS(in_amplitude); - - - - BufferedImage phase_map_FS, amp_map_FS; - - FFT::FourierTransform(phase_map_RS, phase_map_FS); - FFT::FourierTransform(amp_map_RS, amp_map_FS); - - const int s = amp_map_RS.xdim; - const int sh = amp_map_FS.xdim; - - - const double resolution_pixels = filter_freq / pixel_size; - - phase_map_FS = ImageFilter::lowpass3D(phase_map_FS, resolution_pixels, 5); - amp_map_FS = ImageFilter::lowpass3D(amp_map_FS, resolution_pixels, 5); - - if (high_pass_frequency > 0) - { - phase_map_FS = ImageFilter::highpassGauss3D(phase_map_FS, high_pass_frequency); - amp_map_FS = ImageFilter::highpassGauss3D(amp_map_FS, high_pass_frequency); - } - - FFT::inverseFourierTransform(phase_map_FS, phase_map_RS); - FFT::inverseFourierTransform(amp_map_FS, amp_map_RS); - - if (subtract_solvent) - { - const double avg = computeShellAverage(phase_map_RS, s/4, s/2); - phase_map_RS -= avg; - } - - Reconstruction::taper(phase_map_RS, 10, false, number_of_threads); - Reconstruction::taper(amp_map_RS, 10, false, number_of_threads); - - FFT::FourierTransform(phase_map_RS, phase_map_FS); - FFT::FourierTransform(amp_map_RS, amp_map_FS); - - const double optimal_ratio = computeUniformScale(phase_map_FS, amp_map_FS); - - /*const d2Vector scale_and_intercept = computeUniformScaleAndIntercept(phase_map_RS, amp_map_RS); - const double optimal_ratio = scale_and_intercept[0]; - const double optimal_intercept = scale_and_intercept[1];*/ - - std::cout << "amplitude contrast: " << (100.0 * optimal_ratio) << '%' << std::endl; - - if (normalise_uniformly) - { - phase_map_FS *= optimal_ratio; - } - else if (normalise_by_shell) - { - phase_map_FS = normalisePhaseByShell(phase_map_FS, amp_map_FS); - } - - - FFT::inverseFourierTransform(phase_map_FS, phase_map_RS); - FFT::inverseFourierTransform(amp_map_FS, amp_map_RS); - - if (write_filtered_maps) - { - BufferedImage filtered_difference(s,s,s); - - for (int z = 0; z < s; z++) - for (int y = 0; y < s; y++) - for (int x = 0; x < s; x++) - { - filtered_difference(x,y,z) = amp_map_RS(x,y,z) - optimal_ratio * phase_map_RS(x,y,z); - } - - - phase_map_RS.write(out_path + "phase_" + tag + ".mrc", pixel_size); - amp_map_RS.write(out_path + "amplitude_" + tag + ".mrc", pixel_size); - filtered_difference.write(out_path + "difference_" + tag + ".mrc", pixel_size); - } - - - { - const int bins = 100; - BufferedImage histogram(bins, bins); - histogram.fill(0.0); - - const double phase_sd = sqrt(Normalization::computeVariance(phase_map_RS, 0.0)); - const double amp_sd = sqrt(Normalization::computeVariance(amp_map_RS, 0.0)); - - for (int z = 0; z < s; z++) - for (int y = 0; y < s; y++) - for (int x = 0; x < s; x++) - { - const double vp = phase_map_RS(x,y,z) / phase_sd; - const double va = amp_map_RS(x,y,z) / amp_sd; - - const int ip = bins * (vp + 2.0) / 4.0 + 0.5; - const int ia = bins * (va + 2.0) / 4.0 + 0.5; - - if (ip >= 0 && ip < bins && ia >= 0 && ia < bins) - { - histogram(ip,ia) += 1.0; - } - } - - histogram.write(out_path + "joint_histogram_" + tag + ".mrc"); - - BufferedImage normalised_histogram(bins, bins); - - for (int x = 0; x < bins; x++) - { - double max_value = 0.0; - - for (int y = 0; y < bins; y++) - { - if (histogram(x,y) > max_value) - { - max_value = histogram(x,y); - } - } - - for (int y = 0; y < bins; y++) - { - normalised_histogram(x,y) = histogram(x,y) / max_value; - } - } - - normalised_histogram.write(out_path + "joint_histogram_normalised_" + tag + ".mrc"); - - BufferedImage cumulative_histogram(bins, bins); - - for (int x = 0; x < bins; x++) - { - double sum = 0.0; - - for (int y = 0; y < bins; y++) - { - sum += histogram(x,y); - } - - double sum_y = 0.0; - - for (int y = 0; y < bins; y++) - { - cumulative_histogram(x,y) = sum_y / sum; - - sum_y += histogram(x,y); - } - } - - cumulative_histogram.write(out_path + "cumulative_joint_histogram_" + tag + ".mrc"); - } - - const double coord_offset_pixels = - ( (boxOut/2)*pixel_size - (boxModel/2)*psModel ) / pixel_size; - - - Assembly assembly; - assembly.readPDB(in_model); - - std::set heavy_external; - heavy_external.insert("P"); - heavy_external.insert("CL"); - heavy_external.insert("FE"); - heavy_external.insert("ZN"); - heavy_external.insert("NA"); - heavy_external.insert("MG"); - - std::map> atoms_by_name = - PdbHelper::groupAtomsByName(assembly, heavy_external); - - std::map> coords_by_name; - - const d2Matrix scale(1e8, 0, 0, 1e8); - - for (std::map>::iterator it = - atoms_by_name.begin(); it != atoms_by_name.end(); it++) - { - coords_by_name[it->first] = extractCoords( - it->second, phase_map_RS, amp_map_RS, - coord_offset_pixels, pixel_size, scale); - - std::cout << it->first << ": " << coords_by_name[it->first].size() << std::endl; - } - - std::map> element_to_names; - - for (std::map>::iterator it = - coords_by_name.begin(); it != coords_by_name.end(); it++) - { - std::string atom_name = it->first; - std::string element = PdbHelper::getElement(atom_name); - - element_to_names[element].insert(atom_name); - } - - - std::map element_colours; - element_colours["C"] = dRGB(0.1,0.1,0.1); - element_colours["N"] = dRGB(48,80,248)/255.0; - element_colours["O"] = dRGB(1.0,0.0,0.0); - element_colours["P"] = dRGB(0.5,0.125,1); - element_colours["S"] = dRGB(0.9,0.9,0.1); - element_colours["CL"] = dRGB(0.1,0.9,0.1); - element_colours["FE"] = dRGB(255,165,0)/255.0; - element_colours["ZN"] = dRGB(165,42,42)/255.0; - element_colours["NA"] = dRGB(171,92,242)/255.0; - element_colours["MG"] = dRGB(138,255,0)/255.0; - - - const double ellipse_line_width = 0.5; - - { - std::ofstream element_angles_file(out_path+"main_chain_element_angles_" + tag + ".txt"); - element_angles_file << "element angle [degrees]\n"; - - std::vector C_coords = coords_by_name[" C "]; - std::vector CA_coords = coords_by_name[" CA "]; - std::vector O_coords = coords_by_name[" O "]; - std::vector N_coords = coords_by_name[" N "]; - - - CPlot2D main_chain_plot(""); - - std::vector all_C_coords = C_coords; - all_C_coords.insert(all_C_coords.end(), CA_coords.begin(), CA_coords.end()); - - - element_angles_file << "C: " << RAD2DEG(atan(fitSlope(all_C_coords))) << '\n'; - element_angles_file << "N: " << RAD2DEG(atan(fitSlope(N_coords))) << '\n'; - element_angles_file << "O: " << RAD2DEG(atan(fitSlope(O_coords))) << '\n'; - - - plotCloud(main_chain_plot, all_C_coords, 1, element_colours["C"], true); - plotCloud(main_chain_plot, O_coords, 1, element_colours["O"], true); - plotCloud(main_chain_plot, N_coords, 1, element_colours["N"], true); - - - plotEllipse(main_chain_plot, fitEllipse(all_C_coords), 100, - ellipse_line_width, 12, element_colours["C"], true); - - plotEllipse(main_chain_plot, fitEllipse(C_coords), 100, - 0.5*ellipse_line_width, 7, element_colours["C"], true); - - plotEllipse(main_chain_plot, fitEllipse(CA_coords), 100, - 0.5*ellipse_line_width, 7, element_colours["C"], true); - - plotEllipse(main_chain_plot, fitEllipse(O_coords), 100, - ellipse_line_width, 12, element_colours["O"], true); - - plotEllipse(main_chain_plot, fitEllipse(N_coords), 100, - ellipse_line_width, 12, element_colours["N"], true); - - main_chain_plot.SetXAxisTitle("phase"); - main_chain_plot.SetYAxisTitle("amplitude"); - - if (plot_window_set) - { - main_chain_plot.SetViewArea(plot_start.x, plot_start.y, plot_end.x, plot_end.y); - } - - main_chain_plot.OutputPostScriptPlot(out_path+"main_chain_atoms_" + tag + ".eps"); - } - - - plotAllAtoms( - element_to_names, coords_by_name, element_colours, - ellipse_line_width, plot_window_set, plot_start, plot_end, - out_path, tag); - - - //plot2D.SetTitle("amplitude over phase"); - //plot2D.SetDrawLegend(true); - -} diff --git a/src/jaz/scripts/blobs_from_points.cpp b/src/jaz/scripts/blobs_from_points.cpp deleted file mode 100644 index cb20e5576..000000000 --- a/src/jaz/scripts/blobs_from_points.cpp +++ /dev/null @@ -1,405 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - std::string points_file_name, image_directory, outDir; - double binning, score_threshold, particle_spacing, min_radius_bin1, max_radius_bin1, tolerance_bin1, threshold, tethering, - aspect_cost, contrast_cost, acceptance_threshold; - int radius_steps, max_iterations, max_frequencies, num_threads; - bool diag; - - - IOParser parser; - - try - { - IOParser parser; - - parser.setCommandLine(argc, argv); - - int general_section = parser.addSection("General options"); - - points_file_name = parser.getOption("--i", "Topaz membrane detections"); - image_directory = parser.getOption("--id", "Directory containing the micrographs"); - score_threshold = textToDouble(parser.getOption("--pt", "Score threshold for input particles", "-4")); - particle_spacing = textToDouble(parser.getOption("--sp", "Input particle spacing (bin-1 pixels)", "25")); - binning = textToDouble(parser.getOption("--bin", "Binning level", "32")); - min_radius_bin1 = textToDouble(parser.getOption("--r0", "Minimal blob radius (bin-1 pixels)", "300")); - max_radius_bin1 = textToDouble(parser.getOption("--r1", "Maximal blob radius (bin-1 pixels)", "400")); - radius_steps = textToInteger(parser.getOption("--rs", "Radius steps", "5")); - tolerance_bin1 = textToDouble(parser.getOption("--rt", "Radius tolerance (bin-1 pixels)", "50")); - threshold = textToDouble(parser.getOption("--dt", "Blob centre detection threshold (#particles)", "15")); - - max_iterations = textToInteger(parser.getOption("--it", "Max. number of iterations", "1000")); - max_frequencies = textToInteger(parser.getOption("--frq", "Max. number of blob frequencies", "6")); - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - - tethering = textToDouble(parser.getOption("--tth", - "Blob tethering to its initial position", - "0.0")); - - aspect_cost = textToDouble(parser.getOption("--ac", - "Cost of deviating from a circular shape", - "0.02")); - - contrast_cost = textToDouble(parser.getOption("--cc", - "Cost of contrast mismatch (dark pixels outside or bright pixels inside)", - "2.0")); - - acceptance_threshold = textToDouble(parser.getOption("--at", - "Acceptance threshold for final blobs", - "0.5")); - - diag = parser.checkOption("--diag", "Write out diagnostic information"); - - outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - outDir = ZIO::makeOutputDir(outDir); - - if (image_directory.length() > 0) - { - if (image_directory[image_directory.length()-1] != '/') - { - image_directory = image_directory + "/"; - } - } - - - TopazParticleMap particles_by_image = TopazHelper::read(points_file_name, score_threshold); - - const std::string first_image_name = particles_by_image.begin()->first; - - t3Vector full_image_size = ImageFileHelper::getSize(image_directory + first_image_name + ".mrc"); - - const i2Vector binned_image_size( - full_image_size.x / binning, - full_image_size.y / binning); - - const double avg_radius_bin1 = (min_radius_bin1 + max_radius_bin1) / 2.0; - const double binned_avg_radius = avg_radius_bin1 / binning; - const double binned_tolerance = tolerance_bin1 / binning; - - - const int micrograph_count = particles_by_image.size(); - - std::vector all_image_names(micrograph_count); - std::vector> all_particles(micrograph_count); - - { - int index = 0; - - for (TopazParticleMap::iterator it = particles_by_image.begin(); - it != particles_by_image.end(); it++) - { - all_image_names[index] = it->first; - all_particles[index] = it->second; - - index++; - } - } - - { - std::ofstream names_list(outDir+"micrographs.txt"); - - for (int m = 0; m < micrograph_count; m++) - { - names_list << all_image_names[m] << '\n'; - } - } - - - BufferedImage diagnostic(binned_image_size.x, binned_image_size.y, micrograph_count); - - int res; - res = system(("mkdir -p "+outDir+"Frames").c_str()); - res = system(("mkdir -p "+outDir+"diag").c_str()); - - - Log::beginProgress("Finding blobs", micrograph_count / num_threads); - - #pragma omp parallel for num_threads(num_threads) - for (int m = 0; m < micrograph_count; m++) - { - const int th = omp_get_thread_num(); - - if (th == 0) - { - Log::updateProgress(m); - } - - const std::string image_name = all_image_names[m]; - const std::vector particles = all_particles[m]; - - BufferedImage centre_quality(binned_image_size.x, binned_image_size.y); - centre_quality.fill(0.f); - - BufferedImage blob_radius(binned_image_size.x, binned_image_size.y); - blob_radius.fill(0.f); - - BufferedImage micrograph; - micrograph.read(image_directory + image_name + ".mrc"); - micrograph = Resampling::FourierCrop_fullStack(micrograph, binning, 1, true); - micrograph = Normalization::byNormalDist(micrograph); - - BufferedImage lowpass0 = ImageFilter::Gauss2D( - micrograph, 0, 0.125 * binned_avg_radius, true); - - BufferedImage lowpass1 = ImageFilter::Gauss2D( - micrograph, 0, 1.500 * binned_avg_radius, true); - - BufferedImage dog = lowpass1 - lowpass0; - - if (diag) - { - dog.write(outDir+"diag/"+image_name+"_DoG.mrc"); - micrograph.write(outDir+"diag/"+image_name+"_micrograph.mrc"); - } - - - for (int y = 0; y < binned_image_size.y; y++) - for (int x = 0; x < binned_image_size.x; x++) - { - const d2Vector point_pos(x,y); - - double max_score = 0.0; - double best_radius = 0.0; - - for (int rr = 0; rr < radius_steps; rr++) - { - const double t = rr / (double)(radius_steps - 1); - const double rad_bin1 = (1 - t) * min_radius_bin1 + t * max_radius_bin1; - const double rad = rad_bin1 / binning; - - double score = 0.0; - - for (int p = 0; p < particles.size(); p++) - { - const TopazHelper::Particle& particle = particles[p]; - - const d2Vector binned_pos( - particle.coordinates.x / binning, - particle.coordinates.y / binning); - - const double d = (binned_pos - point_pos).length(); - const double dr = (d - rad) / binned_tolerance; - - score += exp(-dr*dr/2); - } - - if (score > max_score) - { - best_radius = rad; - max_score = score; - } - - } - - centre_quality(x,y) = (float) max_score; - blob_radius(x,y) = (float) best_radius; - } - - if (diag) - { - centre_quality.write(outDir + "centre_quality.mrc"); - } - - BufferedImage box_maxima = LocalExtrema::boxMaxima(centre_quality, (int)(0.72 * binned_avg_radius)); - std::vector detections = LocalExtrema::discretePoints2D(centre_quality, box_maxima, (float)threshold); - - - - std::vector all_particle_positions(particles.size()); - - for (int i = 0; i < particles.size(); i++) - { - i2Vector coords = particles[i].coordinates; - all_particle_positions[i] = d2Vector(coords.x, coords.y) / binning; - } - - - if (diag) - { - BufferedImage detections_image(binned_image_size.x, binned_image_size.y); - detections_image.fill(0.f); - Drawing::drawCrosses(detections, 1.f, 10, detections_image); - detections_image.write(outDir + "topaz_blob_detections.mrc"); - detections_image.fill(0.f); - Drawing::drawCrosses(all_particle_positions, 1.f, 3, detections_image); - detections_image.write(outDir + "topaz_input.mrc"); - } - - - BufferedImage density_map(binned_image_size.x, binned_image_size.y); - - for (int y = 0; y < binned_image_size.y; y++) - for (int x = 0; x < binned_image_size.x; x++) - { - density_map(x,y) = 0.f; - - const double sigma = 2 * particle_spacing / binning; - - for (int p = 0; p < all_particle_positions.size(); p++) - { - const double d = (all_particle_positions[p] - d2Vector(x,y)).length() / sigma; - const double rho = exp(-d*d / 2); - - if (density_map(x,y) < rho) - { - density_map(x,y) = rho; - } - } - } - - if (diag) - { - density_map.write(outDir + "density_map.mrc"); - } - - - BufferedImage final_plots_sum(binned_image_size.x, binned_image_size.y); - final_plots_sum.fill(0.f); - - BufferedImage initial_plots_sum; - - if (diag) - { - initial_plots_sum.resize(binned_image_size.x, binned_image_size.y); - initial_plots_sum.fill(0.f); - } - - std::vector all_costs(detections.size()); - std::vector> all_optimal_parameters(detections.size()); - std::vector is_accepted(detections.size()); - - for (int detection_id = 0; detection_id < detections.size(); detection_id++) - { - const d2Vector d = detections[detection_id]; - - const double radius = blob_radius((int)std::round(d.x), (int)std::round(d.y)); - - AreaPointBlobFit point_blob_fit( - density_map, dog, d, radius, binned_tolerance, tethering, aspect_cost, contrast_cost); - - /*PointBlobFit2D point_blob_fit( - all_particle_positions, d, radius, binned_tolerance, tethering);*/ - - std::vector initial_parameters(3+2*max_frequencies, 0.0); - initial_parameters[0] = radius; - initial_parameters[1] = d.x; - initial_parameters[2] = d.y; - - if (diag) - { - BufferedImage final_plot = point_blob_fit.visualise( - initial_parameters, binned_image_size.x, binned_image_size.y); - - initial_plots_sum += final_plot; - } - - - std::vector optimal_parameters = NelderMead::optimize( - initial_parameters, point_blob_fit, 0.5, 0.0001, max_iterations, - 1.0, 2.0, 0.5, 0.5, false); - - const double cost = point_blob_fit.f(optimal_parameters,0); - - - is_accepted[detection_id] = cost < acceptance_threshold; - - if (!(cost == cost)) - { - std::cout << "nan: " << d << ", " << radius << "\n"; - std::cout << "optimal_parameters.size() = " << optimal_parameters.size() << "\n"; - - for (int i = 0; i < optimal_parameters.size(); i++) - { - std::cout << optimal_parameters[i] << " "; - } - std::cout << "\n"; - } - - if (is_accepted[detection_id]) - { - BufferedImage final_plot = point_blob_fit.visualise( - optimal_parameters, binned_image_size.x, binned_image_size.y); - - final_plots_sum += final_plot; - } - - all_costs[detection_id] = cost; - all_optimal_parameters[detection_id] = optimal_parameters; - } - - - BufferedImage all_particle_dots(binned_image_size.x, binned_image_size.y); - Drawing::drawCrosses(all_particle_positions, 0.1f, 3, all_particle_dots); - final_plots_sum += all_particle_dots; - - - std::vector sorted_blobs = IndexSort::sortIndices(all_costs); - - - std::ofstream blob_file(outDir+"Frames/"+image_name+".blobs"); - - for (int i = 0; i < sorted_blobs.size(); i++) - { - if (is_accepted[sorted_blobs[i]]) - { - const std::vector parameters = all_optimal_parameters[sorted_blobs[i]]; - - for (int j = 0; j < parameters.size(); j++) - { - blob_file << binning * parameters[j] << " "; - } - - blob_file << '\n'; - - Drawing::drawCross( - d2Vector(parameters[1], parameters[2]), - (float)all_costs[sorted_blobs[i]], 5, final_plots_sum); - } - } - - diagnostic.getSliceRef(m).copyFrom(final_plots_sum); - - if (diag) - { - initial_plots_sum.write(outDir+"diag/"+image_name+"_initial.mrc"); - final_plots_sum.write(outDir+"diag/"+image_name+"_final.mrc"); - } - } - - Log::endProgress(); - - diagnostic.write(outDir + "diagnostic.mrc"); - - return 0; -} diff --git a/src/jaz/scripts/box_PCA.cpp b/src/jaz/scripts/box_PCA.cpp deleted file mode 100644 index acf51b5c7..000000000 --- a/src/jaz/scripts/box_PCA.cpp +++ /dev/null @@ -1,119 +0,0 @@ -#include -#include -#include -#include -#include -#include - -using namespace Eigen; -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string all_input_filenames, output_directory; - int number_of_dimensions_to_output; - bool subtract_mean; - - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - all_input_filenames = parser.getOption( - "--i", "Comma-separated list of input images (no space after comma)"); - - number_of_dimensions_to_output = textToInteger(parser.getOption( - "--N", "Number of dimensions to write out (negative means all)", "-1")); - - subtract_mean = parser.checkOption("--s", "Subtract the mean value from each image"); - - output_directory = parser.getOption( - "--o", "Output directory"); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - output_directory = ZIO::makeOutputDir(output_directory); - - std::vector input_filenames = ZIO::split(all_input_filenames, ","); - - const int ic = input_filenames.size(); - std::vector> images(ic); - - for (int i = 0; i < ic; i++) - { - std::cout << i << ": " << input_filenames[i] << std::endl; - images[i].read(input_filenames[i]); - } - - const int w = images[0].xdim; - const int h = images[0].ydim; - const int d = images[0].zdim; - - for (int i = 1; i < ic; i++) - { - if (!images[i].hasEqualSize(images[0])) - { - REPORT_ERROR_STR( - "Images '" << input_filenames[0] << "' and '" << input_filenames[i] << "' are " - << "of different size: " << images[0].getSizeString() - << " vs. " << images[i].getSizeString() ); - } - } - - - std::vector mean(ic); - - for (int i = 0; i < ic; i++) - { - mean[i] = subtract_mean? Normalization::computeMean(images[i]) : 0.0; - } - - MatrixXd A0(ic,ic); - - std::vector values(ic); - - for (int z = 0; z < d; z++) - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) - { - for (int i = 0; i < ic; i++) - { - values[i] = images[i](x,y,z); - } - - for (int i = 0; i < ic; i++) - for (int j = 0; j < ic; j++) - { - A0(i,j) += (values[i] - mean[i]) * (values[j] - mean[j]); - } - } - - JacobiSVD svd(A0, ComputeFullV); - - const int N = number_of_dimensions_to_output > 0? number_of_dimensions_to_output : ic; - - for (int i = 0; i < N; i++) - { - BufferedImage out = ((float)svd.matrixV()(0,i)) * images[0]; - - for (int j = 1; j < ic; j++) - { - out += ((float)svd.matrixV()(j,i)) * images[j]; - } - - out.write(output_directory+ZIO::itoa(i)+".mrc"); - } - - return 0; -} diff --git a/src/jaz/scripts/conversion_test.cpp b/src/jaz/scripts/conversion_test.cpp deleted file mode 100644 index f63f3c51b..000000000 --- a/src/jaz/scripts/conversion_test.cpp +++ /dev/null @@ -1,115 +0,0 @@ - -#include - -#include -#include -#include -#include - - -template -class Test -{ - public: - - Test(); - - template - Test(const Test& z); - - T a, b; -}; - -template -Test::Test() -{} - -template template -Test::Test(const Test& z) -: a(z.a), b(z.b) -{} - - - - - -template inline -T linearXY_clip(const RawImage& img, double x, double y, int z) -{ - int x0 = FLOOR(x); - int y0 = FLOOR(y); - - int x1 = x0 + 1; - int y1 = y0 + 1; - - const double xf = x - x0; - const double yf = y - y0; - - if (x0 < 0) x0 = 0; - if (x0 >= img.xdim) x0 = img.xdim - 1; - if (x1 < 0) x1 = 0; - if (x1 >= img.xdim) x1 = img.xdim - 1; - if (y0 < 0) y0 = 0; - if (y0 >= img.ydim) y0 = img.ydim - 1; - if (y1 < 0) y1 = 0; - if (y1 >= img.ydim) y1 = img.ydim - 1; - - const T vx0 = (1 - xf) * img(x0,y0,z) + xf * img(x1,y0,z); - const T vx1 = (1 - xf) * img(x0,y1,z) + xf * img(x1,y1,z); - - std::cout << vx0 << ", " << vx1 << std::endl; - - return (1 - yf) * vx0 + yf * vx1; -} - - - - - - -int main() -{ - const double x = 1.7, y = 2.3; - const int z = 0; - - BufferedImage> img(5,5); - img.fill(tComplex(2,3)); - - /*int x0 = FLOOR(x); - int y0 = FLOOR(y); - - int x1 = x0 + 1; - int y1 = y0 + 1; - - const double xf = x - x0; - const double yf = y - y0; - - if (x0 < 0) x0 = 0; - if (x0 >= img.xdim) x0 = img.xdim - 1; - if (x1 < 0) x1 = 0; - if (x1 >= img.xdim) x1 = img.xdim - 1; - if (y0 < 0) y0 = 0; - if (y0 >= img.ydim) y0 = img.ydim - 1; - if (y1 < 0) y1 = 0; - if (y1 >= img.ydim) y1 = img.ydim - 1; - - const tComplex vx0 = (1 - xf) * img(x0,y0,z) + xf * img(x1,y0,z); - const tComplex vx1 = (1 - xf) * img(x0,y1,z) + xf * img(x1,y1,z); - - std::cout << (1 - yf) * vx0 + yf * vx1;*/ - - std::cout << linearXY_clip(img.getRef(), x, y, z) << std::endl; - - return 0; - - Test ti; - ti.a = 5; - ti.b = 7; - - Test td = ti; - - std::cout << td.a << ", " << td.b << std::endl; - - return 0; -} - diff --git a/src/jaz/scripts/cuda_test.cpp b/src/jaz/scripts/cuda_test.cpp deleted file mode 100644 index aeda93b52..000000000 --- a/src/jaz/scripts/cuda_test.cpp +++ /dev/null @@ -1,23 +0,0 @@ -#include - - -#ifdef CUDA -#include -#endif - - -int main(int argc, char *argv[]) -{ - #ifdef CUDA - - CudaTest00 test; - test.run(); - - #else - - std::cerr << "Not compiled with CUDA." << std::endl; - - #endif - - return 0; -} diff --git a/src/jaz/scripts/defilament.cpp b/src/jaz/scripts/defilament.cpp deleted file mode 100644 index d0201cdfc..000000000 --- a/src/jaz/scripts/defilament.cpp +++ /dev/null @@ -1,469 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - -/* - TODO: - - - consider all frames again - - write non-circular Fourier model - - write explicit-position fit (outside of FilamentFit?) - - write TV segmentation with varying surface cost but constant (axis-aligned) anisotropy - (n.x expensive, n.y and n.z cheap) - - - outline: - - variant A: - - - iterate similarity fit until convergence (better average, more constant-error regions) - - perform TV segmentation - - fit deformation to model - - offset model parameters - - iterate similarity fit again - - - variant B: - - - find segmentation cost using a synthetic template - - perform TV segmentation - - use to intialize similarity fit - -*/ - -void read_splines( - std::string filename, - std::vector>& points, - std::vector>& radii, - double spline_binning) -{ - std::string nextSplineKey = "(0)); - radii.push_back(std::vector(0)); - - splineIndex++; - } - else if (ZIO::beginsWith(line, nextPointKey)) - { - for (int i = 0; i < line.length(); i++) - { - if (line[i] == '"') line[i] = ' '; - } - - int id; - double x, y, z, r; - - std::sscanf(line.c_str(), formatStr.c_str(), &id, &x, &y, &z, &r); - - points[splineIndex].push_back(spline_binning * d3Vector(x,y,z)); - radii[splineIndex].push_back(r); - } - } -} - -BufferedImage compute_mask( - const BufferedImage& binnedStack, - double edge_bin, - double sigma, - double thresh, - double grow_thresh, - int iters, - double current_binning, - int num_threads - ) -{ - const double edge_bin_rel = edge_bin / current_binning; - - - const int w = binnedStack.xdim; - const int h = binnedStack.ydim; - const int fc = binnedStack.zdim; - - BufferedImage out(w,h,fc); - - BufferedImage binnedStackSmooth = ImageFilter::GaussStack(binnedStack, edge_bin_rel, true); - - BufferedImage edgeStack = Resampling::downsampleFiltStack_2D_full( - binnedStackSmooth, edge_bin_rel, num_threads); - - BufferedImage edgeStackHP = ImageFilter::highpassStackGaussPadded(edgeStack, sigma); - - edgeStackHP = Normalization::byNormalDistByFrame(edgeStackHP); - - edgeStackHP = Resampling::upsampleCubic_Stack_full( - edgeStackHP, edge_bin_rel, w, h); - - for (int f = 0; f < fc; f++) - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) - { - out(x,y,f) = edgeStackHP(x,y,f) > thresh? 1.0 : 0.0; - } - - for (int i = 0; i < iters; i++) - { - out = ImageFilter::GaussStack(out, edge_bin_rel, true); - - for (int f = 0; f < fc; f++) - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) - { - out(x,y,f) = out(x,y,f) > grow_thresh? 1.0 : 0.0; - } - } - - return out; -} - -void precondition(BufferedImage& binnedStack) -{ - const float mean = Normalization::computeMean(binnedStack); - const float var = Normalization::computeVariance(binnedStack, mean); - const float stdDev = sqrt(var); - - for (size_t i = 0; i < binnedStack.getSize(); i++) - { - binnedStack[i] = (binnedStack[i] - mean) / stdDev; - } -} - -int main(int argc, char *argv[]) -{ - std::string splineFn = "spline_fit_coord/clicker_23.cmm"; - const double spline_binning = 6.0; - - std::string stackFn = "TS_23/TS_23_aligned_bin8.mrc"; - const double initial_binning = 8.0; - const double max_binning = 8.0; - - std::string projFn = "proj/23.proj"; - - std::string cacheDir = "cache/"; - const bool cached_filament_coordinates = true; - - const double radius_bin_1 = 500.0; - const int num_iters = 100; - - const bool use_Fourier_cropping = false; - const bool hi_pass = false; - const bool low_pass = false; - - - std::string outDir = "1st_max8_DS/"; - - - - int dummy = std::system(("mkdir -p "+outDir).c_str()); - - const int num_freqs = 20; - const int num_threads = 6; - - - - std::cout << "reading projection matrices from: " << projFn << "..." << std::endl; - - int w3D, h3D, d3D; - std::vector proj0 = ProjectionIO::read(projFn, w3D, h3D, d3D); - - for (int f = 0; f < proj0.size(); f++) - { - proj0[f] /= initial_binning; - } - - - - std::cout << "reading filament splines from: " << splineFn << "..." << std::endl; - - std::vector> splines; - std::vector> radii; - - read_splines(splineFn, splines, radii, spline_binning); - - const int filament_count = splines.size(); - - std::vector filaments(filament_count); - - for (int fil = 0; fil < filament_count; fil++) - { - filaments[fil] = Filament(splines[fil], radius_bin_1); - } - - - - std::cout << "reading image stack from: " << stackFn << "..." << std::endl; - - BufferedImage origStack_unfilt; - origStack_unfilt.read(stackFn); - - BufferedImage origStack = origStack_unfilt; - - if (hi_pass) - { - std::cout << " filtering..." << std::endl; - - origStack = ImageFilter::highpassStackGaussPadded(origStack, radius_bin_1 / initial_binning); - } - - std::cout << " preconditioning..." << std::endl; - - precondition(origStack); - - origStack.write(outDir+"initial_stack.mrc"); - - - /*{ - const double rho = 7.0; - Image> J = StructureTensor::compute2D(origStack, rho, 0.0, 5.0); - Image evals = StructureTensor::computeEigenvalues2D(J); - std::vector> evalsSplit = StructureTensor::split(evals); - - - Image diff = evalsSplit[0] - evalsSplit[1]; - - evalsSplit[0].write("eval_0.mrc"); - evalsSplit[1].write("eval_1.mrc"); - diff.write("evals_diff.mrc"); - - return 0; - }*/ - - - std::cout << " computing outlier mask..." << std::endl; - - BufferedImage marker_mask_full_size; - - - { - const double edge_bin = 16.0; - - const double sigma = 20.0; - const double thresh = -3.0; - const double grow_thresh = 0.8; - const int iters = 3; - - - marker_mask_full_size = compute_mask( - origStack, edge_bin, sigma, thresh, grow_thresh, iters, initial_binning, num_threads); - - marker_mask_full_size.write(outDir+"outlier_mask.mrc"); - } - - std::cout << "\ninitiating multiscale fit..." << std::endl; - - - const int scaleCount = (int) round(log(max_binning/initial_binning)/log(2.0)) + 1; - - std::vector - abs_binning_levels(scaleCount), - rel_binning_levels(scaleCount); - - { - double temp_binning = max_binning; - - for (int scale = 0; scale < scaleCount; scale++) - { - abs_binning_levels[scale] = temp_binning; - rel_binning_levels[scale] = temp_binning / initial_binning; - - temp_binning /= 2.0; - } - } - - - std::vector> current_params(filament_count); - - for (int fil = 0; fil < filament_count; fil++) - { - current_params[fil] = std::vector(8 * num_freqs, 0.0); - } - - for (int scale = 0; scale < scaleCount; scale++) - { - std::cout << " scale #" << (scale + 1) << ", " << abs_binning_levels[scale] << std::endl; - - double current_binning = abs_binning_levels[scale]; - double current_rel_binning = rel_binning_levels[scale]; - - BufferedImage binnedStack, binnedStack_unfilt, marker_mask; - - if (use_Fourier_cropping) - { - - binnedStack = Resampling::FourierCrop_fullStack( - origStack, current_rel_binning, num_threads, true); - - binnedStack_unfilt = Resampling::FourierCrop_fullStack( - origStack_unfilt, current_rel_binning, num_threads, true); - - marker_mask = Resampling::FourierCrop_fullStack( - marker_mask_full_size, current_rel_binning, num_threads, true); - - } - else - { - binnedStack = Resampling::downsampleFiltStack_2D_full( - origStack, current_rel_binning, num_threads); - - binnedStack_unfilt = Resampling::downsampleFiltStack_2D_full( - origStack_unfilt, current_rel_binning, num_threads); - - marker_mask = Resampling::downsampleFiltStack_2D_full( - marker_mask_full_size, current_rel_binning, num_threads); - } - - if (low_pass) - { - binnedStack = ImageFilter::GaussStack(binnedStack, 0.5, false); - } - - std::string scaleTag = "bin"+ZIO::itoa(abs_binning_levels[scale]); - - binnedStack.write(outDir + scaleTag + "_filtered_stack.mrc"); - binnedStack_unfilt.write(outDir + scaleTag + "_unfiltered_stack.mrc"); - - - const int w = binnedStack.xdim; - const int h = binnedStack.ydim; - - marker_mask.write(outDir + scaleTag + "_mask.mrc"); - - - std::vector proj = proj0; - - for (int f = 0; f < proj.size(); f++) - { - proj[f] /= current_rel_binning; - } - - std::vector models; - std::vector mappings(filament_count); - std::vector initialFits; - models.reserve(filament_count); - - std::cout << " rasterising filament coordinates..." << std::endl; - - BufferedImage allErased = binnedStack; - - for (int fil = 0; fil < filament_count; fil++) - { - filaments[fil] = Filament(splines[fil], radius_bin_1); - - if (!cached_filament_coordinates) - { - mappings[fil] = filaments[fil].rasteriseCoordinates( - w, h, proj, current_binning, num_threads); - - mappings[fil].write( - cacheDir+scaleTag+"_filament_mapping_"+ZIO::itoa(fil)); - } - else - { - mappings[fil] = FilamentMapping::read( - cacheDir+scaleTag+"_filament_mapping_"+ZIO::itoa(fil)); - } - - models.push_back(CircularFourierFilamentModel(filaments[fil].arcLen, proj)); - - initialFits.push_back(FilamentFit(filaments[fil], mappings[fil], proj, binnedStack, - marker_mask, &models[fil], current_binning, num_threads)); - - allErased = initialFits[fil].visualise(current_params[fil], true, &allErased); - } - - std::cout << " fitting filaments..." << std::endl; - - - BufferedImage allFitsOut = binnedStack_unfilt; - BufferedImage allErasedOut = binnedStack_unfilt; - - - for (int fil = 0; fil < filament_count; fil++) - { - std::cout << " " << (fil+1) << " / " << filament_count << std::endl; - - BufferedImage othersErased = initialFits[fil].visualise( - current_params[fil], true, &allErased, -1); - - FilamentFit subtractedFit(filaments[fil], mappings[fil], proj, othersErased, - marker_mask, &models[fil], current_binning, num_threads); - - - std::string tag = scaleTag + "_fil_" + ZIO::itoa(fil); - - - - /*current_params[fil] = LBFGS::optimize( - current_params[fil], subtractedFit, true, num_iters, 1e-7); - - ZIO::writeDat(current_params[fil], outDir+"params_"+tag+".dat");*/ - - - current_params[fil] = ZIO::readDat(outDir+"params_"+tag+".dat"); - - BufferedImage costByOffset = subtractedFit.computeCostByOffset( - current_params[fil], -10, 10, 42, 1.0); - - costByOffset.write(outDir+tag+"_costByOffset.mrc"); - - - - { - FilamentFit visFit(filaments[fil], mappings[fil], proj, binnedStack_unfilt, - marker_mask, &models[fil], current_binning, num_threads); - - BufferedImage predSub = visFit.visualise(current_params[fil], true, &allErasedOut); - predSub.write(outDir+tag+"_sub.mrc"); - - allFitsOut = visFit.visualise(current_params[fil], false, &allFitsOut); - allFitsOut.write(outDir+tag+"_fit.mrc"); - - allErasedOut = predSub; - } - } - } - - return 0; -} diff --git a/src/jaz/scripts/deramp.cpp b/src/jaz/scripts/deramp.cpp deleted file mode 100644 index c48e34896..000000000 --- a/src/jaz/scripts/deramp.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::vector indices = {"R2_3115", "R2_3160", "R2_3180", "R2_3197"}; - - for (int ind = 0; ind < indices.size(); ind++) - { - std::string index = indices[ind]; - - std::string fn = index+"_square_DW_4.1_CTFcorrected_FlippedXZY_WeightFiltered_XYZ_bin8.rec:mrc"; - std::string fn_out = index+"_square_DW_4.1_CTFcorrected_FlippedXZY_WeightFiltered_XYZ_bin8_filtered.rec:mrc"; - std::string fn_test = index+"_square_DW_4.1_CTFcorrected_FlippedXZY_WeightFiltered_XYZ_bin8_unfiltered.rec:mrc"; - - std::cout << " " << fn << "\n-> " << fn_out << std::endl; - const double r_crit = 50; - - BufferedImage img; - img.read(fn); - - img.write(fn_test); - - BufferedImage imgFS; - - FFT::FourierTransform(img, imgFS, FFT::Both); - - const int w = img.xdim; - const int h = img.ydim; - const int d = img.zdim; - - const int wh = w/2 + 1; - - for (int z = 0; z < d; z++) - for (int y = 0; y < h; y++) - for (int x = 0; x < wh; x++) - { - const double xx = x; - const double yy = y < h/2? y : y - h; - const double zz = z < d/2? z : z - d; - - const double r = sqrt(xx*xx + yy*yy + zz*zz); - - const double amp = r_crit / (r_crit + r); - - imgFS(x,y,z) *= amp; - } - - FFT::inverseFourierTransform(imgFS, img, FFT::Both); - - img.write(fn_out); - } - - return 0; -} diff --git a/src/jaz/scripts/dose_convert.cpp b/src/jaz/scripts/dose_convert.cpp deleted file mode 100644 index 69bebf13f..000000000 --- a/src/jaz/scripts/dose_convert.cpp +++ /dev/null @@ -1,90 +0,0 @@ -#include -#include -#include - -int main(int argc, char *argv[]) -{ - IOParser parser; - - std::string orderFn, tltFn, outFn; - double fractionalDose; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - orderFn = parser.getOption("--ol", "Frame-order list (*.csv)", "order_list.csv"); - tltFn = parser.getOption("--t", "Tilt angles list (*.tlt)"); - fractionalDose = textToDouble(parser.getOption("--fd", "Fractional dose")); - outFn = parser.getOption("--o", "Output file"); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - std::vector> order = ZIO::readFixedDoublesTable(orderFn, 2, ','); - std::vector tilts = ZIO::readDoubles(tltFn); - - int fc = tilts.size(); - // - - MetaDataTable mdt; - mdt.addLabel(EMDL_MICROGRAPH_FRAME_NUMBER); - mdt.addLabel(EMDL_MICROGRAPH_PRE_EXPOSURE); - - for (int i = 0; i < fc; i++) - { - double minDist = 1000000.0; - int bestJ = -1; - - for (int j = 0; j < order.size(); j++) - { - double d = order[j][1] - tilts[i]; - double dd = d*d; - - if (dd < minDist) - { - bestJ = j; - minDist = dd; - } - } - - mdt.addObject(); - mdt.setValue(EMDL_MICROGRAPH_FRAME_NUMBER, i+1, i); - mdt.setValue(EMDL_MICROGRAPH_PRE_EXPOSURE, bestJ * fractionalDose, i); - } - - mdt.write(outFn); - - return 0; - - /*std::ofstream out(outFn); - - for (int i = 0; i < fc; i++) - { - double minDist = 1000000.0; - int bestJ = -1; - - for (int j = 0; j < order.size(); j++) - { - double d = order[j][1] - tilts[i]; - double dd = d*d; - - if (dd < minDist) - { - bestJ = j; - minDist = dd; - } - } - - out << (bestJ * fractionalDose) << '\n'; - } - - return 0;*/ -} diff --git a/src/jaz/scripts/enumerate_micrographs.cpp b/src/jaz/scripts/enumerate_micrographs.cpp deleted file mode 100644 index f27a152b8..000000000 --- a/src/jaz/scripts/enumerate_micrographs.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string particlesFn, outDir; - - IOParser parser; - - try - { - IOParser parser; - - parser.setCommandLine(argc, argv); - - int general_section = parser.addSection("General options"); - - particlesFn = parser.getOption("--i", "Input file (e.g. run_it023_data.star)"); - outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - outDir = ZIO::makeOutputDir(outDir); - - ObservationModel obs_model; - MetaDataTable particles_table; - ObservationModel::loadSafely(particlesFn, obs_model, particles_table); - - - std::vector particles_by_micrograph = StackHelper::splitByMicrographName(particles_table); - - const int micrograph_count = particles_by_micrograph.size(); - - - MetaDataTable output_table; - - for (int m = 0; m < micrograph_count; m++) - { - output_table.addObject(); - - output_table.setValue( - EMDL_MICROGRAPH_ID, - m, - m); - - output_table.setValue( - EMDL_MICROGRAPH_NAME, - particles_by_micrograph[m].getString(EMDL_MICROGRAPH_NAME, 0), - m); - } - - output_table.write(outDir + "micrographs.star"); - - return 0; -} diff --git a/src/jaz/scripts/extract_blob_points.cpp b/src/jaz/scripts/extract_blob_points.cpp deleted file mode 100644 index fdd3fd0c0..000000000 --- a/src/jaz/scripts/extract_blob_points.cpp +++ /dev/null @@ -1,343 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string micrographs_list_filename, micrographs_dir, blobs_dir, outPath; - double min_radius, max_radius, min_distance, perimeter_margin; - int num_threads; - bool diag, estimate_radius; - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - micrographs_list_filename = parser.getOption("--ml", "Micrograph lists filename"); - micrographs_dir = parser.getOption("--md", "Micrographs directory"); - blobs_dir = parser.getOption("--bd", "Initial blobs directory"); - min_distance = textToDouble(parser.getOption("--d", "Min. particle distance [bin-1 pixels]", "128")); - perimeter_margin = textToDouble(parser.getOption("--pm", "Distance of perimeter points from the outline [bin-1 pixels]", "64")); - estimate_radius = parser.checkOption("--est_rad", "Estimate the radius of the blob"); - min_radius = textToDouble(parser.getOption("--r0", "Min. radius [bin-1 pixels]", "300")); - max_radius = textToDouble(parser.getOption("--r1", "Max. radius [bin-1 pixels]", "800")); - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - - diag = parser.checkOption("--diag", "Write out diagnostic information"); - - outPath = parser.getOption("--o", "Output filename pattern"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - parser.writeUsage(std::cout); - exit(1); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - - outPath = ZIO::makeOutputDir(outPath); - - const std::string perimeter_dir = "perimeter/Frames/"; - const std::string full_dir = "full/Frames/"; - const std::string outer_half_dir = "outer_half/Frames/"; - - ZIO::makeOutputDir(outPath + perimeter_dir); - ZIO::makeOutputDir(outPath + full_dir); - ZIO::makeOutputDir(outPath + outer_half_dir); - - micrographs_dir = ZIO::ensureEndingSlash(micrographs_dir); - blobs_dir = ZIO::ensureEndingSlash(blobs_dir); - - std::vector all_micrograph_names; - all_micrograph_names.reserve(1000); - - std::ifstream file(micrographs_list_filename); - - if (!file) - { - REPORT_ERROR("Unable to read " + micrographs_list_filename); - } - - std::string line; - - while (std::getline(file, line)) - { - std::stringstream sts; - sts << line; - - std::string name; - sts >> name; - - all_micrograph_names.push_back(name); - } - - const int micrograph_count = all_micrograph_names.size(); - - std::vector failed_micrographs; - - #pragma omp parallel for num_threads(num_threads) - for (int m = 0; m < micrograph_count; m++) - { - const int thread_id = omp_get_thread_num(); - const bool verbose = thread_id == 0; - - if (verbose) - { - Log::beginSection( - "Micrograph "+ZIO::itoa(m+1)+"/" - +ZIO::itoa((int)std::ceil(micrograph_count / (double)num_threads))+" on this thread (out of " - +ZIO::itoa(micrograph_count)+" on all threads)"); - } - - try - { - const std::string micrograph_name = all_micrograph_names[m]; - const std::string micrograph_path = micrographs_dir + micrograph_name + ".mrc"; - const std::string blob_path = blobs_dir + micrograph_name + ".blobs"; - std::vector> blob_shapes = ZIO::readDoublesTable(blob_path); - - BufferedImage micrograph; - micrograph.read(micrograph_path); - - - const double pixel_size = ImageFileHelper::getSamplingRate(micrograph_path); - - const int w = micrograph.xdim; - const int h = micrograph.ydim; - - - BufferedImage weight(micrograph); - weight.fill(1.f); - - const int blob_count = blob_shapes.size(); - - BufferedImage plot(micrograph); - - std::vector blobs(blob_count); - - if (verbose) - { - Log::beginProgress("Processing Blobs", blob_count); - } - - for (int b = 0; b < blob_count; b++) - { - if (verbose) - { - Log::updateProgress(b); - } - - if (blob_shapes[b].size()%2 == 0) - { - for (int i = 0; i < blob_shapes[b].size(); i++) - { - std::cout << i << ": " << blob_shapes[b][i] << "\n"; - } - - REPORT_ERROR("The blobs in "+blob_path+" do not have a radius"); - } - - DelineatedBlob2D blob(blob_shapes[b]); - - if (estimate_radius) - { - std::pair,std::vector> radAvgAndWgh - = blob.radialAverageAndWeight( - micrograph, weight, max_radius); - - std::vector radAvg = radAvgAndWgh.first; - std::vector radWgh = radAvgAndWgh.second; - - const int bin_count = radAvg.size(); - - int best_t = 0; - double best_separation = 0.0; - - int delta_t = 20; - - for (int t = min_radius; t <= max_radius - delta_t && t < bin_count; t++) - { - double avg0 = 0.0; - double wgh0 = 0.0; - - int t0 = t - delta_t; - if (t0 < 0) t0 = 0; - - for (int i = t0; i < t; i++) - { - avg0 += radWgh[i] * radAvg[i]; - wgh0 += radWgh[i]; - } - - double avg1 = 0.0; - double wgh1 = 0.0; - - int t1 = t + delta_t + 1; - if (t0 > bin_count) t1 = bin_count; - - for (int i = t; i < t1; i++) - { - avg1 += radWgh[i] * radAvg[i]; - wgh1 += radWgh[i]; - } - - avg0 /= wgh0; - avg1 /= wgh1; - - const double separation = avg1 - avg0; - - if (separation > best_separation) - { - best_separation = separation; - best_t = t; - } - } - - blob.radius = best_t; - } - - blobs[b] = blob; - } - - if (verbose) - { - Log::endProgress(); - } - - const int EDGE = 0; - const int OUTER_HALF = 1; - const int FULL_BLOB = 2; - - std::vector> picks(3); - - - for (int b = 0; b < blob_count; b++) - { - DelineatedBlob2D blob = blobs[b]; - - - const double d = min_distance; - const double margin = d; - const double dd = 0.5 * sqrt(3.0) * d; - const int rc = (h - 2*margin) / dd + 1; - const std::vector cc = {(int)((w - 2*margin) / d), (int)((w - 2*margin - d/2) / d)}; - - for (int r = 0; r < rc; r++) - for (int c = 0; c < cc[r%2]; c++) - { - gravis::d2Vector p( - margin + (r%2)*d/2 + c*d, - margin + r*dd); - - double rr = blob.getRelativeSignedDistance(p); - - if (rr < 0) - { - picks[FULL_BLOB].push_back(p); - - if (diag) Drawing::drawCross(p, 100.f, 3, plot); - - if (rr > -0.5) - { - picks[OUTER_HALF].push_back(p); - - if (diag) Drawing::drawCross(p, 100.f, 6, plot); - } - } - } - - const double l = blob.perimeter(); - const int samples = std::floor(l / min_distance); - - DelineatedBlob2D smaller_blob(blob); - smaller_blob.radius -= perimeter_margin; - - for (int i = 0; i < samples; i++) - { - const double phi = 2 * PI * i / (double) samples; - const d2Vector p = smaller_blob.getOutlinePoint(phi); - - if (p.x > margin && p.x < w - margin - && p.y > margin && p.y < h - margin) - { - picks[EDGE].push_back(p); - - if (diag) Drawing::drawCross(p, 100.f, 10, plot); - } - } - } - - if (diag) plot.write(outPath + "diag_"+ZIO::itoa(m)+".mrc", pixel_size); - - std::vector tables(3); - - for (int i = 0; i < 3; i++) - { - const int pc = picks[i].size(); - MetaDataTable& table = tables[i]; - - table.setName("images"); - - table.addLabel(EMDL_IMAGE_COORD_X); - table.addLabel(EMDL_IMAGE_COORD_Y); - table.addLabel(EMDL_PARTICLE_AUTOPICK_FOM); - table.addLabel(EMDL_PARTICLE_CLASS); - table.addLabel(EMDL_ORIENT_PSI); - - for (int p = 0; p < pc; p++) - { - table.addObject(); - - table.setValue(EMDL_IMAGE_COORD_X, picks[i][p].x, p); - table.setValue(EMDL_IMAGE_COORD_Y, picks[i][p].y, p); - table.setValue(EMDL_PARTICLE_AUTOPICK_FOM, 1.0, p); - table.setValue(EMDL_PARTICLE_CLASS, 0, p); - table.setValue(EMDL_ORIENT_PSI, 0.0, p); - } - } - - tables[EDGE].write(outPath + perimeter_dir + micrograph_name + "_blob_pick.star"); - tables[FULL_BLOB].write(outPath + full_dir + micrograph_name + "_blob_pick.star"); - tables[OUTER_HALF].write(outPath + outer_half_dir + micrograph_name + "_blob_pick.star"); - } - catch (...) - { - #pragma omp critical - { - failed_micrographs.push_back(all_micrograph_names[m]); - } - } - - if (verbose) - { - Log::endSection(); - } - } - - - if (failed_micrographs.size() > 0) - { - ZIO::writeToFile(failed_micrographs, outPath + "failed_micrographs.txt"); - } - - return 0; -} diff --git a/src/jaz/scripts/find_blobs_2d.cpp b/src/jaz/scripts/find_blobs_2d.cpp deleted file mode 100644 index 2f2f51f24..000000000 --- a/src/jaz/scripts/find_blobs_2d.cpp +++ /dev/null @@ -1,428 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string particlesFn, class_averages_filename, outDir; - int num_threads, max_class, min_MG, max_MG; - double radius, binning, additional_binning; - bool flip_y, diag; - - - IOParser parser; - - try - { - IOParser parser; - - parser.setCommandLine(argc, argv); - - int general_section = parser.addSection("General options"); - - particlesFn = parser.getOption("--i", "Input file (e.g. run_it023_data.star)"); - class_averages_filename = parser.getOption("--ca", "Class averages stack"); - radius = textToDouble(parser.getOption("--r", "Average blob radius (in bin-1 pixels)", "300")); - flip_y = parser.checkOption("--flip_y", "Centre of blob lies in positive y direction"); - - - max_class = textToInteger(parser.getOption("--max_class", "Last 2D class to consider", "25")); - min_MG = textToInteger(parser.getOption("--min_MG", "First micrograph index", "0")); - max_MG = textToInteger(parser.getOption("--max_MG", "Last micrograph index", "-1")); - - binning = textToDouble(parser.getOption("--bin", "Binning level to work at", "8")); - additional_binning = textToDouble(parser.getOption("--bin2", "Additional binning for the log file", "4")); - - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - diag = parser.checkOption("--diag", "Write out diagnostic information"); - outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - outDir = ZIO::makeOutputDir(outDir); - - ObservationModel obs_model; - MetaDataTable particles_table; - ObservationModel::loadSafely(particlesFn, obs_model, particles_table); - - - std::vector particles_by_micrograph = StackHelper::splitByMicrographName(particles_table); - - const int micrograph_count = particles_by_micrograph.size(); - - if (max_MG < 0) - { - max_MG = micrograph_count - 1; - } - - i2Vector full_size, binned_size, log_size; - { - - const std::string micrograph_fn = particles_by_micrograph[0].getString(EMDL_MICROGRAPH_NAME, 0); - - BufferedImage micrograph; - micrograph.read(micrograph_fn); - - full_size.x = micrograph.xdim; - full_size.y = micrograph.ydim; - - BufferedImage micrograph_binned = Resampling::FourierCrop_fullStack( - micrograph, binning, num_threads, true); - - binned_size.x = micrograph_binned.xdim; - binned_size.y = micrograph_binned.ydim; - - BufferedImage micrograph_binned_2 = Resampling::FourierCrop_fullStack( - micrograph_binned, additional_binning, num_threads, true); - - log_size.x = micrograph_binned_2.xdim; - log_size.y = micrograph_binned_2.ydim; - - } - - const int w_log = log_size.x; - const int h_log = log_size.y; - - const int w_binned = binned_size.x; - const int h_binned = binned_size.y; - - BufferedImage log_image(w_log, h_log, max_MG + 1); - log_image.fill(0.f); - - - - Log::beginProgress("Finding blobs", (max_MG - min_MG + 1)/num_threads); - - std::vector> blob_coordinates(max_MG + 1); - - #pragma omp parallel for num_threads(num_threads) - for (int m = min_MG; m <= max_MG; m++) - { - const int thread_id = omp_get_thread_num(); - - if (thread_id == 0) - { - Log::updateProgress(m); - } - - MetaDataTable& particles = particles_by_micrograph[m]; - - const std::string micrograph_fn = particles.getString(EMDL_MICROGRAPH_NAME, 0); - - BufferedImage micrograph; - micrograph.read(micrograph_fn); - - BufferedImage micrograph_binned = Resampling::FourierCrop_fullStack( - micrograph, binning, 1, true); - - if (diag) - { - micrograph_binned.write(outDir + "mg_" + ZIO::itoa(m) + "_micrograph_binned.mrc"); - } - - BufferedImage accumulation_image(w_binned, h_binned); - - accumulation_image.fill(0.f); - - - const int particle_count = particles.numberOfObjects(); - - for (int p = 0; p < particle_count; p++) - { - const int class_id = particles.getIntMinusOne(EMDL_PARTICLE_CLASS, p); - - if (class_id <= max_class) - { - const d2Vector image_coord( - particles.getDouble(EMDL_IMAGE_COORD_X, p), - particles.getDouble(EMDL_IMAGE_COORD_Y, p)); - - const double phi = DEG2RAD(particles.getDouble(EMDL_ORIENT_PSI, p)); - - const d2Vector predicted_centre = flip_y? - (image_coord + radius * d2Vector(sin(phi), cos(phi))) / binning : - (image_coord - radius * d2Vector(sin(phi), cos(phi))) / binning; - - const int xi = (int)(predicted_centre.x + 0.5); - const int yi = (int)(predicted_centre.y + 0.5); - - if (xi >= 0 && xi < w_binned && yi >= 0 && yi < h_binned) - { - accumulation_image(xi, yi) += 1; - } - } - } - - BufferedImage blurred_accumulation_image = ImageFilter::Gauss2D( - accumulation_image, 0, 0.5 * radius / binning, true); - - if (diag) - { - blurred_accumulation_image.write(outDir + "mg_" + ZIO::itoa(m) + "_likelihood_by_particles.mrc"); - } - - BufferedImage blurred_micrograph_0 = ImageFilter::Gauss2D( - micrograph_binned, 0, 1.00 * radius / binning, true); - - BufferedImage blurred_micrograph_1 = ImageFilter::Gauss2D( - micrograph_binned, 0, 0.25 * radius / binning, true); - - BufferedImage dog_map = blurred_micrograph_0 - blurred_micrograph_1; - - if (diag) - { - dog_map.write(outDir + "mg_" + ZIO::itoa(m) + "_likelihood_by_appearance.mrc"); - } - - BufferedImage detections(w_binned, h_binned); - - for (int y = 0; y < h_binned; y++) - for (int x = 0; x < w_binned; x++) - { - const float dog = dog_map(x,y); - const float centre = blurred_accumulation_image(x,y); - - if (dog > 0.f && centre > 0.f) - { - detections(x,y) = dog * centre; - } - } - - if (diag) - { - detections.write(outDir + "mg_" + ZIO::itoa(m) + "_likelihood_total.mrc"); - } - - BufferedImage box_maxima = LocalExtrema::boxMaxima(detections, radius / binning); - - const float mean_DOG = Normalization::computeMean(detections); - const float threshold = mean_DOG; - - BufferedImage sparse_detections_image(w_binned, h_binned); - std::vector sparse_detections; - sparse_detections.reserve(100); - - for (int y = 0; y < h_binned; y++) - for (int x = 0; x < w_binned; x++) - { - const float bm = box_maxima(x,y); - const float dt = detections(x,y); - - if (bm == dt && dt > threshold) - { - sparse_detections_image(x,y) = dt; - sparse_detections.push_back(binning * d2Vector(x,y)); - } - else - { - sparse_detections_image(x,y) = 0.f; - } - } - - blob_coordinates[m] = sparse_detections; - - BufferedImage micrograph_binned_2 = Resampling::FourierCrop_fullStack( - micrograph_binned, additional_binning, 1, true); - - const float mean = Normalization::computeMean(micrograph_binned_2); - const float variance = Normalization::computeVariance(micrograph_binned_2, mean); - const float dot_value = mean + 7.f * sqrt(variance); - - RawImage log_slice = log_image.getSliceRef(m); - log_slice.copyFrom(micrograph_binned_2); - - for (int i = 0; i < sparse_detections.size(); i++) - { - const d2Vector d = sparse_detections[i] / (binning * additional_binning); - const int dx = (int)(d.x + 0.5); - const int dy = (int)(d.y + 0.5); - - if (dx >= 0 && dx < w_log && dy >= 0 && dy < h_log) - { - log_slice(dx,dy) = dot_value; - } - } - } - - Log::endProgress(); - - log_image.write(outDir+"diagnostic.mrc"); - - { - const int mc = blob_coordinates.size(); - - std::ofstream ofs(outDir+"blobs.star"); - - for (int m = 0; m < mc; m++) - { - MetaDataTable mdt; - mdt.setName(ZIO::itoa(m)); - - const int bc = blob_coordinates[m].size(); - - for (int b = 0; b < bc; b++) - { - const d2Vector p = blob_coordinates[m][b]; - - mdt.addObject(); - - mdt.setValue(EMDL_IMAGE_COORD_X, p.x); - mdt.setValue(EMDL_IMAGE_COORD_Y, p.y); - } - - mdt.write(ofs); - } - } - - return 0; - - - /* - - { - const double bin = 32; - const double radius_bin1 = 350; - const double radius_binned = radius_bin1 / bin; - const double threshold = 0.1; - - BufferedImage micrograph_binned = Resampling::FourierCrop_fullStack( - micrograph_filtered, bin, num_threads, true); - - micrograph_binned.write(outPath+"DEBUG_micrograph_binned.mrc"); - - BufferedImage symm = evaluateRotationalSymmetry( - micrograph_binned, radius_binned, 1.5*radius_binned, 0.25*radius_binned); - - float mean = Normalization::computeMean(symm); - - symm -= mean; - - symm.write(outPath+"DEBUG_symmetry.mrc"); - - - BufferedImage lowpass0 = ImageFilter::Gauss2D( - micrograph_binned, 0, 0.5 * radius_binned, true); - - BufferedImage lowpass1 = ImageFilter::Gauss2D( - micrograph_binned, 0, 1.500 * radius_binned, true); - - BufferedImage dog = lowpass1 - lowpass0; - - dog.write(outPath+"DEBUG_dog.mrc"); - - double var_dog = Normalization::computeVariance(dog, 0.f); - double var_symm = Normalization::computeVariance(symm, 0.f); - - dog /= sqrt(var_dog); - symm /= sqrt(var_symm); - - dog = ImageFilter::thresholdAbove(dog, 0.f); - symm = ImageFilter::thresholdAbove(symm, 0.f); - - BufferedImage product = dog * symm; - - product.write(outPath+"DEBUG_product.mrc"); - - BufferedImage box_maxima = LocalExtrema::boxMaxima( - product, (int)(0.72 * radius_binned)); - - box_maxima.write(outPath+"DEBUG_product_maxima.mrc"); - - std::vector peaks = LocalExtrema::discretePoints2D( - product, box_maxima, (float)threshold); - - const float mean_mg = Normalization::computeMean(micrograph_binned); - const float var_mg = Normalization::computeVariance(micrograph_binned, mean_mg); - const float drawing_value = mean_mg + 5 * sqrt(var_mg); - - Drawing::drawCrosses(peaks, drawing_value, 5, micrograph_binned); - - micrograph_binned.write(outPath+"DEBUG_detections.mrc"); - - std::exit(0); - } - - */ -} - -/* -BufferedImage DeleteBlobs2DProgram::evaluateRotationalSymmetry( - const RawImage &image, double radius, double max_radius, double sigma) -{ - const int w = image.xdim; - const int h = image.ydim; - - BufferedImage out(w,h); - - BufferedImage weight(w,h); - weight.fill(1.f); - - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) - { - std::vector params{(double)x, (double)y}; - Blob2D blob(params, max_radius); - - std::vector radAvg = blob.radialAverage(image, weight); - - double sum = 0, sum_wgh = 0; - - for (int i = 0; i < radAvg.size(); i++) - { - sum += radAvg[i] * i; - sum_wgh += i; - } - - const double avg = sum / sum_wgh; - - double power = 0; - - for (int i = 0; i < radAvg.size(); i++) - { - const double d = radAvg[i] - avg; - const double dr = i - radius; - const double g = exp(-dr/(2*sigma*sigma)); - - power += g * d * d * i; - } - - out(x,y) = power; - } - - return out; -}*/ diff --git a/src/jaz/scripts/fit_class_blobs.cpp b/src/jaz/scripts/fit_class_blobs.cpp deleted file mode 100644 index 692968ba1..000000000 --- a/src/jaz/scripts/fit_class_blobs.cpp +++ /dev/null @@ -1,313 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string particlesFn, class_averages_filename, classes_filename, outDir; - int num_threads, num_frequencies, min_MG, max_MG, max_iterations; - double radius, edge_padding; - bool diag, flip_y; - - - IOParser parser; - - try - { - IOParser parser; - - parser.setCommandLine(argc, argv); - - int general_section = parser.addSection("General options"); - - particlesFn = parser.getOption("--i", "Input STAR file output by align_2d_classes"); - class_averages_filename = parser.getOption("--ca", "Class averages stack"); - classes_filename = parser.getOption("--classes", "File with a list of 2D classes to consider"); - radius = textToDouble(parser.getOption("--r", "Average blob radius (in bin-1 pixels)", "600")); - flip_y = parser.checkOption("--flip_y", "Centre of blob lies in positive y direction"); - edge_padding = textToDouble(parser.getOption("--pad", "Edge padding (in bin-1 pixels)", "20")); - num_frequencies = textToInteger(parser.getOption("--f", "Number of 1D frequencies used to model the blob", "10")); - - min_MG = textToInteger(parser.getOption("--min_MG", "First micrograph index", "0")); - max_MG = textToInteger(parser.getOption("--max_MG", "Last micrograph index", "-1")); - - max_iterations = textToInteger(parser.getOption("--it", "Maximal number of iterations", "1000")); - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - diag = parser.checkOption("--diag", "Write out diagnostic information"); - outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - outDir = ZIO::makeOutputDir(outDir); - - ObservationModel obs_model; - MetaDataTable particles_table; - ObservationModel::loadSafely(particlesFn, obs_model, particles_table); - - BufferedImage class_averages; - class_averages.read(class_averages_filename); - - - const int box_size = class_averages.xdim; - const int num_classes = class_averages.zdim; - - std::vector classes_to_consider = ZIO::readInts(classes_filename); - const int relevant_class_count = classes_to_consider.size(); - - std::vector class_to_subset(num_classes, -1); - - for (int i = 0; i < relevant_class_count; i++) - { - class_to_subset[classes_to_consider[i]] = i; - } - - - const double pixel_size = obs_model.getPixelSize(0); - - - BufferedImage blob_fits(box_size, box_size, relevant_class_count); - std::vector> all_optimal_parameters(relevant_class_count); - - - - Log::beginProgress("Fitting blobs", relevant_class_count/num_threads); - - #pragma omp parallel for num_threads(num_threads) - for (int cc = 0; cc < relevant_class_count; cc++) - { - const int thread_id = omp_get_thread_num(); - - if (thread_id == 0) - { - Log::updateProgress(cc); - } - - const int class_id = classes_to_consider[cc]; - - RawImage slice = class_averages.getSliceRef(class_id); - const d2Vector initial_centre(box_size/2, box_size/2 + (flip_y? radius : -radius)); - - BlobFit2D blob_fit( - slice, initial_centre, radius/2, 0, 0, num_threads); - - for (int y = 0; y < blob_fit.weight.ydim; y++) - for (int x = 0; x < blob_fit.weight.xdim; x++) - { - const double dx = x - box_size/2; - const double dy = y - box_size/2; - const double r = sqrt(dx*dx + dy*dy); - - if (r < box_size/2 - edge_padding) - { - blob_fit.weight(x,y) = 1; - } - else - { - blob_fit.weight(x,y) = 0; - } - } - - - std::vector initial_parameters(num_frequencies + 2, 0.0); - initial_parameters[0] = initial_centre.x; - initial_parameters[1] = initial_centre.y; - - std::vector optimal_parameters = NelderMead::optimize( - initial_parameters, blob_fit, 2, 0.001, max_iterations, 1.0, 2.0, 0.5, 0.5, false); - - all_optimal_parameters[cc] = optimal_parameters; - - - Blob2D blob(optimal_parameters, radius + 2*box_size); - - std::vector radial_average = blob.radialAverage(slice, blob_fit.weight); - BufferedImage projection = blob.radialAverageProjection(slice, radial_average); - - blob_fits.copySliceFrom(cc, projection); - - // DEBUG: - /*{ - const double c = box_size/2; - std::vector coeffs0 = {c, 0.0, 20.0, 0.0, 20.0, 0.0}; - Blob2D b0(coeffs0, box_size); - - std::vector radial_average(box_size+1); - - for (int i = 0; i < box_size; i++) - { - radial_average[i] = sin(i); - } - - BufferedImage projection; - - projection = b0.radialAverageProjection(slice, radial_average); - - projection.write("DEBUG_projection_0.mrc", pixel_size); - - std::vector coeffs1 = Blob2D::rotate(coeffs0, DEG2RAD(30), d2Vector(c,c)); - Blob2D b1(coeffs1, box_size); - - projection = b1.radialAverageProjection(slice, radial_average); - - projection.write("DEBUG_projection_1.mrc", pixel_size); - - std::exit(0); - }*/ - } - - Log::endProgress(); - - blob_fits.write(outDir+"blob_fits_by_class.mrc", pixel_size); - - - - ZIO::makeOutputDir(outDir+"Frames"); - - MetaDataTable output_particles; - - std::vector particles_by_micrograph = StackHelper::splitByMicrographName(particles_table); - const int micrograph_count = particles_by_micrograph.size(); - - Log::beginProgress("Deleting Blobs", micrograph_count); - - for (int m = 0; m < micrograph_count; m++) - { - Log::updateProgress(m); - - const MetaDataTable& particles = particles_by_micrograph[m]; - const int particle_count = particles.numberOfObjects(); - - - std::vector compressed_particle_indices(particle_count, -1); - - int current_index = 0; - - for (int p = 0; p < particle_count; p++) - { - const int global_class_id = particles.getIntMinusOne(EMDL_PARTICLE_CLASS, p); - const int selected_class_id = class_to_subset[global_class_id]; - - if (selected_class_id >= 0) - { - compressed_particle_indices[p] = current_index; - current_index++; - } - } - - const int relevant_particle_count = current_index; - - if (relevant_particle_count > 0) - { - BufferedImage all_particle_images(box_size, box_size, relevant_particle_count); - BufferedImage all_blob_images(box_size, box_size, relevant_particle_count); - - #pragma omp parallel for num_threads(num_threads) - for (int p = 0; p < particle_count; p++) - { - const int global_class_id = particles.getIntMinusOne(EMDL_PARTICLE_CLASS, p); - const int selected_class_id = class_to_subset[global_class_id]; - - if (selected_class_id >= 0) - { - const double dx_A = particles.getDouble(EMDL_ORIENT_ORIGIN_X_ANGSTROM, p); - const double dy_A = particles.getDouble(EMDL_ORIENT_ORIGIN_Y_ANGSTROM, p); - - std::vector raw_blob_parameters = all_optimal_parameters[selected_class_id]; - raw_blob_parameters[0] += dx_A / pixel_size; - raw_blob_parameters[1] += dy_A / pixel_size; - - const d2Vector raw_blob_centre(raw_blob_parameters[0], raw_blob_parameters[1]); - const d2Vector image_centre((double)(box_size/2), (double)(box_size/2)); - const double max_dist = (image_centre - raw_blob_centre).length() + box_size / sqrt(2.0) + 1; - - const double phi = DEG2RAD(particles.getDouble(EMDL_ORIENT_PSI, p)); - - const double centre = box_size / 2; - const d2Vector axis(centre,centre); - - std::vector rotated_blob_parameters = Blob2D::rotate(raw_blob_parameters, phi, axis); - Blob2D blob(rotated_blob_parameters, max_dist); - - BufferedImage weight(box_size,box_size); - weight.fill(1.f); - - - std::string img_fn = particles.getString(EMDL_IMAGE_NAME, p); - BufferedImage particle_image; - particle_image.read(img_fn); - - std::vector rad_average = blob.radialAverage(particle_image, weight); - BufferedImage projection = blob.radialAverageProjection(particle_image, rad_average); - - particle_image -= projection; - - const int index = compressed_particle_indices[p]; - all_particle_images.copySliceFrom(index, particle_image); - all_blob_images.copySliceFrom(index, projection); - } - } - - std::string img_fn = particles.getString(EMDL_IMAGE_NAME, 0); - img_fn = outDir + "Frames/" + img_fn.substr(img_fn.find_last_of('/')+1); - - all_particle_images.write(img_fn); - all_blob_images.write(img_fn.substr(0,img_fn.find_last_of('.'))+"_blobs.mrcs"); - - for (int p = 0; p < particle_count; p++) - { - const int index = compressed_particle_indices[p]; - - if (index >= 0) - { - output_particles.addObject(); - output_particles.setObject(particles.getObject(p)); - output_particles.setValue(EMDL_IMAGE_NAME, ZIO::itoa(index+1) + "@" + img_fn); - } - } - } - } - - Log::endProgress(); - - ObservationModel::saveNew(output_particles, obs_model.opticsMdt, obs_model.generalMdt, outDir + "particles.star"); - - return 0; -} diff --git a/src/jaz/scripts/img_test.cpp b/src/jaz/scripts/img_test.cpp deleted file mode 100644 index 7739eb5c6..000000000 --- a/src/jaz/scripts/img_test.cpp +++ /dev/null @@ -1,33 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace gravis; -using namespace au::edu::anu::qm::ro; - -template -void test(const RawImage& img) -{ - std::cout << img.ydim << "\n"; -} - -int main(int argc, char *argv[]) -{ - BufferedImage imgVec0(64,64,64); - RawImage img0(64,64,64,imgVec0.data); - std::cout << img0.ydim << "\n"; - test(img0); - return 0; -} diff --git a/src/jaz/scripts/imod_test.cpp b/src/jaz/scripts/imod_test.cpp deleted file mode 100644 index 26d6f8b09..000000000 --- a/src/jaz/scripts/imod_test.cpp +++ /dev/null @@ -1,130 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - if (false) - { - Image stack; - stack.read("imod_good/b001ts001.ali:mrc"); - - BufferedImage stack2(stack.data.xdim, stack.data.ydim, stack.data.zdim); - - for (int z = 0; z < stack.data.zdim; z++) - for (int y = 0; y < stack.data.ydim; y++) - for (int x = 0; x < stack.data.xdim; x++) - { - stack2(x,y,z) = stack(z,y,x); - } - - stack2.write("imod_good/b001ts001_nohead.ali:mrc"); - - for (int z = 0; z < stack.data.zdim; z++) - for (int y = 0; y < stack.data.ydim; y++) - for (int x = 0; x < stack.data.xdim; x++) - { - stack(z,y,x) = (x == y)? 1.0 : 0.0; - } - - stack.write("diagonal.ali:mrc"); - - for (int z = 0; z < stack.data.zdim; z++) - for (int y = 0; y < stack.data.ydim; y++) - for (int x = 0; x < stack.data.xdim; x++) - { - stack2(x,y,z) = (x == y)? 1.0 : 0.0; - } - - stack2.write("diagonal_nohead.ali:mrc"); - - return 0; - } - - /*if (false) - { - std::string stack_fn = "gridStack.mrc"; - std::string tlt_fn = "test_off2.tlt"; - std::string xf_fn = "testC.xf"; - - TomoStack ts0 = TomoStack(stack_fn, -1, tlt_fn, xf_fn, "", 1.0, 1.0); - - const int w = ts0.images[0].xdim; - const int h = ts0.images[0].ydim; - const int d = 81; // field THICKNESS in .com file - - BufferedImage dest(w,d,h); - BufferedImage maskDest(w,d,h); - - dest.fill(0.0); - maskDest.fill(0.0); - - d3Vector origin(0.0, -d/2.0 + 1.0, 0.0); - d3Vector spacing(1.0); - - const int n_threads = 6; - - RealSpaceBackprojection::backprojectRaw( - ts0, dest, maskDest, origin, spacing, n_threads, - RealSpaceBackprojection::Linear, - 2, 2, 1.0); - - dest.writeVtk("gridStack_dyn_testC_off2.vtk", d3Vector(0.0, d/2, 0.0), d3Vector(1.0)); - }*/ - - //if (false) - { - const int w = 240; - const int h = 160; - const int s = 240; - const int fc = 5; - - BufferedImage testImg(w,h,fc); - testImg.fill(0.f); - - for (int i = 0; i < s; i++) - { - for (int d = 1; d <= 3; d++) - { - const double e = s / (2 << d); - const double intensity = 1.0 / d; - const int qMax = (int) FLOOR(s / e); - - for (int q = 0; q <= qMax; q++) - { - const int r = ((int)(q * e + 0.5) + s/2) % s; - - for (int f = 0; f < fc; f++) - for (int t = 0; t < s; t++) - { - if (r < w && t < h) testImg(r,t,f) += intensity; - if (r < h && t < w) testImg(t,r,f) += intensity; - } - } - } - } - - testImg.write("gridStack.mrc"); - testImg.write("gridStack.vtk"); - - return 1; - } - - - - -} diff --git a/src/jaz/scripts/make_split_tilts_star.cpp b/src/jaz/scripts/make_split_tilts_star.cpp deleted file mode 100644 index 6906f4c2f..000000000 --- a/src/jaz/scripts/make_split_tilts_star.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include -#include -#include -#include -#include - - -int main(int argc, char *argv[]) -{ - std::map> movies_by_tomo; - - for (int i = 1; i < argc; i++) - { - std::string arg = std::string(argv[i]); - std::string arg_no_path = arg.substr(arg.find_last_of('/')+1); - - int tomo_index = -1; - int tilt_index = -1; - - if (!sscanf(arg_no_path.c_str(), "TS_%d_%d_%*s", &tomo_index, &tilt_index)) - { - std::cerr << "failed to extract indices from " << argv[i] << std::endl; - } - else - { - std::string tomo_name = arg_no_path.substr(0, arg_no_path.find_first_of('_', 3)); - - movies_by_tomo[tomo_name][tilt_index] = arg; - } - } - - std::ofstream out_stream("tilt_frames.star"); - - for (auto it = movies_by_tomo.begin(); it != movies_by_tomo.end(); it++) - { - MetaDataTable table; - - std::cout << it->first << std::endl; - - table.setName(it->first); - - for (auto itt = it->second.begin(); itt != it->second.end(); itt++) - { - std::cout << " " << itt->first << " " << itt->second << std::endl; - - table.addObject(); - table.setValue(EMDL_TOMO_TILT_MOVIE_INDEX, itt->first); - table.setValue(EMDL_TOMO_TILT_MOVIE_FILE_NAME, itt->second); - } - - table.write(out_stream); - } - - out_stream.flush(); - - return 0; -} diff --git a/src/jaz/scripts/measure_noise.cpp b/src/jaz/scripts/measure_noise.cpp deleted file mode 100644 index 0a40a1d5b..000000000 --- a/src/jaz/scripts/measure_noise.cpp +++ /dev/null @@ -1,240 +0,0 @@ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - std::string outDir; - int num_threads, tomoIndex, boxSize; - - OptimisationSet optimisationSet; - - //ReferenceMap reference; - TomoReferenceMap referenceMap; - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - - optimisationSet.read( - parser, - true, // optimisation set - true, true, // particles - true, true, // tomograms - true, false, // trajectories - false, false, // manifolds - true, true); // reference - - int gen_section = parser.addSection("General refinement options"); - - boxSize = textToInteger(parser.getOption("--b", "Box size")); - - referenceMap.read(optimisationSet); - - tomoIndex = textToInteger(parser.getOption("--ti", "Tomogram index", "0")); - boxSize = textToInteger(parser.getOption("--b", "Box size")); - - num_threads = textToInteger(parser.getOption("--j", "Number of threads", "8")); - outDir = parser.getOption("--o", "Output path"); - - parser.checkForErrors(); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - parser.writeUsage(std::cout); - std::exit(-1); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - return RELION_EXIT_FAILURE; - } - - outDir = ZIO::prepareTomoOutputDirectory(outDir, argc, argv); - - - TomogramSet tomogramSet(optimisationSet.tomograms); - - ParticleSet dataSet(optimisationSet.particles); - std::vector> particles = dataSet.splitByTomogram(tomogramSet); - - AberrationsCache aberrationsCache(dataSet.optTable, boxSize, dataSet.getOriginalPixelSize(0)); - - referenceMap.load(boxSize); - - - Tomogram tomogram = tomogramSet.loadTomogram(tomoIndex, true); - tomogram.validateParticleOptics(particles[tomoIndex], dataSet); - - BufferedImage doseWeights = tomogram.computeDoseWeight(boxSize, 1.0); - - const int s = referenceMap.getBoxSize(); - const int sh = s/2 + 1; - const int fc = tomogram.frameCount; - - std::vector> sum_delta2_f(fc, std::vector(sh, 0.0)); - std::vector> sum_obsPwr_f(fc, std::vector(sh, 0.0)); - std::vector> sum_weight_f(fc, std::vector(sh, 0.0)); - - - const int pc = particles[tomoIndex].size(); - - Log::beginProgress("Measuring noise", pc); - - for (int p = 0; p < pc; p++) - { - Log::updateProgress(p); - - const ParticleIndex part_id(p); - - const std::vector traj = dataSet.getTrajectoryInPixels(part_id, fc, tomogram.optics.pixelSize); - - #pragma omp parallel for num_threads(num_threads) - for (int f = 0; f < fc; f++) - { - d4Matrix projCut; - - BufferedImage> observation(sh,s); - - TomoExtraction::extractFrameAt3D_Fourier( - tomogram.stack, f, s, 1.0, tomogram, traj[f], - observation, projCut, 1, true); - - CTF ctf = tomogram.getCtf(f, dataSet.getPosition(part_id)); - RawImage doseSlice = doseWeights.getSliceRef(f); - - BufferedImage prediction = Prediction::predictModulated( - part_id, dataSet, tomogram.projectionMatrices[f], s, - ctf, tomogram.optics.pixelSize, aberrationsCache, - referenceMap.image_FS, - Prediction::OwnHalf, - Prediction::AmplitudeModulated, - &doseSlice, - Prediction::CtfScaled); - - for (int y = 0; y < sh; y++) - for (int x = 0; x < s; x++) - { - const double xx = x; - const double yy = y < s/2? y : y - s; - const double r = sqrt(xx*xx + yy*yy); - - const fComplex delta = prediction(x,y) - (-observation(x,y)); - - const int ri = (int) r; - - if (ri < sh) - { - sum_delta2_f[f][ri] += delta.norm(); - sum_obsPwr_f[f][ri] += observation(x,y).norm(); - sum_weight_f[f][ri] += 1.0; - } - } - } - } - - Log::endProgress(); - - - std::vector sum_delta2(sh, 0.0); - std::vector sum_obsPwr(sh, 0.0); - std::vector sum_weight(sh, 0.0); - - for (int f = 0; f < fc; f++) - { - std::vector var_delta(sh, 0.0), var_obs(sh, 0.0); - - for (int ri = 0; ri < sh; ri++) - { - if (sum_weight_f[f][ri] > 0.0) - { - var_delta[ri] = sum_delta2_f[f][ri] / sum_weight_f[f][ri]; - var_obs[ri] = sum_obsPwr_f[f][ri] / sum_weight_f[f][ri]; - } - - sum_delta2[ri] += sum_delta2_f[f][ri]; - sum_obsPwr[ri] += sum_obsPwr_f[f][ri]; - sum_weight[ri] += sum_weight_f[f][ri]; - } - - std::ofstream out(outDir + "noise_frame_" + ZIO::itoa(f) + ".dat"); - - for (int ri = 0; ri < sh; ri++) - { - out << ri << ' ' << var_delta[ri] << '\n'; - } - - out << '\n'; - - for (int ri = 0; ri < sh; ri++) - { - out << ri << ' ' << var_obs[ri] << '\n'; - } - - - } - - std::vector var_delta(sh, 0.0), var_obs(sh, 0.0); - - for (int ri = 0; ri < sh; ri++) - { - if (sum_weight[ri] > 0.0) - { - var_delta[ri] = sum_delta2[ri] / sum_weight[ri]; - var_obs[ri] = sum_obsPwr[ri] / sum_weight[ri]; - } - } - - std::ofstream out(outDir + "noise_all_frames.dat"); - - for (int ri = 0; ri < sh; ri++) - { - out << ri << ' ' << var_delta[ri] << '\n'; - } - - out << '\n'; - - for (int ri = 0; ri < sh; ri++) - { - out << ri << ' ' << var_obs[ri] << '\n'; - } - - return RELION_EXIT_SUCCESS; -} diff --git a/src/jaz/scripts/measure_scale.cpp b/src/jaz/scripts/measure_scale.cpp deleted file mode 100644 index cc1e2f8a1..000000000 --- a/src/jaz/scripts/measure_scale.cpp +++ /dev/null @@ -1,352 +0,0 @@ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace gravis; - - -BufferedImage computeFrequencyWeights( - const Tomogram& tomogram, TomoReferenceMap& referenceMap, - bool whiten, int num_threads) -{ - const int s = referenceMap.image_FS[0].ydim; - const int sh = s / 2 + 1; - const int fc = tomogram.frameCount; - - BufferedImage frqWghts(sh,s,fc); - - if (whiten) - { - #pragma omp parallel for num_threads(num_threads) - for (int f = 0; f < fc; f++) - { - BufferedImage powSpec = PowerSpectrum::periodogramAverage2D( - tomogram.stack, s, s, 2.0, f, false); - - std::vector powSpec1D = RadialAvg::fftwHalf_2D_lin(powSpec); - - std::vector frqWghts1D(powSpec1D.size()); - - for (int i = 0; i < powSpec1D.size(); i++) - { - frqWghts1D[i] = (float)(1.0 / powSpec1D[i]); - } - - RawImage fw = frqWghts.getSliceRef(f); - RadialAvg::toFftwHalf_2D_lin(frqWghts1D, sh, s, fw); - } - - - BufferedImage staticSigma2(sh,s); - staticSigma2.fill(0.f); - - for (int f = 0; f < fc; f++) - { - for (int y = 0; y < s; y++) - for (int x = 0; x < sh; x++) - { - const double val = frqWghts(x,y,f); - - if (val > 0.f) - { - staticSigma2(x,y) += 1.f / val; - } - } - } - - for (int f = 0; f < fc; f++) - { - for (int y = 0; y < s; y++) - for (int x = 0; x < sh; x++) - { - frqWghts(x,y,f) = fc / staticSigma2(x,y); - } - } - } - else - { - frqWghts.fill(1.0); - } - - for (int f = 0; f < fc; f++) - { - referenceMap.contributeWeight(frqWghts.getSliceRef(f)); - } - - BufferedImage doseWeights = tomogram.computeDoseWeight(s, 1.0); - frqWghts *= doseWeights; - - return frqWghts; -} - - - -int main(int argc, char *argv[]) -{ - std::string outDir; - int num_threads, boxSize; - - OptimisationSet optimisationSet; - - TomoReferenceMap referenceMap; - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - - optimisationSet.read( - parser, - true, // optimisation set - true, true, // particles - true, true, // tomograms - true, false, // trajectories - false, false, // manifolds - true, true); // reference - - int gen_section = parser.addSection("General refinement options"); - - boxSize = textToInteger(parser.getOption("--b", "Box size")); - - referenceMap.read(optimisationSet); - - boxSize = textToInteger(parser.getOption("--b", "Box size")); - - num_threads = textToInteger(parser.getOption("--j", "Number of threads", "8")); - outDir = parser.getOption("--o", "Output path"); - - parser.checkForErrors(); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - parser.writeUsage(std::cout); - std::exit(-1); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - return RELION_EXIT_FAILURE; - } - - outDir = ZIO::prepareTomoOutputDirectory(outDir, argc, argv); - - - TomogramSet tomogramSet(optimisationSet.tomograms); - - ParticleSet dataSet(optimisationSet.particles); - std::vector> particles = dataSet.splitByTomogram(tomogramSet); - - AberrationsCache aberrationsCache(dataSet.optTable, boxSize, dataSet.getOriginalPixelSize(0)); - - referenceMap.load(boxSize); - - - const int f0 = 10; - const int f1 = 30; - - for (int tomoIndex = 0; tomoIndex < tomogramSet.size(); tomoIndex++) - { - Tomogram tomogram = tomogramSet.loadTomogram(tomoIndex, true); - tomogram.validateParticleOptics(particles[tomoIndex], dataSet); - - std::string outDirTomo = outDir + tomogram.name + "/"; - ZIO::ensureParentDir(outDirTomo); - - const int s = referenceMap.getBoxSize(); - const int sh = s/2 + 1; - const int fc = tomogram.frameCount; - - std::vector> sum_prdObs_f(fc, std::vector(sh, 0.0)); - std::vector> sum_prdSqr_f(fc, std::vector(sh, 0.0)); - - - BufferedImage doseWeights = tomogram.computeDoseWeight(s, 1.0); - - BufferedImage frqWeight = computeFrequencyWeights( - tomogram, referenceMap, true, num_threads); - - - const int pc = particles[tomoIndex].size(); - - Log::beginProgress("Measuring scale", pc); - - for (int p = 0; p < pc; p++) - { - Log::updateProgress(p); - - const ParticleIndex part_id = particles[tomoIndex][p]; - - const std::vector traj = dataSet.getTrajectoryInPixels(part_id, fc, tomogram.optics.pixelSize); - - #pragma omp parallel for num_threads(num_threads) - for (int f = f0; f <= f1; f++) - { - d4Matrix projCut; - - BufferedImage> observation(sh,s); - - TomoExtraction::extractFrameAt3D_Fourier( - tomogram.stack, f, s, 1.0, tomogram, traj[f], - observation, projCut, 1, true); - - CTF ctf = tomogram.getCtf(f, dataSet.getPosition(part_id)); - RawImage doseSlice = doseWeights.getSliceRef(f); - - BufferedImage prediction = Prediction::predictModulated( - part_id, dataSet, tomogram.projectionMatrices[f], s, - ctf, tomogram.optics.pixelSize, aberrationsCache, - referenceMap.image_FS, - Prediction::OwnHalf, - Prediction::AmplitudeModulated, - &doseSlice, - Prediction::CtfUnscaled); - - - const double cos_f = tomogram.projectionMatrices[f](2,2); - const double sin2_f = 1.0 - cos_f * cos_f; - const double tan2_f = sin2_f / (cos_f * cos_f); - - for (int y = 0; y < sh; y++) - for (int x = 0; x < s; x++) - { - const double xx = x; - const double yy = y < s/2? y : y - s; - const double r = sqrt(xx*xx + yy*yy); - - const fComplex obs = -observation(x,y); - const fComplex prd = prediction(x,y); - - const int ri = (int) r; - - if (ri < sh) - { - sum_prdObs_f[f][ri] += frqWeight(x,y) * (prd.real * obs.real + prd.imag * obs.imag); - sum_prdSqr_f[f][ri] += frqWeight(x,y) * (prd.real * prd.real + prd.imag * prd.imag); - } - } - } - } - - Log::endProgress(); - - - std::vector sum_prdObs_byFreq(sh, 0.0); - std::vector sum_prdSqr_byFreq(sh, 0.0); - - std::vector sum_prdObs_byFrame(fc, 0.0); - std::vector sum_prdSqr_byFrame(fc, 0.0); - std::vector ratio_byFrame(fc, 0.0); - - double sum_prdObs_tomo = 0.0; - double sum_prdSqr_tomo = 0.0; - - const double eps = 0.01; - - for (int f = 0; f < fc; f++) - { - std::vector ratio(sh, 0.0); - - for (int ri = 0; ri < sh; ri++) - { - if (sum_prdSqr_f[f][ri] > eps) - { - ratio[ri] = sum_prdObs_f[f][ri] / sum_prdSqr_f[f][ri]; - } - - sum_prdObs_byFreq[ri] += sum_prdObs_f[f][ri]; - sum_prdSqr_byFreq[ri] += sum_prdSqr_f[f][ri]; - - sum_prdObs_byFrame[f] += sum_prdObs_f[f][ri]; - sum_prdSqr_byFrame[f] += sum_prdSqr_f[f][ri]; - - sum_prdObs_tomo += sum_prdObs_f[f][ri]; - sum_prdSqr_tomo += sum_prdSqr_f[f][ri]; - } - - std::ofstream out(outDirTomo + "scale_over_freq__frame_" + ZIO::itoa(f) + ".dat"); - - for (int ri = 0; ri < sh; ri++) - { - if (ratio[ri] > 0.0) - { - out << ri << ' ' << ratio[ri] << '\n'; - } - } - - if (sum_prdSqr_byFrame[f] > eps) - { - ratio_byFrame[f] = sum_prdObs_byFrame[f] / sum_prdSqr_byFrame[f]; - } - } - - std::cout << tomogram.name << ": " << (sum_prdObs_tomo / sum_prdSqr_tomo) << '\n'; - - std::vector ratio_byFreq(sh, 0.0); - std::ofstream out(outDirTomo + "scale_over_freq__all_frames.dat"); - - for (int ri = 0; ri < sh; ri++) - { - if (sum_prdSqr_byFreq[ri] > eps) - { - ratio_byFreq[ri] = sum_prdObs_byFreq[ri] / sum_prdSqr_byFreq[ri]; - out << ri << ' ' << ratio_byFreq[ri] << '\n'; - } - } - - - std::ofstream out2(outDirTomo + "scale_over_frame.dat"); - std::ofstream out3(outDirTomo + "thickness_by_frame.dat"); - - for (int f = 0; f < fc; f++) - { - if (ratio_byFrame[f] > 0.0) - { - out2 << f << ' ' << ratio_byFrame[f] << '\n'; - } - - const double cos_f = tomogram.projectionMatrices[f](2,2); - const double sin2_f = 1.0 - cos_f * cos_f; - const double tan2_f = sin2_f / (cos_f * cos_f); - - out3 << f << ' ' << 1.0 / sqrt(1 + tan2_f) << '\n'; - } - } - - return RELION_EXIT_SUCCESS; -} diff --git a/src/jaz/scripts/membrane_erase_2D.cpp b/src/jaz/scripts/membrane_erase_2D.cpp deleted file mode 100644 index 8f9686dc8..000000000 --- a/src/jaz/scripts/membrane_erase_2D.cpp +++ /dev/null @@ -1,165 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - IOParser parser; - - std::string outTag, tomoListFn, catFnN, catFnS, catFnC; - - int num_threads; - double diameter, binning, thickness; - bool diag; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - catFnN = parser.getOption("--co", "Catalogue file, outer membrane particles"); - catFnS = parser.getOption("--ci", "Catalogue file, inner membrane particles"); - catFnC = parser.getOption("--cc", "Catalogue file, substack particles"); - - tomoListFn = parser.getOption("--t", "Tomogram list", "tomolist.txt"); - - diameter = textToDouble(parser.getOption("--d", "Disc diameter in binned pixels", "64")); - thickness = textToDouble(parser.getOption("--th", "Membrane thickness in binned pixels", "3")); - - - binning = textToDouble(parser.getOption("--bin", "Binning factor", "1")); - diag = parser.checkOption("--diag", "Write out diagnostic information"); - - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - outTag = parser.getOption("--o", "Output filename pattern"); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - Catalogue catN(catFnN), catS(catFnS), catC(catFnC); - TomoList tomoList(tomoListFn); - - const int tc = catN.particles.size(); - - if (catN.particles.size() != catS.particles.size()) - { - REPORT_ERROR_STR("Unequal numbers of particles in " - << catFnN << " and " << catFnS << "."); - } - - int dummy = std::system(("mkdir -p " + outTag).c_str()); - - std::string diagTag = outTag + "/diag/"; - - if (diag) - { - int dummy = std::system(("mkdir -p " + diagTag).c_str()); - } - - for (int tt = 0; tt < tc; tt++) - { - DynamoParticle& partC = catC.particles[tt]; - - DynamoParticle& partN = catN.particles[tt]; - DynamoParticle& partS = catS.particles[tt]; - - const int t = partC.tomo; - - if (!tomoList.isKnown(t)) - { - REPORT_ERROR_STR("Bad tomogram: " << t << "."); - } - - std::string stackFn = tomoList.getTiltSeriesFilename(t); - std::string projFn = tomoList.getProjectionsFilename(t); - - BufferedImage stack; - stack.read(stackFn); - - const int w = stack.xdim; - const int h = stack.ydim; - const int fc = stack.zdim; - - int w0, h0, d0; - std::vector projTomo = ProjectionIO::read(projFn, w0, h0, d0); - - QuadricDiscFit mdf( - stack, projTomo, - partN.getPosition(), - partS.getPosition(), - binning, diameter, thickness, num_threads); - - std::vector x0 = mdf.getInitial(); - - std::vector x1 = NelderMead::optimize(x0, mdf, 1e-5, 1e-6, 10000); - - std::cout << "final: " << mdf.f(x1, 0) << std::endl; - - BufferedImage phaselines = mdf.writePhaselines(x1, w, h, projTomo); - - BufferedImage stackAvg(w,h,fc); - - for (int f = 0; f < fc; f++) - { - std::vector avg = PhaseLineAverage::averageNN( - stack.getSliceRef(f), phaselines.getSliceRef(f), w); - - BufferedImage expa = PhaseLineAverage::expandLIN( - stack.getSliceRef(f), phaselines.getSliceRef(f), avg); - - stackAvg.copySliceFrom(f, expa); - } - - stack -= stackAvg; - - if (diag) - { - std::string tag = diagTag + partC.getFormattedTag(); - - mdf.localTomo.write(tag + "_3D_tomo.mrc"); - - BufferedImage vis0 = mdf.visualize(x0); - BufferedImage vis1 = mdf.visualize(x1); - - vis0.write(tag + "_3D_initial.mrc"); - vis1.write(tag + "_3D_final.mrc"); - - phaselines.write(tag + "_phase_lines.mrc"); - - BufferedImage vis2D = mdf.visualize2D(x1, stack, projTomo); - vis2D.write(tag + "_fit.mrc"); - - stackAvg.write(tag + "_average.mrc"); - } - - stack.write(outTag + "/" + partC.getFormattedTag() + ".mrc"); - } - - return 0; -} - diff --git a/src/jaz/scripts/membrane_segment.cpp b/src/jaz/scripts/membrane_segment.cpp deleted file mode 100644 index 3cdb5e84d..000000000 --- a/src/jaz/scripts/membrane_segment.cpp +++ /dev/null @@ -1,274 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string tomoTag = "214"; - - std::string pointsFn = "coords_"+tomoTag+"_bin1.txt";//"coords_145_bin8.txt"; - std::vector> coords = ZIO::readFixedDoublesTable(pointsFn, 6); - - const double binning = 16.0; - const int pc = coords.size(); - - const bool debug = true; - const double rho = 1.0; // 5 - const double sigma0 = 0.0; // 0 - const int num_threads = 6; - - const double sigma_diff = 1; - const double lambda_edge = 0.5; - const double thresh_edge = 0.1; - const double sigma_plate = 0.0002; - - const int iters_across = 30; - const int iters_along = 500; - - - { - - BufferedImage membrane; - membrane.read("debug/membrane.mrc"); - - BufferedImage softmaxDist = MembraneSegmentation::softmaxMembraneDist(membrane, 5); - softmaxDist.write("debug/softmaxDist.mrc"); - - BufferedImage centers; - centers.read("debug/maxCent_FS.mrc"); - - Tapering::taper(centers, 30, 6, false); - - centers /= softmaxDist; - - centers.write("debug/maxCent_by_softmaxDist.mrc"); - - return 0; - } - - - - - - - - - BufferedImage tomo; - tomo.read("bin16/R1_"+tomoTag+".mrc"); - - Tapering::taper(tomo, 20, num_threads, true); - - TomoList tomoList("local_tomolist.txt"); - std::string projFn = tomoList.getProjectionsFilename(145); - - - int w0, h0, d0; - std::vector projTomo = ProjectionIO::read(projFn, w0, h0, d0); - - - std::vector south(pc), north(pc); - std::vector thickness(pc); - - for (int p = 0; p < pc ; p++) - { - south[p] = d3Vector(coords[p][0], coords[p][1], coords[p][2]) / binning; - north[p] = d3Vector(coords[p][3], coords[p][4], coords[p][5]) / binning; - thickness[p] = (north[p] - south[p]).length(); - } - - - const int w = tomo.xdim; - const int h = tomo.ydim; - const int d = tomo.zdim; - - BufferedImage data(w,h,d), regional(w,h,d), weight(w,h,d); - BufferedImage regional_memb(w,h,d), weight_memb(w,h,d); - data.fill(0.f); - weight.fill(0.f); - regional.fill(0.f); - weight_memb.fill(0.f); - regional_memb.fill(0.f); - - for (int p = 0; p < pc ; p++) - { - d3Vector nd = north[p]; - - const int r = 3; - - for (int dx = -r; dx <= r; dx++) - for (int dy = -r; dy <= r; dy++) - for (int dz = -r; dz <= r; dz++) - { - regional_memb( - (int)(nd.x + 0.5) + dx, - (int)(nd.y + 0.5) + dy, - (int)(nd.z + 0.5) + dz) = 1.f; - - weight_memb( - (int)(nd.x + 0.5) + dx, - (int)(nd.y + 0.5) + dy, - (int)(nd.z + 0.5) + dz) = 1.f; - } - } - - for (int z = 0; z < d; z++) - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) - { - const d3Vector r(x,y,z); - - for (int p = 0; p < pc ; p++) - { - const d3Vector n = north[p]; - const d3Vector s = south[p]; - const d3Vector t = 2.0 * n - s; - - const double dp = 0.9 * thickness[p]; - - const double ds = (s - r).length(); - const double dt = (t - r).length(); - - const double ra = (r - n).dot(n - s)/dp; - - if (dt < dp || ds < dp) - { - weight(x,y,z) += 1.f; - data(x,y,z) -= ra; - - const double thr = 1; - - if (ra > thr) - { - regional(x,y,z) = 1.f; - } - else if (ra < -thr) - { - regional(x,y,z) = -1.f; - } - } - - double bounary_conf = 0.2; - double boundary = Tapering::getTaperWeight3D(x,y,z, w,h,d, 5); - - regional(x,y,z) += bounary_conf * (1.0 - boundary); - weight(x,y,z) += bounary_conf * (1.0 - boundary); - - double conf_reg = 0.001; - double reg_thresh = -4.0; - - regional(x,y,z) += conf_reg * (tomo(x,y,z) - reg_thresh); - weight(x,y,z) += conf_reg; - } - - - } - - if (debug) - { - weight.write("debug/weight.mrc"); - regional.write("debug/regional.mrc"); - weight_memb.write("debug/weight_memb.mrc"); - regional_memb.write("debug/regional_memb.mrc"); - data.write("debug/data.mrc"); - } - - BufferedImage> J = StructureTensor::compute3D(tomo, rho, sigma0, 20.0); - J = StructureTensor::forwardAverage(J); - - /*std::vector> evals0 = StructureTensor::split( - StructureTensor::computeEigenvalues3D(J)); - - evals0[0].write("debug/Jlin_eval0.mrc"); - (evals0[0] - evals0[1]).write("debug/Jlin_eval0by1.mrc"); - - Image> J_nl = StructureTensor::computeNonLinear( - tomo, rho, sigma0, 20.0, - 20, 20, true, sigma_diff, 0.05f, num_threads); - - - std::vector> evals1 = StructureTensor::split( - StructureTensor::computeEigenvalues3D(J_nl)); - - evals1[0].write("debug/Jnonlin_eval0.mrc"); - (evals1[0] - evals1[1]).write("debug/Jnonlin_eval0by1.mrc");*/ - - std::cout << "finding membranes..." << std::endl; - - BufferedImage membrane = MembraneSegmentation::determineMembraniness( - tomo, J, sigma_diff, lambda_edge, thresh_edge, - num_threads, iters_across, iters_along); - - membrane.write("debug/membrane.mrc"); - - - BufferedImage softmaxDist = MembraneSegmentation::softmaxMembraneDist(membrane, 10); - softmaxDist.write("debug/softmaxDist.mrc"); - - - BufferedImage ptSymmsMembrane = Cells::findPointSymmetries(membrane, 20, tomo.xdim/24); - ptSymmsMembrane.write("debug/membrane_ptSymms.mrc"); - - BufferedImage> surfKernel = Skeletonization::getKernel( - J, Skeletonization::Surface, 0.1f); - BufferedImage surf = Skeletonization::apply(membrane, surfKernel, num_threads, 1); - surf.write("debug/membrane_thinned.mrc"); - - BufferedImage ptSymmsMembraneThin = Cells::findPointSymmetries(surf, 20, tomo.xdim/24); - ptSymmsMembraneThin.write("debug/thin_membrane_ptSymms.mrc"); - - - //std::vector surfPts = Skeletonization::discretize(surf, 1.f); - - //std::cout << surfPts.size() << " surface points found." << std::endl; - - BufferedImage maxCent(w,h,d), maxRad(w,h,d); - - Cells::findCenters(surf, 10, 100.f, 1.f, maxCent, maxRad, num_threads); - - - maxCent.write("debug/maxCent_FS.mrc"); - maxRad.write("debug/maxRad_FS.mrc"); - - //Image ptSymms = Cells::findPointSymmetries(tomo); - - - - //NewVtkHelper::writeR3(eig0, "debug/eigenvector0.vtk"); - - /*Image diffused = Diffusion::diffuse(tomo, D, 0.05f, 500, num_threads); - diffused.write("debug/diffused.mrc"); - - Image diffusedNoise = Diffusion::diffuse(noise, D, 0.05f, 500, num_threads); - diffusedNoise.write("debug/diffused_noise.mrc");*/ - - /*Image segTV = Segmentation::anisotropicTV(regional, D, 100, 0.1f, 0.1f); - segTV.write("debug/seg-TV_100.mrc");*/ - -} - diff --git a/src/jaz/scripts/plot_2d_classes.cpp b/src/jaz/scripts/plot_2d_classes.cpp deleted file mode 100644 index b12e5a1a6..000000000 --- a/src/jaz/scripts/plot_2d_classes.cpp +++ /dev/null @@ -1,203 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string particlesFn, class_averages_filename, classes_filename, micrograph_dir, outDir; - int num_threads, num_MG, num_best_classes, pad; - bool flip_contrast, diag; - - - IOParser parser; - - try - { - IOParser parser; - - parser.setCommandLine(argc, argv); - - int general_section = parser.addSection("General options"); - - particlesFn = parser.getOption("--i", "Input STAR file output by align_2d_classes"); - class_averages_filename = parser.getOption("--ca", "Class averages stack"); - micrograph_dir = parser.getOption("--mgdir", "Micrographs directory", ""); - classes_filename = parser.getOption("--classes", "File with a list of 2D classes to consider", ""); - num_best_classes = textToInteger(parser.getOption("--bc", "Number of best 2D classes to consider otherwise", "20")); - num_MG = textToInteger(parser.getOption("--mgs", "Number of micrographs to use", "12")); - pad = textToInteger(parser.getOption("--pad", "Image padding (pixels)", "20")); - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - flip_contrast = parser.checkOption("--keep_contrast", "Do not flip the contrast"); - diag = parser.checkOption("--diag", "Write out diagnostic information"); - outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - outDir = ZIO::makeOutputDir(outDir); - - ObservationModel obs_model; - MetaDataTable particles_table; - ObservationModel::loadSafely(particlesFn, obs_model, particles_table); - - BufferedImage class_averages; - class_averages.read(class_averages_filename); - - - const int box_size = class_averages.xdim; - const int midbox = box_size/2; - const double radius = midbox - pad; - const int num_classes = class_averages.zdim; - - std::vector classes_to_consider; - - if (classes_filename != "") - { - classes_to_consider = ZIO::readInts(classes_filename); - } - else - { - const int class_count = ClassHelper::countClasses(particles_table); - - if (class_count < num_best_classes) - { - REPORT_ERROR_STR("Cannot consider " << num_best_classes - << " 2D classes, only " << class_count << " present"); - } - - std::vector particle_count = ClassHelper::getClassSizes(particles_table, class_count); - std::vector order = ClassHelper::sortByAscendingFrequency(particle_count); - - classes_to_consider = std::vector(num_best_classes); - - for (int i = 0; i < num_best_classes; i++) - { - classes_to_consider[i] = order[i]; - } - } - - const int relevant_class_count = classes_to_consider.size(); - - std::vector class_to_subset(num_classes, -1); - - for (int i = 0; i < relevant_class_count; i++) - { - class_to_subset[classes_to_consider[i]] = i; - } - - - const double particle_pixel_size = obs_model.getPixelSize(0); - - - std::vector particles_by_micrograph = StackHelper::splitByMicrographName(particles_table); - const int micrograph_count = std::min(num_MG, (int)particles_by_micrograph.size()); - - - t3Vector mg_size = ImageFileHelper::getSize( - particles_by_micrograph[0].getString(EMDL_MICROGRAPH_NAME, 0)); - - BufferedImage output(mg_size.x, mg_size.y, 2 * micrograph_count); - - const float scale = flip_contrast? -1.f : 1.f; - - - Log::beginProgress("Plotting 2D class averages", micrograph_count); - - for (int m = 0; m < micrograph_count; m++) - { - Log::updateProgress(m); - - if (particles_by_micrograph[m].numberOfObjects() == 0) continue; - - MetaDataTable& particles = particles_by_micrograph[m]; - - std::string micrograph_filename = particles.getString(EMDL_MICROGRAPH_NAME, 0); - - BufferedImage micrograph; - micrograph.read(micrograph_filename); - - const float average_value = Normalization::computeMean(micrograph); - - output.getSliceRef(2*m).copyFrom(micrograph); - - const int w = micrograph.xdim; - const int h = micrograph.ydim; - - const double micrograph_pixel_size = ImageFileHelper::getSamplingRate(micrograph_filename); - const double particle_scale = particle_pixel_size / micrograph_pixel_size; - - const int pc = particles.numberOfObjects(); - - for (int p = 0; p < pc; p++) - { - const int global_class_id = particles.getIntMinusOne(EMDL_PARTICLE_CLASS, p); - const int selected_class_id = class_to_subset[global_class_id]; - - if (selected_class_id >= 0) - { - const double dx_A = particles.getDouble(EMDL_ORIENT_ORIGIN_X_ANGSTROM, p); - const double dy_A = particles.getDouble(EMDL_ORIENT_ORIGIN_Y_ANGSTROM, p); - const double phi = DEG2RAD(particles.getDouble(EMDL_ORIENT_PSI, p)); - - const double xc = particles.getDouble(EMDL_IMAGE_COORD_X, p) - dx_A / micrograph_pixel_size; - const double yc = particles.getDouble(EMDL_IMAGE_COORD_Y, p) - dy_A / micrograph_pixel_size; - - const int x0 = std::max(std::ceil(xc - particle_scale * box_size), 0.0); - const int y0 = std::max(std::ceil(yc - particle_scale * box_size), 0.0); - const int x1 = std::min(std::ceil(xc + particle_scale * box_size), (double) w); - const int y1 = std::min(std::ceil(yc + particle_scale * box_size), (double) h); - - for (int y = y0; y < y1; y++) - for (int x = x0; x < x1; x++) - { - const double xm = x - xc; - const double ym = y - yc; - - const double xp = (cos(phi) * xm - sin(phi) * ym) / particle_scale; - const double yp = (sin(phi) * xm + cos(phi) * ym) / particle_scale; - - if (xp * xp + yp * yp < radius * radius) - { - micrograph(x,y) = average_value + scale * Interpolation::linearXY_clip( - class_averages.getSliceRef(global_class_id), - midbox + xp, - midbox + yp); - } - } - } - } - - output.getSliceRef(2*m+1).copyFrom(micrograph); - } - - Log::endProgress(); - - output.write(outDir+"class_average_plots.mrc"); - - return 0; -} diff --git a/src/jaz/scripts/plot_DC_analysis.cpp b/src/jaz/scripts/plot_DC_analysis.cpp deleted file mode 100644 index 465cd8c74..000000000 --- a/src/jaz/scripts/plot_DC_analysis.cpp +++ /dev/null @@ -1,413 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - -#define LINE_BUFFER_LEN 1024 - -bool isAtomInteresting( - std::string atom_name, - bool main_chain_only, - const std::set& desired_elements) -{ - const std::string element = atom_name.substr(0,1); - const std::string position_code = atom_name.substr(1); - - if (main_chain_only - && element != "S" - && atom_name != "CA" - && position_code.length() > 0) - { - return false; - } - - if (desired_elements.size() != 0 && desired_elements.find(element) == desired_elements.end()) - { - return false; - } - - return true; -} - -int main(int argc, char *argv[]) -{ - std::string fn_data = "processed_SNR1_sig1_res2_norot/amp_over_phase_sharp_all.dat"; - std::string fn_legend = "processed_SNR1_sig1_res2_norot/amp_over_phase_sharp_all_legend.txt"; - std::string fn_out = "DC_all_CNOS_rot5.eps"; - - const bool main_chain_only = false; - const bool rotate = true; - const double angle = DEG2RAD(-5); - - std::set desired_elements; - desired_elements.insert("C"); - desired_elements.insert("O"); - desired_elements.insert("N"); - desired_elements.insert("S"); - - std::ifstream ifs_data(fn_data); - std::ifstream ifs_legend(fn_legend); - - const int line_buffer_length = 1024; - char* data_line = new char[line_buffer_length]; - - - std::map> coordinates, averages, inner_ellipses, outer_ellipses; - std::vector atom_names; - - while (ifs_legend) - { - std::string atom_name, atom_count_string; - ifs_legend >> atom_name; - ifs_legend >> atom_count_string; - - atom_names.push_back(atom_name); - - for (int figure = 0; figure < 4; figure++) - { - while (true) - { - ifs_data.getline(data_line, line_buffer_length); - - std::string data_string(data_line); - - if (data_string.length() == 0) - { - break; - } - else - { - std::stringstream sts(data_string); - - d2Vector c; - sts >> c.x; - sts >> c.y; - - c *= 1e8; - - if (rotate) - { - const d2Matrix A - ( cos(angle), -sin(angle), - sin(angle), cos(angle) ); - - c = A * c; - } - - switch (figure) - { - case 0: - coordinates[atom_name].push_back(c); - break; - case 1: - averages[atom_name].push_back(c); - break; - case 2: - inner_ellipses[atom_name].push_back(c); - break; - case 3: - outer_ellipses[atom_name].push_back(c); - break; - } - } - } - } - } - - std::map element_colours; - element_colours["C"] = dRGB(0.2,0.2,0.2); - element_colours["N"] = dRGB(0.0,0.3,1.0); - element_colours["O"] = dRGB(1.0,0.2,0.0); - element_colours["S"] = dRGB(0.8,0.8,0.0); - - CPlot2D plot2D(""); - - //plot2D.SetTitle("amplitude over phase"); - plot2D.SetDrawLegend(true); - - const int anc = atom_names.size(); - - std::map element_means; - std::map element_atom_count; - - for (std::set::iterator it = desired_elements.begin(); - it != desired_elements.end(); it++) - { - std::string element = *it; - element_means[element] = d2Vector(0,0); - element_atom_count[element] = 0; - } - - for (int an = 0; an < anc; an++) - { - const std::string atom_name = atom_names[an]; - - if (atom_name == "") continue; - - const std::string element = atom_name.substr(0,1); - - if (!isAtomInteresting(atom_name, main_chain_only, desired_elements)) - { - continue; - } - - const int ac = coordinates[atom_name].size(); - - for (int a = 0; a < ac; a++) - { - element_means[element] += coordinates[atom_name][a]; - } - - element_atom_count[element] += ac; - } - - std::map> element_covariance_matrices; - - for (std::set::iterator it = desired_elements.begin(); - it != desired_elements.end(); it++) - { - std::string element = *it; - element_means[element] /= element_atom_count[element]; - element_covariance_matrices[element] = Tensor2x2(0,0,0); - - std::cout << element << ": mean = " << element_means[element] << std::endl; - } - - for (int an = 0; an < anc; an++) - { - const std::string atom_name = atom_names[an]; - - if (atom_name == "") continue; - - const std::string element = atom_name.substr(0,1); - - if (!isAtomInteresting(atom_name, main_chain_only, desired_elements)) - { - continue; - } - - const int ac = coordinates[atom_name].size(); - - for (int a = 0; a < ac; a++) - { - const d2Vector d = coordinates[atom_name][a] - element_means[element]; - - element_covariance_matrices[element].xx += d.x * d.x; - element_covariance_matrices[element].xy += d.x * d.y; - element_covariance_matrices[element].yy += d.y * d.y; - } - } - - for (std::set::iterator it = desired_elements.begin(); - it != desired_elements.end(); it++) - { - std::string element = *it; - - element_covariance_matrices[element] /= element_atom_count[element]; - - std::cout << element << ": S = " << element_covariance_matrices[element] << std::endl; - - const dRGB colour = element_colours[element]; - - CDataSet ellipse_points; - ellipse_points.SetDrawMarker(false); - ellipse_points.SetDatasetColor(colour.r, colour.g, colour.b); - ellipse_points.SetDrawLine(true); - ellipse_points.SetLineWidth(0.5); - - const d2Vector mu = element_means[element]; - - const int ellipse_samples = 100; - - Tensor2x2 C = element_covariance_matrices[element]; - d2Vector evals, eig0, eig1; - C.diagonalize(evals, eig0, eig1); - - eig0 *= sqrt(evals[0]); - eig1 *= sqrt(evals[1]); - - std::cout << " e0 = " << eig0 << std::endl; - std::cout << " e1 = " << eig1 << std::endl; - - for (int i = 0; i < ellipse_samples+1; i++) - { - const double phi = 2.0 * PI * i / (double) ellipse_samples; - const double sp = sin(phi); - const double cp = cos(phi); - - const d2Vector c = mu + 2.0 * (cp * eig0 + sp * eig1); - - ellipse_points.AddDataPoint(CDataPoint(c.x, c.y)); - } - - plot2D.AddDataSet(ellipse_points); - - - CDataSet average_point; - average_point.SetDrawMarker(true); - average_point.SetMarkerSize(16); - average_point.SetDatasetColor(colour.r, colour.g, colour.b); - average_point.SetDrawLine(false); - average_point.SetDrawMarkerFilled(true); - - average_point.AddDataPoint(CDataPoint(mu.x, mu.y)); - average_point.SetDatasetTitle(element); - - plot2D.AddDataSet(average_point); - - - CDataSet line_to_origin_points; - line_to_origin_points.SetDrawMarker(false); - line_to_origin_points.SetDatasetColor(colour.r, colour.g, colour.b); - line_to_origin_points.SetDrawLine(true); - - line_to_origin_points.AddDataPoint(CDataPoint(mu.x, mu.y)); - line_to_origin_points.AddDataPoint(CDataPoint(0,0)); - - plot2D.AddDataSet(line_to_origin_points); - } - - std::map plot_symbol; - - plot_symbol["A"] = "o"; - plot_symbol["B"] = "x"; - plot_symbol["G"] = "+"; - plot_symbol["D"] = "diamond"; - plot_symbol["E"] = "square"; - plot_symbol["Z"] = "triangle"; - plot_symbol["H"] = "triangle"; - - for (int an = 0; an < anc; an++) - { - const std::string atom_name = atom_names[an]; - - if (atom_name == "") continue; - - const std::string element = atom_name.substr(0,1); - - if (!isAtomInteresting(atom_name, main_chain_only, desired_elements)) - { - continue; - } - - std::cout << atom_name << ": " << element << std::endl; - - const dRGB colour = element_colours[element]; - const bool is_hollow = main_chain_only && (atom_name == "CA" || atom_name == "SD"); - - const std::vector& coords = coordinates[atom_name]; - const std::vector& average = averages[atom_name]; - const std::vector& inner_ellipse = inner_ellipses[atom_name]; - const std::vector& outer_ellipse = outer_ellipses[atom_name]; - - const int ac = coords.size(); - const int ec = inner_ellipse.size(); - - CDataSet cloud_points; - cloud_points.SetDrawMarker(true); - cloud_points.SetMarkerSize(1); - cloud_points.SetDatasetColor(colour.r, colour.g, colour.b); - cloud_points.SetDrawLine(false); - cloud_points.SetDrawMarkerFilled(!is_hollow); - - for (int a = 0; a < ac; a++) - { - const d2Vector c = coords[a]; - cloud_points.AddDataPoint(CDataPoint(c.x, c.y)); - } - - - CDataSet average_point; - average_point.SetDrawMarker(true); - average_point.SetMarkerSize(8); - - if (atom_name.length() > 1) - { - average_point.SetMarkerSymbol(plot_symbol[atom_name.substr(1,1)]); - } - - average_point.SetDatasetColor(colour.r, colour.g, colour.b); - average_point.SetDrawLine(false); - - if (main_chain_only) - { - average_point.SetDatasetTitle(atom_name); - } - - average_point.SetDrawMarkerFilled(!is_hollow); - - { - const d2Vector c = average[0]; - average_point.AddDataPoint(CDataPoint(c.x, c.y)); - } - - - CDataSet line_to_origin_points; - line_to_origin_points.SetDrawMarker(false); - line_to_origin_points.SetDatasetColor(colour.r, colour.g, colour.b); - line_to_origin_points.SetDrawLine(true); - - if (main_chain_only) - { - const d2Vector c = average[0]; - line_to_origin_points.AddDataPoint(CDataPoint(c.x, c.y)); - line_to_origin_points.AddDataPoint(CDataPoint(0,0)); - } - - CDataSet inner_ellipse_points; - inner_ellipse_points.SetDrawMarker(false); - inner_ellipse_points.SetDatasetColor(colour.r, colour.g, colour.b); - inner_ellipse_points.SetDrawLine(true); - inner_ellipse_points.SetLineWidth(0.5); - - CDataSet outer_ellipse_points; - outer_ellipse_points.SetDrawMarker(false); - outer_ellipse_points.SetDatasetColor(colour.r, colour.g, colour.b); - outer_ellipse_points.SetDrawLine(true); - outer_ellipse_points.SetLineWidth(0.5); - - - for (int e = 0; e < ec; e++) - { - const d2Vector ci = inner_ellipse[e]; - const d2Vector co = outer_ellipse[e]; - - inner_ellipse_points.AddDataPoint(CDataPoint(ci.x, ci.y)); - outer_ellipse_points.AddDataPoint(CDataPoint(co.x, co.y)); - } - - if (main_chain_only) - { - //plot2D.AddDataSet(outer_ellipse_points); - plot2D.AddDataSet(line_to_origin_points); - } - - plot2D.AddDataSet(cloud_points); - plot2D.AddDataSet(average_point); - } - - - if (rotate) - { - //plot2D.SetXAxisTitle("amplitude + "+ZIO::itoa(AC)+" * phase"); - //plot2D.SetYAxisTitle("amplitude - "+ZIO::itoa(AC)+" * phase"); - } - else - { - plot2D.SetXAxisTitle("phase"); - plot2D.SetYAxisTitle("amplitude"); - } - - plot2D.OutputPostScriptPlot(fn_out); - - return 0; -} diff --git a/src/jaz/scripts/plot_dose_weight.cpp b/src/jaz/scripts/plot_dose_weight.cpp deleted file mode 100644 index 970267d41..000000000 --- a/src/jaz/scripts/plot_dose_weight.cpp +++ /dev/null @@ -1,95 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - - - -int main(int argc, char *argv[]) -{ - IOParser parser; - parser.setCommandLine(argc, argv); - - std::string tomoSetFn, optFn, outDir; - int boxSize; - bool normalise; - - try - { - int gen_section = parser.addSection("General options"); - - tomoSetFn = parser.getOption("--t", "Tomogram set", "tomograms.star"); - optFn = parser.getOption("--ctf", "Consider a CTF using parameters from the supplied file"); - boxSize = textToInteger(parser.getOption("--b", "Box size")); - normalise = parser.checkOption("--nrm", "Scale each column to make its sum 1"); - outDir = parser.getOption("--o", "Output directory"); - - if (parser.checkForErrors()) - { - parser.writeUsage(std::cout); - std::exit(-1); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - TomogramSet tomogramSet(tomoSetFn); - const int tc = tomogramSet.size(); - - if (outDir[outDir.length()-1] != '/') - { - outDir = outDir + "/"; - } - - int res = system(("mkdir -p "+outDir).c_str()); - - for (int t = 0; t < tc; t++) - { - Tomogram tomogram = tomogramSet.loadTomogram(t, false); - const int fc = tomogram.frameCount; - const int s = boxSize; - const int sh = s/2 + 1; - - BufferedImage doseWeights = tomogram.computeDoseWeight(s, 1.0); - - BufferedImage out(sh, fc); - - for (int f = 0; f < fc; f++) - for (int x = 0; x < sh; x++) - { - out(x,f) = doseWeights(x,0,f); - } - - if (normalise) - { - for (int x = 0; x < sh; x++) - { - double sum(0.0); - - for (int f = 0; f < fc; f++) - { - sum += out(x,f); - } - - if (sum != 0.0) - { - for (int f = 0; f < fc; f++) - { - out(x,f) /= sum; - } - } - } - } - - out.write(outDir + ZIO::itoa(t) + ".mrc"); - } - - return 0; -} diff --git a/src/jaz/scripts/plot_particles.cpp b/src/jaz/scripts/plot_particles.cpp deleted file mode 100644 index 9f16b49a0..000000000 --- a/src/jaz/scripts/plot_particles.cpp +++ /dev/null @@ -1,171 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - - -void addPoint(const d3Vector& pos, const d3Matrix& A, double rad, double out_bin, Mesh& mesh) -{ - const d3Vector n(A(0,2), A(1,2), A(2,2)); - - MeshBuilder::addCone(pos / out_bin, (pos + 2 * rad * n) / out_bin, rad, 12, mesh); -} - -int main(int argc, char *argv[]) -{ - std::string inFn, refFn, tomoSetFn, motFn, outDir; - int t0, t1, f; - double bin, rad, relScale; - bool allFrames; - - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - inFn = parser.getOption("--i", "Input particle set"); - refFn = parser.getOption("--ref", "Other particles file to serve as reference to zoom against", ""); - tomoSetFn = parser.getOption("--t", "Tomogram set", "tomograms.star"); - - t0 = textToInteger(parser.getOption("--t0", "First tomogram", "0")); - t1 = textToInteger(parser.getOption("--t1", "Last tomogram", "-1")); - - motFn = parser.getOption("--mot", "Particle trajectories", ""); - - f = textToInteger(parser.getOption("--f", "Frame", "0")); - allFrames = parser.checkOption("--all_frames", "Output meshes for all frames"); - - bin = textToDouble(parser.getOption("--bin", "Divide coordinates by this", "1.0")); - rad = textToDouble(parser.getOption("--rad", "Size of output octahedron", "1.0")); - relScale = textToDouble(parser.getOption("--rel_scale", "Scale the distance from reference pt. by this", "8.0")); - - outDir = parser.getOption("--o", "Output directory"); - - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - if ((f != 0 || allFrames) && (motFn == "")) - { - std::cerr << "A motion file (--mot) is required to select a frame (--f) or output all frames (--all_frames)." << std::endl; - return -1; - } - - if (f < 0) - { - std::cerr << "The frame index (--f) must not be negative." << std::endl; - return -1; - } - - - TomogramSet tomogramSet(tomoSetFn); - - ParticleSet dataSet(inFn, motFn); - std::vector> particles = dataSet.splitByTomogram(tomogramSet); - - - const int tc = particles.size(); - - if (t1 < 0) t1 = tc - 1; - - outDir = ZIO::makeOutputDir(outDir); - - - for (int t = t0; t <= t1; t++) - { - const int pc = particles[t].size(); - - if (pc == 0) continue; - - Tomogram tomogram = tomogramSet.loadTomogram(t, false); - - std::vector frameSeq = IndexSort::sortIndices(tomogram.cumulativeDose); - - const int fc = tomogram.frameCount; - dataSet.checkTrajectoryLengths(particles[t][0], pc, fc, "backproject"); - - - Mesh mesh; - std::vector meshes(fc); - - for (int p = 0; p < pc; p++) - { - const ParticleIndex part_id = particles[t][p]; - - const d3Matrix A = dataSet.getMatrix3x3(part_id); - - - if (f == 0 && !allFrames) - { - const d3Vector pos = dataSet.getPosition(part_id); - - addPoint(pos, A, rad, bin, mesh); - } - else - { - const std::vector traj = dataSet.getTrajectoryInPixels( - part_id, 0, tomogram.optics.pixelSize); - - if (allFrames) - { - const int fc = traj.size(); - - for (int f = 0; f < fc; f++) - { - const d3Vector pos = traj[frameSeq[f]]; - - addPoint(pos, A, rad, bin, meshes[f]); - } - } - else - { - if (f >= traj.size()) - { - if (motFn != "") - { - REPORT_ERROR_STR( - "Bad frame index: only " << traj.size() << " frames available for particle " - << part_id.value << " in " << motFn); - } - else - { - // has been handled - } - } - - const d3Vector pos = traj[frameSeq[f]]; - - addPoint(pos, A, rad, bin, mesh); - } - } - } - - if (allFrames) - { - for (int f = 0; f < fc; f++) - { - meshes[f].writePly(outDir + ZIO::itoa(t) + "_frame_" + ZIO::itoa(f) + ".ply"); - } - } - else - { - mesh.writePly(outDir + ZIO::itoa(t) + ".ply"); - } - } - - return 0; -} diff --git a/src/jaz/scripts/plot_pdb.cpp b/src/jaz/scripts/plot_pdb.cpp deleted file mode 100644 index bff603bc8..000000000 --- a/src/jaz/scripts/plot_pdb.cpp +++ /dev/null @@ -1,81 +0,0 @@ -#include -#include -#include -#include - - -using namespace gravis; - - -void addPoint(d3Vector pos, d3Vector ref, double scale, double rad, double out_bin, Mesh& mesh) -{ - const d3Vector pos2 = ref + scale * (pos - ref); - MeshBuilder::addOctahedron(pos2 / out_bin, rad, mesh); -} - -int main(int argc, char *argv[]) -{ - std::string inFn, outDir; - double psModel, psOut; - int boxModel, boxOut; - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - inFn = parser.getOption("--i", "Input PDB file"); - outDir = parser.getOption("--o", "Output directory"); - boxModel = textToInteger(parser.getOption("--box_model", "Box size of the map corresponding to the PDB file")); - psModel = textToDouble(parser.getOption("--angpix_model", "Pixel size of the map corresponding to the PDB file")); - boxOut = textToInteger(parser.getOption("--box_out", "Box size of the map to be compared")); - psOut = textToDouble(parser.getOption("--angpix_out", "Pixel size of the map to be compared")); - - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - outDir = ZIO::makeOutputDir(outDir); - - const double coordOffset = (boxOut/2)*psOut - (boxModel/2)*psModel; - - Assembly assembly; - assembly.readPDB(inFn); - - std::map> atoms = PdbHelper::groupAtomsByElement(assembly); - - std::cout << atoms.size() << " elements found" << std::endl; - std::cout << " " << assembly.molecules.size() << " molecules" << std::endl; - std::cout << " " << assembly.looseAtoms.size() << " lose atoms" << std::endl; - - for (std::map>::iterator it = atoms.begin(); - it != atoms.end(); it++) - { - Mesh mesh; - - const std::string element = it->first; - const std::vector& positions = it->second; - - std::cout << element << " (" << positions.size() << ")" << std::endl; - - const int pc = positions.size(); - - for (int p = 0; p < pc; p++) - { - const d3Vector pos = positions[p] + coordOffset * d3Vector(1,1,1); - MeshBuilder::addOctahedron(pos, 0.5, mesh); - } - - mesh.writePly(outDir+element+".ply"); - } - - return 0; -} diff --git a/src/jaz/scripts/plot_tomo_defoci.cpp b/src/jaz/scripts/plot_tomo_defoci.cpp deleted file mode 100644 index 02b9013be..000000000 --- a/src/jaz/scripts/plot_tomo_defoci.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include -#include -#include -#include - - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string inFn, outDir; - - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - inFn = parser.getOption("--t", "Input tomogram set"); - outDir = parser.getOption("--o", "Output directory"); - - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - TomogramSet tomogramSet(inFn); - - outDir = ZIO::makeOutputDir(outDir); - - std::ofstream file(outDir + "defoci.dat"); - - const int tc = tomogramSet.size(); - - for (int dim = 0; dim < 2; dim++) - { - double x_coord = 0; - - for (int t = 0; t < tc; t++) - { - Tomogram tomogram = tomogramSet.loadTomogram(t, false); - - const int fc = tomogram.frameCount; - - for (int f = 0; f < fc; f++) - { - if (dim == 0) - { - file << x_coord << ' ' << tomogram.centralCTFs[f].DeltafU << '\n'; - } - else - { - file << x_coord << ' ' << tomogram.centralCTFs[f].DeltafV << '\n'; - } - - x_coord += 1.0 / (double) (fc + 1); - } - - x_coord += 1.0 / (double) (fc + 1); - } - - file << '\n'; - } - - return 0; -} - diff --git a/src/jaz/scripts/plot_topaz_points.cpp b/src/jaz/scripts/plot_topaz_points.cpp deleted file mode 100644 index 9d167ca35..000000000 --- a/src/jaz/scripts/plot_topaz_points.cpp +++ /dev/null @@ -1,167 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - std::string points_file_name, image_directory, outDir; - double binning; - int num_threads; - - - IOParser parser; - - try - { - IOParser parser; - - parser.setCommandLine(argc, argv); - - int general_section = parser.addSection("General options"); - - points_file_name = parser.getOption("--i", "Topaz membrane detections"); - image_directory = parser.getOption("--id", "Directory containing the micrographs"); - binning = textToDouble(parser.getOption("--bin", "Binning level", "32")); - - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - - outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - outDir = ZIO::makeOutputDir(outDir); - - if (image_directory.length() > 0) - { - if (image_directory[image_directory.length()-1] != '/') - { - image_directory = image_directory + "/"; - } - } - - - TopazParticleMap particles_by_image = TopazHelper::read(points_file_name, -1000); - - const std::string first_image_name = particles_by_image.begin()->first; - - - BufferedImage micrograph; - micrograph.read(image_directory + first_image_name + ".mrc"); - micrograph = Resampling::FourierCrop_fullStack(micrograph, binning, 1, true); - - /*const i2Vector binned_image_size( - full_image_size.x / binning, - full_image_size.y / binning);*/ - - const i2Vector binned_image_size(micrograph.xdim, micrograph.ydim); - - const int micrograph_count = particles_by_image.size(); - - std::vector all_image_names(micrograph_count); - std::vector> all_particles(micrograph_count); - - { - int index = 0; - - for (TopazParticleMap::iterator it = particles_by_image.begin(); - it != particles_by_image.end(); it++) - { - all_image_names[index] = it->first; - all_particles[index] = it->second; - - index++; - } - } - - { - std::ofstream names_list(outDir+"micrographs.txt"); - - for (int m = 0; m < micrograph_count; m++) - { - names_list << m << " " << all_image_names[m] << '\n'; - } - } - - - BufferedImage all_particle_images(binned_image_size.x, binned_image_size.y, micrograph_count); - BufferedImage all_micrographs(binned_image_size.x, binned_image_size.y, micrograph_count); - - - int res = system(("mkdir -p "+outDir+"Frames").c_str()); - - - Log::beginProgress("Plotting micrographs and particles", micrograph_count / num_threads); - - #pragma omp parallel for num_threads(num_threads) - for (int m = 0; m < micrograph_count; m++) - { - const int th = omp_get_thread_num(); - - if (th == 0) - { - Log::updateProgress(m); - } - - const std::string image_name = all_image_names[m]; - const std::vector particles = all_particles[m]; - - BufferedImage centre_quality(binned_image_size.x, binned_image_size.y); - centre_quality.fill(0.f); - - BufferedImage blob_radius(binned_image_size.x, binned_image_size.y); - blob_radius.fill(0.f); - - BufferedImage micrograph; - micrograph.read(image_directory + image_name + ".mrc"); - micrograph = Resampling::FourierCrop_fullStack(micrograph, binning, 1, true); - micrograph = Normalization::byNormalDist(micrograph); - - all_micrographs.getSliceRef(m).copyFrom(micrograph); - - - BufferedImage particles_image(binned_image_size.x, binned_image_size.y); - particles_image.fill(0.f); - - - for (int i = 0; i < particles.size(); i++) - { - TopazHelper::Particle p = particles[i]; - i2Vector c = p.coordinates; - - Drawing::drawCross(d2Vector(c.x, c.y) / binning, (float)p.score, 2, particles_image); - } - - all_particle_images.getSliceRef(m).copyFrom(particles_image); - } - - Log::endProgress(); - - all_particle_images.write(outDir + "particles.mrc"); - all_micrographs.write(outDir + "micrographs.mrc"); - - return 0; -} diff --git a/src/jaz/scripts/predict_tomo_view.cpp b/src/jaz/scripts/predict_tomo_view.cpp deleted file mode 100644 index ef633a641..000000000 --- a/src/jaz/scripts/predict_tomo_view.cpp +++ /dev/null @@ -1,178 +0,0 @@ - -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - std::string particleFn, tomoSetFn, outPath; - double minFreqPx, lowPass; - bool oppositeHalf, predictCTF, applyDose, writeObs; - int threads, tomoIndex, particleIndex, boxSize; - - //ReferenceMap reference; - TomoReferenceMap referenceMap; - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - - parser.addSection("General options"); - - particleFn = parser.getOption("--i", "Input particle set"); - tomoSetFn = parser.getOption("--t", "Tomogram set", "tomograms.star"); - tomoIndex = textToInteger(parser.getOption("--ti", "Tomogram index", "0")); - particleIndex = textToInteger(parser.getOption("--pi", "Particle index", "0")); - boxSize = textToInteger(parser.getOption("--b", "Box size")); - - referenceMap.read(parser); - - minFreqPx = textToDouble(parser.getOption("--min_freq", "Min. image frequency [px]", "0")); - - predictCTF = parser.checkOption("--predict_CTF", "Modulate prediction by CTF"); - oppositeHalf = parser.checkOption("--opposite_half", "Make prediction from the opposite subset"); - applyDose = !parser.checkOption("--no_dose", "Do not apply dose weighting"); - writeObs = parser.checkOption("--write_obs", "Write out the observed images as well"); - - lowPass = textToDouble(parser.getOption("--lowpass", "Blur by a Gaussian with this sigma [px]", "-1")); - - threads = textToInteger(parser.getOption("--j", "Number of threads", "1")); - outPath = parser.getOption("--o", "Output path"); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - return RELION_EXIT_FAILURE; - } - - if (outPath[outPath.length()-1] != '/') - { - outPath = outPath + "/"; - } - - std::string command = "mkdir -p " + outPath; - int res = system(command.c_str()); - - - TomogramSet tomogramSet(tomoSetFn); - - ParticleSet dataSet(particleFn); - std::vector> particles = dataSet.splitByTomogram(tomogramSet); - - AberrationsCache aberrationsCache(dataSet.optTable, boxSize, dataSet.getOriginalPixelSize(0)); - - referenceMap.load(boxSize); - - const int s = referenceMap.getBoxSize(); - const int sh = s/2 + 1; - - - { - const int pc = particles[tomoIndex].size(); - - if (pc <= particleIndex) - { - REPORT_ERROR_STR("Only " << pc << " particles found in tomogram " << tomoIndex); - } - - const ParticleIndex part_id(particleIndex); - - Tomogram tomogram = tomogramSet.loadTomogram(tomoIndex, true); - tomogram.validateParticleOptics({part_id}, dataSet); - - BufferedImage doseWeights = tomogram.computeDoseWeight(s, 1.0); - - const int fc = tomogram.frameCount; - - if (writeObs) - { - BufferedImage obsStack(s,s,fc); - BufferedImage sliceRS(s,s); - BufferedImage> sliceFS(sh,s); - - const std::vector traj = dataSet.getTrajectoryInPixels(part_id, fc, tomogram.optics.pixelSize); - - for (int f = 0; f < fc; f++) - { - d4Matrix projCut; - - TomoExtraction::extractFrameAt3D_Fourier( - tomogram.stack, f, s, 1.0, tomogram, traj[f], - sliceFS, projCut, 1, true); - - Centering::shiftInSitu(sliceFS); - FFT::inverseFourierTransform(sliceFS, sliceRS); - - obsStack.getSliceRef(f).copyFrom(sliceRS); - } - - obsStack.write( - outPath + "tomo_" + ZIO::itoa(tomoIndex) + "_part_" + ZIO::itoa(particleIndex) + "_obs.mrc", - tomogram.optics.pixelSize); - } - - BufferedImage predStack(s,s,fc); - - for (int f = 0; f < fc; f++) - { - CTF ctf = tomogram.getCtf(f, dataSet.getPosition(part_id)); - RawImage doseSlice = doseWeights.getSliceRef(f); - - BufferedImage prediction = Prediction::predictModulated( - part_id, dataSet, tomogram.projectionMatrices[f], s, - ctf, tomogram.optics.pixelSize, aberrationsCache, - referenceMap.image_FS, - oppositeHalf? Prediction::OppositeHalf : Prediction::OwnHalf, - predictCTF? Prediction::AmplitudeModulated : Prediction::Unmodulated, - applyDose? &doseSlice : 0, - Prediction::CtfScaled); - - Centering::shiftInSitu(prediction); - - BufferedImage predReal(s,s); - FFT::inverseFourierTransform(prediction, predReal); - - predStack.getSliceRef(f).copyFrom(predReal); - } - - predStack.write( - outPath + "tomo_" + ZIO::itoa(tomoIndex) - + "_part_" + ZIO::itoa(particleIndex) + "_pred.mrc", - tomogram.optics.pixelSize); - } - - return RELION_EXIT_SUCCESS; -} diff --git a/src/jaz/scripts/print_coords.cpp b/src/jaz/scripts/print_coords.cpp deleted file mode 100644 index 3cbdde6b7..000000000 --- a/src/jaz/scripts/print_coords.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - IOParser parser; - - std::string particlesFn, tomoSetFn, outFn; - int particlesToOutput; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - particlesFn = parser.getOption("--i", "Input particle set"); - tomoSetFn = parser.getOption("--t", "Tomogram set", "tomograms.star"); - particlesToOutput = textToInteger(parser.getOption("--n", "Number of particles to output", "10")); - outFn = parser.getOption("--o", "Output filename pattern"); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - TomogramSet tomogramSet(tomoSetFn); - - ParticleSet dataSet(particlesFn, ""); - std::vector> particles = dataSet.splitByTomogram(tomogramSet); - - const int tc = particles.size(); - - std::ofstream output(outFn); - - int tpc = 0; - - for (int t = 0; t < tc; t++) - { - const int pc = particles[t].size(); - - if (pc == 0) continue; - - Tomogram tomogram = tomogramSet.loadTomogram(t, false); - output << "ts_" << t << ": \n"; - - std::vector projTomo = tomogram.projectionMatrices; - const int fc = projTomo.size(); - - for (int p = 0; p < pc; p++) - { - output << "\n\tparticle " << p << ": \n\n"; - - const ParticleIndex part_id = particles[t][p]; - - const d3Vector pos = dataSet.getPosition(part_id); - - const gravis::d4Vector pw(pos.x, pos.y, pos.z, 1.0); - - for (int f = 0; f < fc; f++) - { - const d4Vector q = projTomo[f] * pw; - d2Vector r = gravis::d2Vector(q.x, q.y); - - output << "\t\t" << f << ": \t" - << std::setw(8) << r.x << " \t" - << std::setw(8) << r.y << '\n'; - } - - tpc++; - - if (tpc >= particlesToOutput) return 0; - } - } - - return 0; -} diff --git a/src/jaz/scripts/process_image.cpp b/src/jaz/scripts/process_image.cpp deleted file mode 100644 index fc7fd0b4b..000000000 --- a/src/jaz/scripts/process_image.cpp +++ /dev/null @@ -1,14 +0,0 @@ -#include -#include -#include -#include - -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - return 0; -} diff --git a/src/jaz/scripts/ramp.cpp b/src/jaz/scripts/ramp.cpp deleted file mode 100644 index 49f0b75c9..000000000 --- a/src/jaz/scripts/ramp.cpp +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include -#include -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - if (argc < 3) - { - std::cerr << "usage: ramp \n"; - return 1; - } - - std::string fnIn = argv[1]; - std::string fnOut = argv[2]; - - BufferedImage img; - img.read(fnIn); - - BufferedImage out = ImageFilter::ramp(img); - - out.write(fnOut); - - return 0; -} diff --git a/src/jaz/scripts/rotate_subtomograms.cpp b/src/jaz/scripts/rotate_subtomograms.cpp deleted file mode 100644 index 4ad2f5d1e..000000000 --- a/src/jaz/scripts/rotate_subtomograms.cpp +++ /dev/null @@ -1,74 +0,0 @@ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - IOParser parser; - - std::string particles_filename, output_filename; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - particles_filename = parser.getOption("--i", "Catalogue .tbl or .star file"); - output_filename = parser.getOption("--o", "Output filename pattern"); - - Log::readParams(parser); - - parser.checkForErrors(); - - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - - - - ParticleSet data_set(particles_filename, ""); - ParticleSet data_set_copy = data_set; - - const int pc = data_set.getTotalParticleNumber(); - - for (int p = 0; p < pc; p++) - { - double rot_particle = data_set.partTable.getDouble(EMDL_ORIENT_ROT, p); - double tilt_particle = data_set.partTable.getDouble(EMDL_ORIENT_TILT, p); - double psi_particle = data_set.partTable.getDouble(EMDL_ORIENT_PSI, p); - - data_set_copy.partTable.setValue(EMDL_TOMO_SUBTOMOGRAM_ROT, rot_particle, p); - data_set_copy.partTable.setValue(EMDL_TOMO_SUBTOMOGRAM_TILT, tilt_particle, p); - data_set_copy.partTable.setValue(EMDL_TOMO_SUBTOMOGRAM_PSI, psi_particle, p); - - data_set_copy.partTable.setValue(EMDL_ORIENT_ROT, 0.0, p); - data_set_copy.partTable.setValue(EMDL_ORIENT_TILT, 0.0, p); - data_set_copy.partTable.setValue(EMDL_ORIENT_PSI, 0.0, p); - } - - data_set_copy.write(output_filename); -} diff --git a/src/jaz/scripts/sample_blob_points.cpp b/src/jaz/scripts/sample_blob_points.cpp deleted file mode 100644 index 2b1cf58c3..000000000 --- a/src/jaz/scripts/sample_blob_points.cpp +++ /dev/null @@ -1,361 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string micrographs_list_filename, micrographs_dir, blobs_dir, outPath; - double min_radius, max_radius, min_distance, perimeter_margin; - int num_threads; - bool diag, estimate_radius; - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - micrographs_list_filename = parser.getOption("--ml", "Micrograph lists filename"); - micrographs_dir = parser.getOption("--md", "Micrographs directory"); - blobs_dir = parser.getOption("--bd", "Initial blobs directory"); - min_distance = textToDouble(parser.getOption("--d", "Min. particle distance [bin-1 pixels]", "128")); - perimeter_margin = textToDouble(parser.getOption("--pm", "Distance of perimeter points from the outline [bin-1 pixels]", "64")); - estimate_radius = parser.checkOption("--est_rad", "Estimate the radius of the blob"); - min_radius = textToDouble(parser.getOption("--r0", "Min. radius [bin-1 pixels]", "300")); - max_radius = textToDouble(parser.getOption("--r1", "Max. radius [bin-1 pixels]", "800")); - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - - diag = parser.checkOption("--diag", "Write out diagnostic information"); - - outPath = parser.getOption("--o", "Output filename pattern"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - parser.writeUsage(std::cout); - exit(1); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - - outPath = ZIO::makeOutputDir(outPath); - - const std::string perimeter_dir = "perimeter/Frames/"; - const std::string full_dir = "full/Frames/"; - const std::string outer_half_dir = "outer_half/Frames/"; - - ZIO::makeOutputDir(outPath + perimeter_dir); - ZIO::makeOutputDir(outPath + full_dir); - ZIO::makeOutputDir(outPath + outer_half_dir); - - micrographs_dir = ZIO::ensureEndingSlash(micrographs_dir); - blobs_dir = ZIO::ensureEndingSlash(blobs_dir); - - std::vector all_micrograph_names; - all_micrograph_names.reserve(1000); - - std::ifstream file(micrographs_list_filename); - - if (!file) - { - REPORT_ERROR("Unable to read " + micrographs_list_filename); - } - - std::string line; - - while (std::getline(file, line)) - { - std::stringstream sts; - sts << line; - - std::string name; - sts >> name; - - all_micrograph_names.push_back(name); - } - - const int micrograph_count = all_micrograph_names.size(); - - std::vector failed_micrographs; - - #pragma omp parallel for num_threads(num_threads) - for (int m = 0; m < micrograph_count; m++) - { - const int thread_id = omp_get_thread_num(); - const bool verbose = thread_id == 0; - - if (verbose) - { - Log::beginSection( - "Micrograph "+ZIO::itoa(m+1)+"/" - +ZIO::itoa((int)std::ceil(micrograph_count / (double)num_threads))+" on this thread (out of " - +ZIO::itoa(micrograph_count)+" on all threads)"); - } - - try - { - const std::string micrograph_name = all_micrograph_names[m]; - const std::string micrograph_path = micrographs_dir + micrograph_name + ".mrc"; - const std::string blob_path = blobs_dir + micrograph_name + ".blobs"; - std::vector> blob_shapes = ZIO::readDoublesTable(blob_path); - - BufferedImage micrograph; - micrograph.read(micrograph_path); - - - const double pixel_size = ImageFileHelper::getSamplingRate(micrograph_path); - - const int w = micrograph.xdim; - const int h = micrograph.ydim; - - - BufferedImage weight(micrograph); - weight.fill(1.f); - - const int blob_count = blob_shapes.size(); - - BufferedImage plot(micrograph); - - std::vector blobs(blob_count); - - if (verbose) - { - Log::beginProgress("Processing Blobs", blob_count); - } - - for (int b = 0; b < blob_count; b++) - { - if (verbose) - { - Log::updateProgress(b); - } - - if (blob_shapes[b].size()%2 == 0) - { - for (int i = 0; i < blob_shapes[b].size(); i++) - { - std::cout << i << ": " << blob_shapes[b][i] << "\n"; - } - - REPORT_ERROR("The blobs in "+blob_path+" do not have a radius"); - } - - DelineatedBlob2D blob(blob_shapes[b]); - - if (estimate_radius) - { - std::pair,std::vector> radAvgAndWgh - = blob.radialAverageAndWeight( - micrograph, weight, max_radius); - - std::vector radAvg = radAvgAndWgh.first; - std::vector radWgh = radAvgAndWgh.second; - - const int bin_count = radAvg.size(); - - int best_t = 0; - double best_separation = 0.0; - - int delta_t = 20; - - for (int t = min_radius; t <= max_radius - delta_t && t < bin_count; t++) - { - double avg0 = 0.0; - double wgh0 = 0.0; - - int t0 = t - delta_t; - if (t0 < 0) t0 = 0; - - for (int i = t0; i < t; i++) - { - avg0 += radWgh[i] * radAvg[i]; - wgh0 += radWgh[i]; - } - - double avg1 = 0.0; - double wgh1 = 0.0; - - int t1 = t + delta_t + 1; - if (t0 > bin_count) t1 = bin_count; - - for (int i = t; i < t1; i++) - { - avg1 += radWgh[i] * radAvg[i]; - wgh1 += radWgh[i]; - } - - avg0 /= wgh0; - avg1 /= wgh1; - - const double separation = avg1 - avg0; - - if (separation > best_separation) - { - best_separation = separation; - best_t = t; - } - } - - blob.radius = best_t; - } - - blobs[b] = blob; - } - - if (verbose) - { - Log::endProgress(); - } - - const int EDGE = 0; - const int OUTER_HALF = 1; - const int FULL_BLOB = 2; - - std::vector> picks(3); - std::vector normals; - - - for (int b = 0; b < blob_count; b++) - { - DelineatedBlob2D blob = blobs[b]; - - - const double d = min_distance; - const double margin = d; - const double dd = 0.5 * sqrt(3.0) * d; - const int rc = (h - 2*margin) / dd + 1; - const std::vector cc = {(int)((w - 2*margin) / d), (int)((w - 2*margin - d/2) / d)}; - - for (int r = 0; r < rc; r++) - for (int c = 0; c < cc[r%2]; c++) - { - gravis::d2Vector p( - margin + (r%2)*d/2 + c*d, - margin + r*dd); - - double rr = blob.getRelativeSignedDistance(p); - - if (rr < 0) - { - picks[FULL_BLOB].push_back(p); - - if (diag) Drawing::drawCross(p, 100.f, 3, plot); - - if (rr > -0.5) - { - picks[OUTER_HALF].push_back(p); - - if (diag) Drawing::drawCross(p, 100.f, 6, plot); - } - } - } - - const double l = blob.perimeter(); - const int samples = std::floor(l / min_distance); - - DelineatedBlob2D smaller_blob(blob); - smaller_blob.radius -= perimeter_margin; - - for (int i = 0; i < samples; i++) - { - const double phi = 2 * PI * i / (double) samples; - const d2Vector p = smaller_blob.getOutlinePoint(phi); - - if (p.x > margin && p.x < w - margin - && p.y > margin && p.y < h - margin) - { - picks[EDGE].push_back(p); - - d2Vector n = smaller_blob.estimateNormal(phi, 2 * PI / (double) samples); - normals.push_back(n); - - if (diag) Drawing::drawCross(p, 100.f, 10, plot); - } - } - } - - if (diag) plot.write(outPath + "diag_"+ZIO::itoa(m)+".mrc", pixel_size); - - std::vector tables(3); - - for (int i = 0; i < 3; i++) - { - const int pc = picks[i].size(); - MetaDataTable& table = tables[i]; - - table.setName("images"); - - table.addLabel(EMDL_IMAGE_COORD_X); - table.addLabel(EMDL_IMAGE_COORD_Y); - table.addLabel(EMDL_PARTICLE_AUTOPICK_FOM); - table.addLabel(EMDL_PARTICLE_CLASS); - table.addLabel(EMDL_ORIENT_PSI); - table.addLabel(EMDL_ORIENT_PSI_PRIOR); - - for (int p = 0; p < pc; p++) - { - table.addObject(); - - table.setValue(EMDL_IMAGE_COORD_X, picks[i][p].x, p); - table.setValue(EMDL_IMAGE_COORD_Y, picks[i][p].y, p); - table.setValue(EMDL_PARTICLE_AUTOPICK_FOM, 1.0, p); - table.setValue(EMDL_PARTICLE_CLASS, 0, p); - - if (i == EDGE) - { - const d2Vector n = normals[p]; - double phi_deg = 180 - RAD2DEG(atan2(n.x, -n.y)); - - table.setValue(EMDL_ORIENT_PSI, phi_deg, p); - table.setValue(EMDL_ORIENT_PSI_PRIOR, phi_deg, p); - } - else - { - table.setValue(EMDL_ORIENT_PSI, 0.0, p); - table.setValue(EMDL_ORIENT_PSI_PRIOR, 0.0, p); - } - } - } - - tables[EDGE].write(outPath + perimeter_dir + micrograph_name + "_blob_pick.star"); - tables[FULL_BLOB].write(outPath + full_dir + micrograph_name + "_blob_pick.star"); - tables[OUTER_HALF].write(outPath + outer_half_dir + micrograph_name + "_blob_pick.star"); - } - catch (...) - { - #pragma omp critical - { - failed_micrographs.push_back(all_micrograph_names[m]); - } - } - - if (verbose) - { - Log::endSection(); - } - } - - - if (failed_micrographs.size() > 0) - { - ZIO::writeToFile(failed_micrographs, outPath + "failed_micrographs.txt"); - } - - return 0; -} diff --git a/src/jaz/scripts/scale_test.cpp b/src/jaz/scripts/scale_test.cpp deleted file mode 100644 index 864f0c6d3..000000000 --- a/src/jaz/scripts/scale_test.cpp +++ /dev/null @@ -1,108 +0,0 @@ -#include -#include -#include -#include - -using namespace gravis; - - -int main(int argc, char** argv) -{ - const int box = 512; - - BufferedImage box2D(box, box); - - box2D.fill(1.f); - - const double dot_rad = box/16; - const double dot_edge = 3; - - for (int y = 0; y < box; y++) - for (int x = 0; x < box; x++) - { - const double xx = x < box/2? x : x - box; - const double yy = y < box/2? y : y - box; - const double r = sqrt(xx*xx + yy*yy); - - if (r < dot_rad) - { - box2D(x,y) = 1.f; - } - else if (r < dot_rad + dot_edge) - { - box2D(x,y) = 1.0 - (r - dot_rad) / dot_edge; - } - else - { - box2D(x,y) = 0.f; - } - } - - box2D.write("DEBUG_box2D_initial.mrc"); - - - BufferedImage box2D_FS(box/2 + 1, box); - FFT::FourierTransform(box2D, box2D_FS, FFT::Both); - - - - std::vector crops {512, 384, 256, 192, 128, 64}; - - for (int ic = 0; ic < crops.size(); ic++) - { - const int crop = crops[ic]; - - BufferedImage box3D(crop, crop, crop); - - BufferedImage box3D_FS(crop/2 + 1, crop, crop); - - box3D_FS.fill(fComplex(0.f, 0.f)); - - BufferedImage box3D_div(crop, crop, crop); - - BufferedImage ctf(box/2 + 1, box, box); - ctf.fill(1.f); - - { - BufferedImage - ctfImgFS(crop/2 + 1, crop, crop), - multiImageFS(crop/2 + 1, crop, crop); - - ctfImgFS.fill(0.f); - multiImageFS.fill(0.f); - - d4Matrix P; - P.loadIdentity(); - - P *= crop / (double) box; - - FourierBackprojection::backprojectSlice_forward_with_multiplicity( - box2D_FS, - ctf, - P, - box3D_FS, - ctfImgFS, - multiImageFS); - - box3D_FS *= (float) sqrt(box / (double) crop); - - BufferedImage div3D_FS(crop/2 + 1, crop, crop); - - for (size_t i = 0; i < div3D_FS.getSize(); i++) - { - div3D_FS[i] = box3D_FS[i] / (ctfImgFS[i] + 0.001); - } - - FFT::inverseFourierTransform(div3D_FS, box3D_div, FFT::Both); - } - - box3D_div.write("DEBUG_box3D_div_box_"+ZIO::itoa(box)+"_crop_"+ZIO::itoa(crop)+".mrc"); - - FFT::inverseFourierTransform(box3D_FS, box3D, FFT::Both); - - box3D.write("DEBUG_box3D_data_box_"+ZIO::itoa(box)+"_crop_"+ZIO::itoa(crop)+".mrc"); - } - - - return 0; -} diff --git a/src/jaz/scripts/scratch.cpp b/src/jaz/scripts/scratch.cpp deleted file mode 100644 index 851c2e0f4..000000000 --- a/src/jaz/scripts/scratch.cpp +++ /dev/null @@ -1,50 +0,0 @@ -#include -#include -#include -#include -#include - - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - const int s = 32; - BufferedImage test(s,s); - - for (int y = 0; y < s; y++) - for (int x = 0; x < s; x++) - { - test(x,y) = rand() / (double)RAND_MAX; - } - - const int s2 = 512; - BufferedImage test2(s2,s2,5); - - const double scale = s / (double)s2; - const double eps = 1e-6; - - for (int y = 0; y < s2; y++) - for (int x = 0; x < s2; x++) - { - test2(x,y,0) = Interpolation::cubicXY_clip(test, scale*x, scale*y, 0); - - d2Vector g = Interpolation::cubicXYGrad_clip(test, scale*x, scale*y, 0); - - const double vxp = Interpolation::cubicXY_clip(test, scale*x + eps, scale*y, 0); - const double vxn = Interpolation::cubicXY_clip(test, scale*x - eps, scale*y, 0); - const double vyp = Interpolation::cubicXY_clip(test, scale*x, scale*y + eps, 0); - const double vyn = Interpolation::cubicXY_clip(test, scale*x, scale*y - eps, 0); - - test2(x,y,1) = g.x; - test2(x,y,2) = (vxp - vxn) / (2.0 * eps); - - test2(x,y,3) = g.y; - test2(x,y,4) = (vyp - vyn) / (2.0 * eps); - - } - - test2.write("test2.mrc"); - - return 0; -} diff --git a/src/jaz/scripts/set_defocus_slope.cpp b/src/jaz/scripts/set_defocus_slope.cpp deleted file mode 100644 index 4ada8339c..000000000 --- a/src/jaz/scripts/set_defocus_slope.cpp +++ /dev/null @@ -1,83 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace gravis; - - -void run(int argc, char *argv[]); - -int main(int argc, char *argv[]) -{ - try - { - run(argc, argv); - } - catch (RelionError e) - { - return RELION_EXIT_FAILURE; - } - - return RELION_EXIT_SUCCESS; -} - -void run(int argc, char *argv[]) -{ - OptimisationSet optimisationSet; - - IOParser parser; - - parser.setCommandLine(argc, argv); - - optimisationSet.read( - parser, - true, // optimisation set - false, false, // particles - true, true, // tomograms - true, false, // trajectories - false, false, // manifolds - false, false); // reference - - const int gen_section = parser.addSection("General options"); - const double slope = textToDouble(parser.getOption("--ds", "Defocus slope", "1.0")); - std::string outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - - outDir = ZIO::prepareTomoOutputDirectory(outDir, argc, argv); - - - TomogramSet tomogram_set(optimisationSet.tomograms); - - const int tc = tomogram_set.size(); - - for (int t = 0; t < tc; t++) - { - tomogram_set.globalTable.setValue(EMDL_TOMO_DEFOCUS_SLOPE, slope, t); - } - - tomogram_set.write(outDir + "tomograms.star"); - optimisationSet.tomograms = outDir + "tomograms.star"; - - optimisationSet.write(outDir + "optimisation_set.star"); -} - diff --git a/src/jaz/scripts/shift_plot.cpp b/src/jaz/scripts/shift_plot.cpp deleted file mode 100644 index 83821ef3d..000000000 --- a/src/jaz/scripts/shift_plot.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - std::string partFn0, partFn1, tomoSetFn0, tomoSetFn1, outDir; - double scale; - - IOParser parser; - parser.setCommandLine(argc, argv); - - try - { - int defocus_section = parser.addSection("General options"); - - partFn0 = parser.getOption("--i0", "Initial-state particles"); - tomoSetFn0 = parser.getOption("--t0", "Initial tomogram set"); - - partFn1 = parser.getOption("--i1", "Final-state particles"); - tomoSetFn1 = parser.getOption("--t1", "Final tomogram set"); - - scale = textToDouble(parser.getOption("--scale", "Scale of output 3D arrows", "1")); - - outDir = parser.getOption("--o", "Output directory"); - - if (parser.checkForErrors()) std::exit(-1); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - if (outDir[outDir.length()-1] != '/') - { - outDir = outDir + "/"; - } - - int res = system(("mkdir -p "+outDir).c_str()); - - - ParticleSet dataSet0(partFn0, ""); - ParticleSet dataSet1(partFn1, ""); - - TomogramSet tomogramSet0(tomoSetFn0); - TomogramSet tomogramSet1(tomoSetFn1); - - std::vector> particles0 = dataSet0.splitByTomogram(tomogramSet0); - std::vector> particles1 = dataSet1.splitByTomogram(tomogramSet1); - - const int tc0 = particles0.size(); - const int tc1 = particles1.size(); - - if (tc0 != tc1) - { - REPORT_ERROR_STR("Unequal tomogram numbers: " << tc0 << " and " << tc1); - } - - const int tc = tc0; - - for (int t = 0; t < tc; t++) - { - const int pc0 = particles0[t].size(); - const int pc1 = particles1[t].size(); - - if (pc0 != pc1) - { - std::cerr << "Warning: unequal particle numbers in tomogram " << t << ": " - << pc0 << " and " << pc1 << std::endl; - std::cerr << "skipping tomogram" << std::endl; - - continue; - } - - const int pc = pc0; - - if (pc == 0) continue; - - const std::string tag = outDir+"tomo_"+ZIO::itoa(t); - - Mesh out; - - double var1D = 0.0; - d3Vector var3D(0.0, 0.0, 0.0); - - - for (int pp = 0; pp < pc; pp++) - { - const ParticleIndex p = particles0[t][pp]; - - d3Vector p0 = dataSet0.getPosition(p); - d3Vector p1 = dataSet1.getPosition(p); - d3Vector m = (p0 + p1) / 2.0; - - p0 = m + scale * (p0 - m); - p1 = m + scale * (p1 - m); - - double rad = 0.1 * (p0 - p1).length(); - MeshBuilder::addCone(p0, p1, rad, 5, out); - - const d3Vector d = p1 - p0; - - var1D += d.norm2(); - - var3D.x += d.x * d.x; - var3D.y += d.y * d.y; - var3D.z += d.z * d.z; - } - - var1D /= pc - 1; - var3D /= pc - 1; - - out.writePly(tag+"_mesh.ply"); - - std::cout << "std. dev.: " << sqrt(var1D) << '\n'; - std::cout << " x: " << sqrt(var3D.x) << '\n'; - std::cout << " y: " << sqrt(var3D.y) << '\n'; - std::cout << " z: " << sqrt(var3D.z) << std::endl; - } - - return 0; -} diff --git a/src/jaz/scripts/sort_2d_classes.cpp b/src/jaz/scripts/sort_2d_classes.cpp deleted file mode 100644 index 3516554aa..000000000 --- a/src/jaz/scripts/sort_2d_classes.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string particles_filename, class_averages_filename, outDir; - int num_threads; - - IOParser parser; - - try - { - IOParser parser; - - parser.setCommandLine(argc, argv); - - int general_section = parser.addSection("General options"); - - particles_filename = parser.getOption("--i", "Input file (e.g. run_it023_data.star)"); - class_averages_filename = parser.getOption("--ca", "Class averages stack"); - - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - outDir = ZIO::makeOutputDir(outDir); - - ObservationModel obs_model; - MetaDataTable particles_table; - ObservationModel::loadSafely(particles_filename, obs_model, particles_table); - - const int class_count = ClassHelper::countClasses(particles_table); - std::vector particle_count = ClassHelper::getClassSizes(particles_table, class_count); - std::vector order = ClassHelper::sortByAscendingFrequency(particle_count); - - BufferedImage class_averages; - class_averages.read(class_averages_filename); - - std::cout << class_averages.getSizeString() << std::endl; - - const int s = class_averages.xdim; - - BufferedImage output_stack(s, s, class_count); - - std::ofstream class_size_file(outDir+"class_sizes.txt"); - - int total = 0; - - for (int i = 0; i < class_count; i++) - { - const int j = order[i]; - - output_stack.getSliceRef(i).copyFrom(class_averages.getSliceRef(j)); - class_size_file << i << " (old " << j << ") " << particle_count[j] << '\n'; - - total += particle_count[j]; - } - - class_size_file << "\ntotal: " << total << '\n'; - - output_stack.write(outDir+"sorted_classes.mrc"); - - return 0; -} - diff --git a/src/jaz/scripts/split_tilts.cpp b/src/jaz/scripts/split_tilts.cpp deleted file mode 100644 index 3a5e9308b..000000000 --- a/src/jaz/scripts/split_tilts.cpp +++ /dev/null @@ -1,230 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - IOParser parser; - - double data_scale; - int num_threads; - bool write_stack; - - std::string in_file, gain_file, out_path; - OptimisationSet optimisation_set; - - try - { - parser.setCommandLine(argc, argv); - - optimisation_set.read( - parser, - true, // optimisation set - false, false, // particles - true, true, // tomograms - false, false, // trajectories - false, false, // manifolds - false, false); // reference - - in_file = parser.getOption("--ti", "STAR file mapping chronological tilt indices to their movie files"); - gain_file = parser.getOption("--g", "Gain reference file", ""); - data_scale = textToDouble(parser.getOption("--ds", "Scale gain-reference multiplied pixels by this before truncating them to 16 bits", "1000")); - write_stack = !parser.checkOption("--no_stack", "Do not write out an image stack"); - out_path = parser.getOption("--o", "Output filename"); - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - out_path = ZIO::prepareTomoOutputDirectory(out_path, argc, argv); - ZIO::makeDir(out_path+"TiltSeries"); - - TomogramSet tomogram_set = TomogramSet(optimisation_set.tomograms, true); - - std::vector tables = MetaDataTable::readAll(in_file, 100); - - const int tc = tables.size(); - const int tc2 = tomogram_set.size(); - - if (tc != tc2) - { - REPORT_ERROR_STR("Tomogram count mismatch: " << tc << " vs. " << tc2); - } - - - BufferedImage gain; - bool has_gain = gain_file != ""; - - if (has_gain) - { - gain.read(gain_file); - } - - TomogramSet new_tomogram_set = tomogram_set; - - Log::beginProgress("Processing tomograms", tc); - - for (int tt = 0; tt < tc; tt++) - { - Log::updateProgress(tt); - - MetaDataTable& table = tables[tt]; - const std::string tomo_name = table.getName(); - - const int t = tomogram_set.getTomogramIndexSafely(tomo_name); - const Tomogram tomogram = tomogram_set.loadTomogram(t, false); - - const int fc = tomogram.frameCount; - const int fc2 = table.numberOfObjects(); - - if (fc2 != fc) - { - REPORT_ERROR_STR( - "Tilt number mismatch in " << table.getName() - << ": " << fc2 << " vs. " << fc); - } - - - int new_frame_count = 0; - i2Vector movie_size(-1,-1); - std::vector frames_by_tilt(fc); - - double pixel_size = 1; - - for (int ft = 0; ft < fc; ft++) - { - const int f = tomogram.frameSequence[ft]; - - const std::string movie_file = table.getString(EMDL_TOMO_TILT_MOVIE_FILE_NAME, ft); - t3Vector size = ImageFileHelper::getSize(movie_file); - - if (ft == 0) - { - pixel_size = ImageFileHelper::getSamplingRate(movie_file); - } - - new_frame_count += size.z; - - if (movie_size.x < 0) - { - movie_size.x = size.x; - movie_size.y = size.y; - } - else if (movie_size.x != size.x || movie_size.y != size.y) - { - REPORT_ERROR_STR( - "Movie size mismatch in " << table.getName() - << ": " << movie_size.x << 'x' << movie_size.y - << " vs. " << size.x << 'x' << size.y); - } - - frames_by_tilt[f] = size.z; - } - - if (has_gain && (gain.xdim != movie_size.x || gain.ydim != movie_size.y)) - { - REPORT_ERROR_STR( - "Gain-reference size mismatch in " << table.getName() - << ": " << movie_size.x << 'x' << movie_size.y - << " vs. " << gain.xdim << 'x' << gain.ydim); - } - - std::vector tilt_to_frame(fc); - int current_index = 0; - - for (int f = 0; f < fc; f++) - { - tilt_to_frame[f] = current_index; - current_index += frames_by_tilt[f]; - } - - - - BufferedImage new_stack(movie_size.x, movie_size.y, new_frame_count); - const std::string out_file = out_path + "TiltSeries/" + tomo_name + ".mrc"; - - if (write_stack) - { - new_stack.fill(0.f); - - #pragma omp parallel for num_threads(num_threads) - for (int ft = 0; ft < fc; ft++) - { - const int f = tomogram.frameSequence[ft]; - - BufferedImage movie; - const std::string movie_file = table.getString(EMDL_TOMO_TILT_MOVIE_FILE_NAME, ft); - movie.read(movie_file); - - for (int ff = 0; ff < movie.zdim; ff++) - { - if (has_gain) - { - for (size_t y = 0; y < movie.ydim; y++) - for (size_t x = 0; x < movie.xdim; x++) - { - new_stack(x, y, tilt_to_frame[f] + ff) = data_scale * (gain(x,y) * movie(x,y,ff)); - } - } - else - { - for (size_t y = 0; y < movie.ydim; y++) - for (size_t x = 0; x < movie.xdim; x++) - { - new_stack(x, y, tilt_to_frame[f] + ff) = movie(x,y,ff); - } - } - } - } - - - new_stack.writeNoVTK(out_file, pixel_size); - } - - new_tomogram_set.globalTable.setValue(EMDL_TOMO_TILT_SERIES_NAME, out_file, t); - new_tomogram_set.globalTable.setValue(EMDL_TOMO_FRAME_COUNT, new_frame_count, t); - - const double fdose0 = tomogram_set.globalTable.getDouble(EMDL_TOMO_IMPORT_FRACT_DOSE, t); - new_tomogram_set.globalTable.setValue(EMDL_TOMO_IMPORT_FRACT_DOSE, fdose0 / frames_by_tilt[0], t); - - - MetaDataTable& new_table = new_tomogram_set.tomogramTables[t]; - MetaDataTable& old_table = tomogram_set.tomogramTables[t]; - - new_table.clear(); - new_table.setName(old_table.getName()); - - for (int f = 0; f < fc; f++) - { - const double dose0 = old_table.getDouble(EMDL_MICROGRAPH_PRE_EXPOSURE, f); - const double ddose = tomogram.fractionalDose / frames_by_tilt[f]; - - for (int ff = 0; ff < frames_by_tilt[f]; ff++) - { - new_table.addObject(old_table.getObject(f)); - new_table.setValue(EMDL_MICROGRAPH_PRE_EXPOSURE, dose0 + ff * ddose); - } - } - } - - Log::endProgress(); - - optimisation_set.tomograms = out_path + "tomograms.star"; - new_tomogram_set.write(optimisation_set.tomograms); - optimisation_set.write(out_path + "optimisation_set.star"); - - return 0; -} diff --git a/src/jaz/scripts/suppress_cone.cpp b/src/jaz/scripts/suppress_cone.cpp deleted file mode 100644 index c71b0fb90..000000000 --- a/src/jaz/scripts/suppress_cone.cpp +++ /dev/null @@ -1,79 +0,0 @@ -#include -#include -#include -#include -#include - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - IOParser parser; - - int n_threads; - - double slope, d0; - std::string imgFn, outFn; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - imgFn = parser.getOption("--i", "map"); - const double alpha = 0.5 * textToDouble(parser.getOption("--angle", "opening angle [°]", "2")); - slope = sin(DEG2RAD(alpha)); - d0 = textToDouble(parser.getOption("--d0", "d0", "1")); - n_threads = textToInteger(parser.getOption("--j", "Number of threads", "5")); - outFn = parser.getOption("--o", "Output filename"); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - std::cout << "slope = " << slope << std::endl; - - BufferedImage img; - img.read(imgFn); - - const int s = img.xdim; - const int sh = s/2 + 1; - - BufferedImage imgFS; - - FFT::FourierTransform(img, imgFS); - imgFS.write("debug_0.vtk"); - - - BufferedImage mask(sh,s,s); - - for (int z = 0; z < s; z++) - for (int y = 0; y < s; y++) - for (int x = 0; x < sh; x++) - { - const double xx = x; - const double yy = y < s/2? y : y - s; - const double zz = z < s/2? z : z - s; - - const double rho = sqrt(xx*xx + yy*yy); - const double t = rho / (std::abs(zz) * slope + d0); - - const double m = 1.0 - exp(-0.5*t*t); - - imgFS(x,y,z) *= m; - - mask(x,y,z) = m; - } - - imgFS.write("debug_1.vtk"); - FFT::inverseFourierTransform(imgFS, img); - - mask.write("debug_mask.mrc"); - img.write(outFn); -} diff --git a/src/jaz/scripts/test_extraction.cpp b/src/jaz/scripts/test_extraction.cpp deleted file mode 100644 index a2694d758..000000000 --- a/src/jaz/scripts/test_extraction.cpp +++ /dev/null @@ -1,211 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -using namespace gravis; - - -int main(int argc, char *argv[]) -{ - std::string particlesFn, outDir; - double margin, SNR; - int num_threads; - - - IOParser parser; - - try - { - IOParser parser; - - parser.setCommandLine(argc, argv); - - int general_section = parser.addSection("General options"); - - particlesFn = parser.getOption("--i", "Input file (e.g. run_it023_data.star)", ""); - SNR = textToDouble(parser.getOption("--SNR", "Assumed signal-to-noise ratio", "0.1")); - margin = textToDouble(parser.getOption("--m", "Margin around the particle [Px]", "20")); - num_threads = textToInteger(parser.getOption("--j", "Number of OMP threads", "6")); - outDir = parser.getOption("--o", "Output directory"); - - Log::readParams(parser); - - if (parser.checkForErrors()) - { - REPORT_ERROR("Errors encountered on the command line (see above), exiting..."); - } - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - outDir = ZIO::makeOutputDir(outDir); - - ObservationModel obs_model; - MetaDataTable particles_table; - ObservationModel::loadSafely(particlesFn, obs_model, particles_table); - - int max_class = -1; - - for (long int p = 0; p < particles_table.numberOfObjects(); p++) - { - const int class_id = particles_table.getIntMinusOne(EMDL_PARTICLE_CLASS, p); - - if (class_id > max_class) max_class = class_id; - } - - const int class_count = max_class + 1; - - if (class_count == 1) - { - Log::print("1 class found"); - } - else - { - Log::print(ZIO::itoa(class_count)+" classes found"); - } - - - std::vector class_size(class_count, 0); - - for (long int p = 0; p < particles_table.numberOfObjects(); p++) - { - const int class_id = particles_table.getIntMinusOne( - EMDL_PARTICLE_CLASS, p); - - class_size[class_id]++; - } - - - - const int box_size = obs_model.getBoxSize(0); - const double pixel_size = obs_model.getPixelSize(0); - - - - BufferedImage data(box_size / 2 + 1, box_size, num_threads * class_count); - data.fill(dComplex(0.0, 0.0)); - - BufferedImage weight(box_size / 2 + 1, box_size, num_threads * class_count); - weight.fill(0.0); - - - std::vector particles_by_micrograph = StackHelper::splitByMicrographName(particles_table); - - const int micrograph_count = particles_by_micrograph.size(); - - for (int micrograph_id = 0; micrograph_id < micrograph_count; micrograph_id++) - { - Log::print("Micrograph " + ZIO::itoa(micrograph_id+1)); - - const MetaDataTable& particles_in_micrograph = particles_by_micrograph[micrograph_id]; - const int particle_count = particles_in_micrograph.numberOfObjects(); - - - BufferedImage micrograph; - float mean_value = 0, std_dev = 1; - double micrograph_pixel_size = pixel_size; - double extraction_scale = 1; - - - const std::string micrograph_filename = particles_in_micrograph.getString(EMDL_MICROGRAPH_NAME, 0); - micrograph_pixel_size = ImageFileHelper::getSamplingRate(micrograph_filename); - extraction_scale = pixel_size / micrograph_pixel_size; - extraction_scale = std::round(1000 * extraction_scale)/1000.0; - - - micrograph.read(micrograph_filename); - - mean_value = Normalization::computeMean(micrograph); - std_dev = sqrt(Normalization::computeVariance(micrograph, mean_value)); - - const i2Vector micrograph_size(micrograph.xdim, micrograph.ydim); - - - BufferedImage - out_loaded(box_size, box_size, particle_count), - out_extracted(box_size, box_size, particle_count), - out_centres = micrograph; - - for (long int p = 0; p < particle_count; p++) - { - BufferedImage particle_image_RS; - - std::string img_fn = particles_in_micrograph.getString(EMDL_IMAGE_NAME, p); - particle_image_RS.read(img_fn); - - out_loaded.copySliceFrom(p, particle_image_RS); - - const int extraction_box_size = std::round(extraction_scale * box_size); - - const d2Vector global_position_0( - particles_in_micrograph.getDouble(EMDL_IMAGE_COORD_X, p), - particles_in_micrograph.getDouble(EMDL_IMAGE_COORD_Y, p)); - - const d2Vector global_position = global_position_0; - - i2Vector integral_position(std::round(global_position.x), std::round(global_position.y)); - - BufferedImage extraction_buffer(extraction_box_size, extraction_box_size); - - const int x0 = integral_position.x - extraction_box_size / 2; - const int y0 = integral_position.y - extraction_box_size / 2; - - for (int y = 0; y < extraction_box_size; y++) - for (int x = 0; x < extraction_box_size; x++) - { - int xx = x0 + x; - int yy = y0 + y; - - if (xx < 0) xx = 0; - else if (xx >= micrograph_size.x) xx = micrograph_size.x - 1; - - if (yy < 0) yy = 0; - else if (yy >= micrograph_size.y) yy = micrograph_size.y - 1; - - extraction_buffer(x,y) = -micrograph(xx, yy); - - out_centres(xx,yy) = mean_value + 6 * std_dev; - } - - const double mean_value_p = Normalization::computeMean(extraction_buffer); - extraction_buffer -= mean_value_p; - - extraction_buffer /= std_dev; - - if (std::abs(micrograph_pixel_size - pixel_size) > 0.001) - { - particle_image_RS = Resampling::FourierCrop_fullStack( - extraction_buffer, extraction_scale, num_threads, true); - } - else - { - particle_image_RS = extraction_buffer; - } - - out_extracted.copySliceFrom(p, particle_image_RS); - } - - out_extracted.write(outDir+"micrograph_"+ZIO::itoa(micrograph_id)+"_extracted.mrc"); - out_loaded.write(outDir+"micrograph_"+ZIO::itoa(micrograph_id)+"_loaded.mrc"); - out_centres.write(outDir+"micrograph_"+ZIO::itoa(micrograph_id)+"_centres.mrc"); - } - - return 0; -} diff --git a/src/jaz/scripts/test_logger.cpp b/src/jaz/scripts/test_logger.cpp deleted file mode 100644 index 6bd8d9dce..000000000 --- a/src/jaz/scripts/test_logger.cpp +++ /dev/null @@ -1,76 +0,0 @@ -#include -#include -#include - - -int main(int argc, char *argv[]) -{ - - IOParser parser; - parser.setCommandLine(argc, argv); - - Log::readParams(parser); - - const int N = 70; - - Log::beginSection("initialising"); - - Log::beginSection("component X"); - - Log::print("loading X"); - usleep(920000u); - - Log::beginProgress("transmogrifying", N); - - for (int i = 0; i < N; i++) - { - Log::updateProgress(i); - - usleep(50000u); - } - - Log::endProgress(); - - Log::print("component X ready"); - - Log::endSection(); - - Log::endSection(); - - Log::beginSection("processing"); - - Log::beginSection("component X"); - - Log::beginSection("preparing"); - usleep(230000u); - - Log::print("step 1"); - usleep(400000u); - Log::print("step 2"); - usleep(270000u); - - Log::endSection(); - - Log::endSection(); - - Log::endSection(); - - Log::beginProgress("performing global optimisation", N); - - for (int i = 0; i < N; i++) - { - Log::updateProgress(i); - - usleep(70000u); - } - - Log::endProgress(); - - Log::print("writing"); - - usleep(370000u); - - Log::print("all done"); - - return 0; -} diff --git a/src/jaz/scripts/test_splines.cpp b/src/jaz/scripts/test_splines.cpp deleted file mode 100644 index 112c5ed9b..000000000 --- a/src/jaz/scripts/test_splines.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include -#include -#include - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - const int w = 5; - const int h = 4; - - BufferedImage data(w,h,2); - - for (int z = 0; z < 2; z++) - for (int y = 0; y < h; y++) - for (int x = 0; x < w; x++) - for (int i = 0; i < 4; i++) - { - data(x,y,z)[i] = 1.0 - 2.0 * (rand() / (double) RAND_MAX); - } - - - const int ww = 1024; - const int hh = 768; - - Deformation2D::Parameters parameters; - parameters.grid_width = w; - parameters.grid_height = h; - - Spline2DDeformationModel model(parameters, i2Vector(ww, hh)); - - /*BufferedImage test0(ww,hh), test1(ww,hh); - - for (int y = 0; y < hh; y++) - for (int x = 0; x < ww; x++) - { - d2Vector def, def_x, def_y; - - model.computeShiftAndGradient( - d2Vector(x,y), (double*)(data.data), def, def_x, def_y); - - test0(x,y) = def_y.x; - } - - test0.write("spline_test_gradXy-a.mrc"); - - for (int y = 1; y < hh-1; y++) - for (int x = 0; x < ww; x++) - { - d2Vector def1, def1_x, def1_y; - d2Vector def0, def0_x, def0_y; - - model.computeShiftAndGradient( - d2Vector(x,y-1), (double*)(data.data), def0, def0_x, def0_y); - - model.computeShiftAndGradient( - d2Vector(x,y+1), (double*)(data.data), def1, def1_x, def1_y); - - test1(x,y) = (def1.x - def0.x) / 2.0; - } - - test1.write("spline_test_gradXy-n.mrc");*/ - - - BufferedImage data0 = data; - - const double eps = 1e-3; - const int dim = 0; - - for (int dy = 0; dy < 2; dy++) - for (int dx = 0; dx < 2; dx++) - for (int i = 0; i < 4; i++) - { - data = data0; - - d2Vector def1, def1_x, def1_y; - d2Vector def0, def0_x, def0_y; - - const d2Vector pl(1.7 * model.gridSpacing.x, 1.2 * model.gridSpacing.y); - - model.computeShiftAndGradient( - pl, (double*)(data.data), def0, def0_x, def0_y); - - data(1+dx, 1+dy, dim)[i] += eps; - - model.computeShiftAndGradient( - pl, (double*)(data.data), def1, def1_x, def1_y); - - const d2Vector d = def1 - def0; - const d2Vector g0(1,2); - - const double m = g0.dot(d) / eps; - - - BufferedImage grad(w,h,2); - grad.fill(d4Vector(0.0,0.0,0.0,0.0)); - - model.updateDataTermGradient(pl, g0, 0, (double*)grad.data); - - std::cout << std::setprecision(12) << std::scientific - << grad(1+dx, 1+dy, dim)[i] << " \t vs \t " << m << " \t (" - << (grad(1+dx, 1+dy, dim)[i] - m) << ')' << std::endl; - } - - return 0; -} diff --git a/src/jaz/scripts/update_tomogram_set.cpp b/src/jaz/scripts/update_tomogram_set.cpp deleted file mode 100644 index bc60045f0..000000000 --- a/src/jaz/scripts/update_tomogram_set.cpp +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace gravis; - -int main(int argc, char *argv[]) -{ - std::string tomoSetFn, outFn; - - IOParser parser; - - try - { - parser.setCommandLine(argc, argv); - int gen_section = parser.addSection("General options"); - - tomoSetFn = parser.getOption("--t", "Tomogram set"); - outFn = parser.getOption("--o", "Output file name"); - - parser.checkForErrors(); - } - catch (RelionError XE) - { - parser.writeUsage(std::cout); - std::cerr << XE; - exit(1); - } - - std::ifstream ifs(tomoSetFn); - - if (!ifs) - { - REPORT_ERROR_STR("update_tomogram_set: Unable to read " << tomoSetFn); - } - - - MetaDataTable globalTable; - std::vector tomogramTables; - - globalTable.readStar(ifs, "global"); - - const int tc = globalTable.numberOfObjects(); - - tomogramTables.resize(tc); - - std::vector allTables = MetaDataTable::readAll(ifs, tc+1); - - bool namesAreOld = false; - - for (int t = 0; t < tc; t++) - { - const std::string expectedOldName = "tomo_" + ZIO::itoa(t); - const std::string expectedNewName = globalTable.getString(EMDL_TOMO_NAME, t); - const std::string name = allTables[t+1].getName(); - - if (name == expectedOldName) - { - namesAreOld = true; - } - else if (name != expectedNewName) - { - REPORT_ERROR_STR("TomogramSet::TomogramSet: file is corrupted " << tomoSetFn); - } - - tomogramTables[t] = allTables[t+1]; - tomogramTables[t].setName(expectedNewName); - } - - if (!namesAreOld) - { - Log::warn("Tomogram set " + tomoSetFn + " was already up to date."); - } - - globalTable.setName("global"); - - if (outFn.find_last_of('/') != std::string::npos) - { - std::string path = outFn.substr(0, outFn.find_last_of('/')); - mktree(path); - } - - std::ofstream ofs(outFn); - - if (!ofs) - { - REPORT_ERROR("update_tomogram_set: unable to write to " + outFn); - } - - globalTable.write(ofs); - - for (int t = 0; t < tc; t++) - { - tomogramTables[t].write(ofs); - } - - return 0; -} diff --git a/src/jaz/tomography/programs/align.cpp b/src/jaz/tomography/programs/align.cpp index db1f7f085..8a8bce0a6 100644 --- a/src/jaz/tomography/programs/align.cpp +++ b/src/jaz/tomography/programs/align.cpp @@ -72,6 +72,7 @@ void AlignProgram::parseInput() do_anisotropy = parser.checkOption("--aniso", "Assume an anisotropic projection model"); per_tilt_anisotropy = parser.checkOption("--per_tilt_aniso", "Fit independent view anisotropy for each tilt image"); num_iters = textToInteger(parser.getOption("--it", "Max. number of iterations", "10000")); + only_do_unfinished =parser.checkOption("--only_do_unfinished", "Skip tomograms for which intermediate projections.star files exist"); int motion_section = parser.addSection("Motion estimation options"); diff --git a/src/jaz/tomography/programs/reconstruct_particle.cpp b/src/jaz/tomography/programs/reconstruct_particle.cpp index 04b4e85da..2277ed2de 100644 --- a/src/jaz/tomography/programs/reconstruct_particle.cpp +++ b/src/jaz/tomography/programs/reconstruct_particle.cpp @@ -343,7 +343,7 @@ void ReconstructParticleProgram::processTomograms( part_id, fc, tomogram.centre, tomogram.optics.pixelSize); std::vector projCut(fc), projPart(fc); - const std::vector isVisible = tomogram.determineVisiblity(traj, s/2.0); + const std::vector isVisible = tomogram.determineVisiblity(traj, binning * s / 2.0); const bool circle_crop = do_circle_crop; diff --git a/src/jaz/tomography/programs/reconstruct_tomogram.cpp b/src/jaz/tomography/programs/reconstruct_tomogram.cpp index d86ccac77..70fa53c98 100644 --- a/src/jaz/tomography/programs/reconstruct_tomogram.cpp +++ b/src/jaz/tomography/programs/reconstruct_tomogram.cpp @@ -18,15 +18,31 @@ using namespace gravis; double ReconstructSnrOptimisation::gradAndValue(const std::vector &x, std::vector &gradDest) const { - int size = x.size(); if (size != ctf2.size()) REPORT_ERROR("ReconstructSnrOptimisation ERROR: input x has incorrect size!"); if (size != gradDest.size()) REPORT_ERROR("ReconstructSnrOptimisation ERROR: input gradDest has incorrect size!"); + // Optimisation target: + // F(A) = 1/2 *|| C^2A - X||^2 +lamda/2 ||DA||^2 + // with + // ( 1 0 0 0) + // D = (-1 1 0 0) + // ( 0 -1 1 0) + // ( 0 0 -1 1) + // + // Then gradient: + // Delta F(A) = C^2 * ( C^2 A - X) * lambda * D^T * D * A + // + // and + // ( 2 -1 0 0) + // D ^T * D= (-1 2 -1 0) + // ( 0 -1 2 -1) + // ( 0 0 -1 2) + + /* Old, slow code for readability of the algorithm... // Convert input vector to Matrix1D Matrix1D xx(size); - for (int i = 0; i < size; i++) - VEC_ELEM(xx, i) = x[i]; + for (int i = 0; i < size; i++) VEC_ELEM(xx, i) = x[i]; // Calculate the current value of the target function Matrix1D Dy = D * xx; @@ -37,10 +53,30 @@ double ReconstructSnrOptimisation::gradAndValue(const std::vector &x, st Matrix1D grad = ctf2 * diff + lambda * D.transpose() * D * xx; // Convert output Matrix1D grad to vector - for (int i = 0; i < size; i++) - gradDest[i] = VEC_ELEM(grad, i); + for (int i = 0; i < size; i++) gradDest[i] = VEC_ELEM(grad, i); + */ + + // Much faster to act on the vectors only + std::vector myGrad(size); + RFLOAT sumDy2 = 0., mydiff, diff2 = 0, myDtDx; + for (long int i = 0; i < size; i++) + { + RFLOAT elem = x[i]; + if (i-1 >= 0) elem -= x[i-1]; + sumDy2 += elem*elem; + mydiff = ctf2[i] * x[i] - snr[i]; + diff2 += mydiff * mydiff; + + myDtDx = (i == size-1) ? x[i] : 2*x[i]; + if (i-1 >= 0) myDtDx -= x[i-1]; + if (i+1 < size) myDtDx -= x[i+1]; + + // set gradient + gradDest[i] = ctf2[i] * mydiff + lambda * myDtDx; + } + + return diff2 + (lambda / 2.) * sumDy2; - return value; } void TomoBackprojectProgram::readParameters(int argc, char *argv[]) @@ -63,43 +99,47 @@ void TomoBackprojectProgram::readParameters(int argc, char *argv[]) tomoName = parser.getOption("--tn", "Tomogram name", "*"); outFn = parser.getOption("--o", "Output filename (or output directory in case of reconstructing multiple tomograms)"); do_even_odd_tomograms = parser.checkOption("--generate_split_tomograms", "Reconstruct tomograms from even/odd movie frames or tilt image index for denoising"); + do_only_unfinished = parser.checkOption("--only_do_unfinished", "Only reconstruct those tomograms that haven't finished yet"); w = textToInteger(parser.getOption("--w", "Width")); h = textToInteger(parser.getOption("--h", "Height" )); d = textToInteger(parser.getOption("--d", "Thickness")); - fourierInversion = parser.checkOption("--fourier", "Use a Fourier-inversion reconstruction algorithm"); - lambda = textToDouble(parser.getOption("--lambda", "Regularisation constant for CTF-correction of the SNRs in the Fourier-inversion algorithm", "10")); - ctf_intact_first_peak = parser.checkOption("--ctf_intact_first_peak", "Leave CTFs intact until first peak"); + spacing = textToDouble(parser.getOption("--bin", "Binning", "1.0")); + angpix_spacing = textToDouble(parser.getOption("--binned_angpix", "OR: desired pixel size after binning", "-1")); + + tiltAngleOffset = textToDouble(parser.getOption("--tiltangle_offset", "Offset applied to all tilt angles (in deg)", "0")); + BfactorPerElectronDose = textToDouble(parser.getOption("--bfactor_per_edose", "B-factor dose-weighting per electron/A^2 dose (default is use Niko's model)", "0")); + n_threads = textToInteger(parser.getOption("--j", "Number of threads", "1")); + + int wbp_section = parser.addSection("Weighted backprojection options"); applyWeight = !parser.checkOption("--no_weight", "Do not perform weighting in Fourier space using a Wiener filter"); applyPreWeight = parser.checkOption("--pre_weight", "Pre-weight the 2D slices prior to backprojection"); FourierCrop = parser.checkOption("--Fc", "Downsample the 2D images by Fourier cropping"); - do_only_unfinished = parser.checkOption("--only_do_unfinished", "Only reconstruct those tomograms that haven't finished yet"); SNR = textToDouble(parser.getOption("--SNR", "SNR assumed by the Wiener filter", "10")); - applyCtf = parser.checkOption("--ctf", "Perform CTF correction"); doWiener = !parser.checkOption("--skip_wiener", "Do multiply images with CTF, but don't divide by CTF^2 in Wiener filter"); - if (!doWiener) applyCtf = true; zeroDC = !parser.checkOption("--keep_mean", "Do not zero the DC component of each frame"); - - taperDist = textToDouble(parser.getOption("--td", "Tapering distance", "0.0")); - taperFalloff = textToDouble(parser.getOption("--tf", "Tapering falloff", "0.0")); + taperDist = textToDouble(parser.getOption("--td", "Tapering distance", "0.0")); + taperFalloff = textToDouble(parser.getOption("--tf", "Tapering falloff", "0.0")); // SHWS & Aburt 19Jul2022: use zero-origins from relion-4.1 onwards.... x0 = textToDouble(parser.getOption("--x0", "X origin", "0.0")); y0 = textToDouble(parser.getOption("--y0", "Y origin", "0.0")); z0 = textToDouble(parser.getOption("--z0", "Z origin", "0.0")); - spacing = textToDouble(parser.getOption("--bin", "Binning", "1.0")); - angpix_spacing = textToDouble(parser.getOption("--binned_angpix", "OR: desired pixel size after binning", "-1")); - tiltAngleOffset = textToDouble(parser.getOption("--tiltangle_offset", "Offset applied to all tilt angles (in deg)", "0")); - BfactorPerElectronDose = textToDouble(parser.getOption("--bfactor_per_edose", "B-factor dose-weighting per electron/A^2 dose (default is use Niko's model)", "0")); - n_threads = textToInteger(parser.getOption("--j", "Number of threads", "1")); + int fourier_section = parser.addSection("Fourier inversion options"); + fourierInversion = parser.checkOption("--fourier", "Use a Fourier-inversion reconstruction algorithm"); + fourierWienerFilter = !parser.checkOption("--skip_fourier_wiener", "Only CTF-premultiplication will be performed, but Wiener-type division is skipped"); + lambda = textToDouble(parser.getOption("--lambda", "Regularisation constant for CTF-correction of the SNRs in the Fourier-inversion algorithm", "10")); + ctf_intact_first_peak = parser.checkOption("--ctf_intact_first_peak", "Leave CTFs intact until first peak"); + + int proj_section = parser.addSection("2D projection options"); - do_2dproj = parser.checkOption("--do_proj", "Use this to skip calculation of 2D projection of the tomogram along the Z-axis"); + do_2dproj = parser.checkOption("--do_proj", "Use this to also generate 2D projection of the entire tomogram along the Z-axis"); centre_2dproj = textToInteger(parser.getOption("--centre_proj", "Central Z-slice for 2D projection (in tomogram pixels from the middle)", "0")); thickness_2dproj = textToInteger(parser.getOption("--thickness_proj", "Thickness of the 2D projection (in tomogram pixels)", "10")); @@ -169,12 +209,28 @@ void TomoBackprojectProgram::initialise(bool verbose) std::cout << " + Applying a tilt angle offset of " << tiltAngleOffset << " degrees" << std::endl; } + if (fourierInversion) + { + std::cout << " + Using a Fourier-inversion reconstruction algorithm " << std::endl; + if (fourierWienerFilter) std::cout << " - with a Wiener-filter correction for the CTFs " << std::endl; + else std::cout << " - with only CTF-premultiplication of the tilt series images (for subsequent subtomogram extraction) " << std::endl; + } + else + { + std::cout << " + Using a real-space back-projection algorithm " << std::endl; + std::cout << " - applyWeight= " << applyWeight << std::endl; + std::cout << " - applyPreWeight= " << applyPreWeight << std::endl; + std::cout << " - FourierCrop= " << FourierCrop << std::endl; + std::cout << " - applyCtf= " << applyCtf << std::endl; + std::cout << " - doWiener= " << doWiener << " with SNR= " << SNR << std::endl; + } if (do_2dproj) { - std::cout << " + Making 2D projections " << std::endl; + std::cout << " + Also making 2D projections of the tomograms " << std::endl; std::cout << " - centered at " << centre_2dproj << " tomogram pixels from the centre of the tomogram" << std::endl; std::cout << " - and a thickness of " << thickness_2dproj << " tomogram pixels" << std::endl; } + } } @@ -299,7 +355,6 @@ MultidimArray TomoBackprojectProgram::getCtfCorrectedSNR(const Multidim } std::vector newSNR= LBFGS::optimize(initial, problem, false, 100, 1e-7, 1e-6); - FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(corrSNR) { if (n < first_peak) @@ -318,7 +373,6 @@ MultidimArray TomoBackprojectProgram::getCtfCorrectedSNR(const Multidim if (verb > 0) { - std::cout << " first_peak= " << first_peak << std::endl; std::cout << "# shell corrSNR newSNR oriSNR corrSNR*CTF^2 oriSNR*CTF^2 CTF^2 FSC" << std::endl; FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(corrSNR) { @@ -342,9 +396,15 @@ void TomoBackprojectProgram::reconstructOneTomogramFourier(int tomoIndex) Tomogram tomogram1, tomogram2; - tomogram1 = tomogramSet.loadTomogram(tomoIndex, true, true, false, w, h, d); - tomogram2 = tomogramSet.loadTomogram(tomoIndex, true, false, true, w, h, d); - + if (fourierWienerFilter) + { + tomogram1 = tomogramSet.loadTomogram(tomoIndex, true, true, false, w, h, d); + tomogram2 = tomogramSet.loadTomogram(tomoIndex, true, false, true, w, h, d); + } + else + { + tomogram1 = tomogramSet.loadTomogram(tomoIndex, true, false, false, w, h, d); + } MetaDataTable& m = tomogramSet.tomogramTables[tomoIndex]; if (!tomogram1.hasMatrices) REPORT_ERROR("ERROR; tomograms do not have tilt series alignment parameters to calculate projectionMatrices!"); @@ -355,8 +415,10 @@ void TomoBackprojectProgram::reconstructOneTomogramFourier(int tomoIndex) // Make sure to make all images squared before using FFTs int square_box = (tomogram1.stack.xdim == tomogram1.stack.ydim) ? tomogram1.stack.xdim : XMIPP_MAX(tomogram1.stack.xdim, tomogram1.stack.ydim); - // Make sqrt(2) bigger to account for the empty corners that otherwise appear with the spherical mask.... - square_box *= sqrt(2.); + + RFLOAT extra_box = 0.2 * square_box; + square_box += extra_box; + if (square_box%2 != 0) square_box++; double pixelSizeAct = tomogramSet.getTiltSeriesPixelSize(tomoIndex); int new_box = square_box; @@ -375,113 +437,156 @@ void TomoBackprojectProgram::reconstructOneTomogramFourier(int tomoIndex) } tomogramSet.globalTable.setValue(EMDL_TOMO_TOMOGRAM_BINNING, spacing, tomoIndex); - float padding_factor = 1; - bool skip_gridding = true; BackProjector BP = BackProjector(new_box, 3, - "C1", TRILINEAR, padding_factor, - 10, 0, 1.9, 15, 2, skip_gridding); + "C1", TRILINEAR, 1., + 10, 0, 1.9, 15, 2, true); BP.initZeros(); #pragma omp parallel for num_threads(n_threads) for (int f = 0; f < fc; f++) { - //std::cerr << " f= " << f << std::endl; - CTF ctf = tomogram1.centralCTFs[f]; - // Don't use CTF scale factors, as we will measure SNRs using the FSC! + // Don't use CTF scale factors, as we will measure SNRs using the FSC, and without the Wiener filter we will use doseWeights ctf.scale = 1.0; // Skip any frames that are over-focused, as first-peak calculations below will be invalid. These frames are probably bad anyway.... if (ctf.DeltafU < 100. || ctf.DeltafV < 100.) continue; - // Get frame from Jasenko's stack - MultidimArray frame1(tomogram1.stack.ydim, tomogram1.stack.xdim); - MultidimArray frame2(tomogram1.stack.ydim, tomogram1.stack.xdim); - for (long int y=0; y A(3, 3); + for (int row = 0; row < 3; row++) + for (int col = 0; col < 3; col++) + MAT_ELEM(A, row, col) = tomogram1.projectionMatrices[f](row, col); - // Make square (plus factor 1.4 padding) - frame1.setXmippOrigin(); - frame2.setXmippOrigin(); - frame1.window(FIRST_XMIPP_INDEX(square_box), FIRST_XMIPP_INDEX(square_box), - LAST_XMIPP_INDEX(square_box), LAST_XMIPP_INDEX(square_box)); - frame2.window(FIRST_XMIPP_INDEX(square_box), FIRST_XMIPP_INDEX(square_box), - LAST_XMIPP_INDEX(square_box), LAST_XMIPP_INDEX(square_box)); - - // Mirror the image back out into the padding area to prevent low-resolution artifacts - int first_x = FIRST_XMIPP_INDEX(tomogram1.stack.xdim); - int last_x = LAST_XMIPP_INDEX(tomogram1.stack.xdim); - int first_y = FIRST_XMIPP_INDEX(tomogram1.stack.ydim); - int last_y = LAST_XMIPP_INDEX(tomogram1.stack.ydim); - FOR_ALL_ELEMENTS_IN_ARRAY2D(frame1) + int nr_halves = (fourierWienerFilter) ? 2 : 1; + MultidimArray FT1, FT2; + MultidimArray frame; + for (int ihalf = 0; ihalf < nr_halves; ihalf++) { - int jp = j, ip = i; - bool do_change = false; - if (j < first_x) {jp = 2 * first_x - j; do_change = true;} - else if (j > last_x) {jp = 2 * last_x - j; do_change = true;} - if (i < first_y) {ip = 2 * first_y - i; do_change = true;} - else if (i > last_y) {ip = 2 * last_y - i; do_change = true;} - if (do_change) + + frame.resize(tomogram1.stack.ydim, tomogram1.stack.xdim); + // Get frame from Jasenko's stack + if (ihalf == 0) + { + for (long int y = 0; y < tomogram1.stack.ydim; y++) + for (long int x = 0; x < tomogram1.stack.xdim; x++) + DIRECT_A2D_ELEM(frame, y, x) = tomogram1.stack(x, y, f); + } + else { - A2D_ELEM(frame1, i, j) = A2D_ELEM(frame1, ip, jp); - A2D_ELEM(frame2, i, j) = A2D_ELEM(frame2, ip, jp); + for (long int y = 0; y < tomogram2.stack.ydim; y++) + for (long int x = 0; x < tomogram2.stack.xdim; x++) + DIRECT_A2D_ELEM(frame, y, x) = tomogram2.stack(x, y, f); } - } + // Make square (plus factor 1.4 padding) + frame.setXmippOrigin(); + frame.window(FIRST_XMIPP_INDEX(square_box), FIRST_XMIPP_INDEX(square_box), + LAST_XMIPP_INDEX(square_box), LAST_XMIPP_INDEX(square_box)); + + // Mirror the image back out into the padding area to prevent low-resolution artifacts + int first_x = FIRST_XMIPP_INDEX(tomogram1.stack.xdim); + int last_x = LAST_XMIPP_INDEX(tomogram1.stack.xdim); + int first_y = FIRST_XMIPP_INDEX(tomogram1.stack.ydim); + int last_y = LAST_XMIPP_INDEX(tomogram1.stack.ydim); + FOR_ALL_ELEMENTS_IN_ARRAY2D(frame) + { - // Downscale - if (new_box != square_box) - { - resizeMap(frame1, new_box); - resizeMap(frame2, new_box); - } + // Check whether I need to mirror in the rotated corners from the other side + int jp = j, ip = i; + bool do_change = false; + if (j < first_x) + { + jp = 2 * first_x - j; + do_change = true; + } + else if (j > last_x) + { + jp = 2 * last_x - j; + do_change = true; + } + if (i < first_y) + { + ip = 2 * first_y - i; + do_change = true; + } + else if (i > last_y) + { + ip = 2 * last_y - i; + do_change = true; + } + if (do_change) + { + A2D_ELEM(frame, i, j) = A2D_ELEM(frame, ip, jp); + } - // Get the transformation matrix - const Matrix2D A(3,3); - for (int row= 0; row < 3; row++) - for (int col = 0; col < 3; col++) - MAT_ELEM(A, row, col) = tomogram1.projectionMatrices[f](row, col); + } - RFLOAT xshift, yshift; - m.getValueSafely(EMDL_TOMO_XSHIFT_ANGST, xshift, f); - m.getValueSafely(EMDL_TOMO_YSHIFT_ANGST, yshift, f); + // Downscale + if (new_box != square_box) resizeMap(frame, new_box); - // FT and get SNRs - MultidimArray FT1, FT2; - // Not entirely sure this is necessary, but FFTW transformers have been troublesome with threads in the past... - #pragma omp critical + //Image It; + //It()=frame; + //It.write(outFn + "rec_frame"+ integerToString(f)+".mrc"); + + // FT and get SNRs + // Not entirely sure this is necessary, but FFTW transformers have been troublesome with threads in the past... +#pragma omp critical + { + FourierTransformer transformer; + if (ihalf == 0) transformer.FourierTransform(frame, FT1); + else transformer.FourierTransform(frame, FT2); + }; + } + + MultidimArray FSC, SNR; + if (fourierWienerFilter) { - FourierTransformer transformer; - transformer.FourierTransform(frame1, FT1); - transformer.FourierTransform(frame2, FT2); - }; - MultidimArray FSC; - getFSC(FT1, FT2, FSC); + getFSC(FT1, FT2, FSC); + + // Now that we have the FSC, sum the two halves together + FT1 += FT2; + } - // Now that we have the FSC, sum the two halves together - FT1 += FT2; // Center and shift CenterFFTbySign(FT1); - shiftImageInFourierTransform(FT1, FT1, XSIZE(frame1), -xshift/angpix_spacing, -yshift/angpix_spacing); + shiftImageInFourierTransform(FT1, FT1, XSIZE(frame), -xshift_angst / angpix_spacing, -yshift_angst / angpix_spacing); // Get CTF - MultidimArray Fctf, Ftmp; + MultidimArray Fctf; Fctf.resize(YSIZE(FT1), XSIZE(FT1)); ctf.getFftwImage(Fctf, new_box, new_box, angpix_spacing, false, false, ctf_intact_first_peak, false); - // Calculate the CTF-corrected SNR from the FSC - MultidimArray SNR = getCtfCorrectedSNR(FSC, Fctf, lambda, 0); + //Image Ictf; + //Ictf()=Fctf; + //Ictf.write(outFn + "rec_Ictf_frame"+ integerToString(f)+".mrc"); - FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM2D(FT1) + // Calculate the CTF-corrected SNR from the FSC + if (fourierWienerFilter) { - long int idx = XMIPP_MIN(ROUND(sqrt(ip*ip + jp*jp)), XSIZE(SNR)-1); - // Wiener filter = Sum(CTF*SNR*X) / (Sum(CTF^2*SNR) + 1.) - DIRECT_A2D_ELEM(FT1, i, j) *= DIRECT_MULTIDIM_ELEM(SNR, idx) * DIRECT_A2D_ELEM(Fctf, i, j); - DIRECT_A2D_ELEM(Fctf, i, j) *= DIRECT_MULTIDIM_ELEM(SNR, idx) * DIRECT_A2D_ELEM(Fctf, i, j); + // Wiener filter-type correction + SNR = getCtfCorrectedSNR(FSC, Fctf, lambda, 0); + FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM2D(FT1) + { + long int idx = XMIPP_MIN(ROUND(sqrt(ip*ip + jp*jp)), XSIZE(SNR)-1); + // Wiener filter = Sum(CTF*SNR*X) / (Sum(CTF^2*SNR) + 1.) + DIRECT_A2D_ELEM(FT1, i, j) *= DIRECT_MULTIDIM_ELEM(SNR, idx) * DIRECT_A2D_ELEM(Fctf, i, j); + DIRECT_A2D_ELEM(Fctf, i, j) *= DIRECT_MULTIDIM_ELEM(SNR, idx) * DIRECT_A2D_ELEM(Fctf, i, j); + } + } + else + { + + // Premultiply with the CTF + FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM2D(FT1) + { + DIRECT_A2D_ELEM(FT1, i, j) *= DIRECT_A2D_ELEM(Fctf, i, j); + DIRECT_A2D_ELEM(Fctf, i, j) = 1.; + } } #pragma omp critical @@ -489,15 +594,15 @@ void TomoBackprojectProgram::reconstructOneTomogramFourier(int tomoIndex) BP.set2DFourierTransform(FT1, A, &Fctf); }; - } + } // end for loop over frames Image vol; vol().resize(new_box, new_box, new_box); vol().setXmippOrigin(); - bool do_map = true; MultidimArray tau2(new_box); tau2.initConstant(1.); - BP.reconstruct(vol(), 0, do_map, tau2); + + BP.reconstruct(vol(), 0, fourierWienerFilter, tau2); if (!do_multiple) Log::print("Writing output"); vol().window(FIRST_XMIPP_INDEX(d/spacing), FIRST_XMIPP_INDEX(h/spacing), FIRST_XMIPP_INDEX(w/spacing), @@ -677,7 +782,7 @@ void TomoBackprojectProgram::reconstructOneTomogram(int tomoIndex, bool doEven, if (applyPreWeight) { - stackAct = RealSpaceBackprojection::preWeight(stackAct, projAct, n_threads); + stackAct = RealSpaceBackprojection::preWeight(stackAct, projAct, n_threads); } if (!do_multiple) Log::print("Backprojecting"); diff --git a/src/jaz/tomography/programs/reconstruct_tomogram.h b/src/jaz/tomography/programs/reconstruct_tomogram.h index b26a2eeeb..5867950a9 100644 --- a/src/jaz/tomography/programs/reconstruct_tomogram.h +++ b/src/jaz/tomography/programs/reconstruct_tomogram.h @@ -7,10 +7,12 @@ #include #include #include +#include #include #include #include #include +#include class ReconstructSnrOptimisation : public FastDifferentiableOptimization { @@ -29,26 +31,22 @@ class ReconstructSnrOptimisation : public FastDifferentiableOptimization if (ctf > 0.99) has_reached_one = true; if (has_reached_one && ctf < 0.99 && first_peak < 0) first_peak = n; } + if (first_peak < 0) first_peak = XSIZE(CTF) -1 ; + + // set lambda + lambda = _lambda; + + // vectors ctf2.resize(size); snr.resize(size); FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(CTF) { double ctf = DIRECT_MULTIDIM_ELEM(CTF, n); - VEC_ELEM(ctf2, n) = ctf * ctf; - VEC_ELEM(snr, n) = DIRECT_MULTIDIM_ELEM(SNR, n); - + ctf2[n] = ctf * ctf; + snr[n] = DIRECT_MULTIDIM_ELEM(SNR, n); } - // Set D matrix - D.initIdentity(size); - for (int i=1; i < size - 1; i++) - { - MAT_ELEM(D, i+1, i) = -1; - } - - // set lambda - lambda = _lambda; } double gradAndValue(const std::vector& x, std::vector& gradDest) const; @@ -57,8 +55,7 @@ class ReconstructSnrOptimisation : public FastDifferentiableOptimization int getFirstPeak() {return first_peak;}; private: - Matrix1D ctf2, snr; - Matrix2D D; + std::vector ctf2, snr; double lambda; int first_peak; @@ -74,7 +71,7 @@ class TomoBackprojectProgram int w, h, d; double spacing, angpix_spacing, x0, y0, z0, taperDist, taperFalloff; FileName tomoName, outFn; - bool applyPreWeight, applyWeight, applyCtf, doWiener, zeroDC, FourierCrop, fourierInversion; + bool applyPreWeight, applyWeight, applyCtf, doWiener, zeroDC, FourierCrop, fourierInversion, fourierWienerFilter; bool do_multiple, do_only_unfinished; bool do_even_odd_tomograms, do_2dproj, ctf_intact_first_peak; int centre_2dproj, thickness_2dproj; diff --git a/src/jaz/tomography/programs/subtomo.cpp b/src/jaz/tomography/programs/subtomo.cpp index c992a4ace..bdc105216 100644 --- a/src/jaz/tomography/programs/subtomo.cpp +++ b/src/jaz/tomography/programs/subtomo.cpp @@ -44,9 +44,15 @@ void SubtomoProgram::readBasicParameters(IOParser& parser) int gen_section = parser.addSection("Reconstruction options"); - boxSize = textToInteger(parser.getOption("--b", "Binned projection box size")); + + + boxSize = textToInteger(parser.getOption("--b", "Binned projection box size", "-1")); cropSize = textToInteger(parser.getOption("--crop", "Output box size", "-1")); binning = textToDouble(parser.getOption("--bin", "Binning factor", "1")); + boxSizeAngst = textToDouble(parser.getOption("--box_size_A", "OR: Final (cropped) box size (in Angstrom)", "-1")); + precropSizeAngst = textToDouble(parser.getOption("--precrop_size_A", "OR: Pre-cropped box size for extraction from tilt series (in Angstrom)", "-1")); + binnedSizePixel = textToInteger(parser.getOption("--binned_size_pix", "OR: Binned box size (in pixels)", "-1")); + do_stack2d = parser.checkOption("--stack2d", "Write out 2D stacks of cropped images for each particle, instead of pseudo-subtomograms"); write_multiplicity = parser.checkOption("--multi", "Write out multiplicity volumes"); SNR = textToDouble(parser.getOption("--SNR", "Assumed signal-to-noise ratio (negative means use a heuristic)", "-1")); @@ -95,7 +101,7 @@ void SubtomoProgram::readBasicParameters(IOParser& parser) run_from_GUI = is_under_pipeline_control(); - do_real_subtomo = parser.checkOption("--real_subtomo", "Extract true subtomograms and write out projections of those out as 2D stacks"); + do_real_subtomo = parser.checkOption("--real_subtomo", "Extract true subtomograms and write those out as 3D volumes, together with their 3D CTFs and 2D projections along Z"); } @@ -125,6 +131,31 @@ void SubtomoProgram::readParameters(int argc, char *argv[]) outDir = ZIO::prepareTomoOutputDirectory(outDir, argc, argv); } + +void SubtomoProgram::setBoxsizes(TomogramSet &tomogramSet, bool verb) +{ + if (boxSizeAngst > 0.) + { + double angpix = tomogramSet.getTiltSeriesPixelSize(0); + binning = boxSizeAngst / (binnedSizePixel * angpix); + cropSize = binnedSizePixel; + + if (precropSizeAngst < 0.) + { + boxSize = cropSize; + } + else + { + boxSize = precropSizeAngst / (binning * angpix); + if (boxSize%2 != 0) boxSize++; + } + if (verb) Log::print("Setting boxSize= " + ZIO::itoa(boxSize)+" cropSize= " + ZIO::itoa(cropSize) + " binning= " + ZIO::itoa(binning)); + } + + if (cropSize < 0) cropSize = boxSize; + +} + void SubtomoProgram::run() { TomogramSet tomogramSet(optimisationSet.tomograms, true); @@ -132,8 +163,8 @@ void SubtomoProgram::run() ParticleSet particleSet(optimisationSet.particles, optimisationSet.trajectories, true, &tomogramSet); std::vector > particles = particleSet.splitByTomogram(tomogramSet, true); - if (cropSize < 0) cropSize = boxSize; - + setBoxsizes(tomogramSet); + const long int s2D = boxSize; const long int s3D = cropSize; @@ -239,6 +270,10 @@ void SubtomoProgram::initialise( { Log::print("Slash found in first particle name: not creating subdirectories for each tomogram"); } + if (do_real_subtomo) + { + Log::print("Extracting true subtomogram volumes for relion-3-style averaging in 3D; will also write out projections along Z for 2D classification"); + } } for (int t = 0; t < tc; t++) @@ -304,6 +339,7 @@ void SubtomoProgram::writeParticleSet( Tomogram tomogram = tomogramSet.loadTomogram(t, false); + std::string outProj; if (do_real_subtomo) { RFLOAT tomogram_binning; @@ -324,7 +360,17 @@ void SubtomoProgram::writeParticleSet( else cropSize_tomogram--; } + outProj = outDir + "Subtomograms/" + tomogram.name + "/proj2d.mrcs"; + + } + + int least_tilt_frame; + if (do_real_subtomo) + { + std::vector dummy; + least_tilt_frame = tomogramSet.getImageIndexWithSmallestVisibleTiltAngle(t, dummy); } + for (int p = 0; p < pc; p++) { const ParticleIndex part_id = particles[t][p]; @@ -332,8 +378,6 @@ void SubtomoProgram::writeParticleSet( const std::vector traj = particleSet.getTrajectoryInPixels( part_id, tomogram.frameCount, tomogram.centre, tomogram.optics.pixelSize, !apply_offsets); - //SHWS 24jan2024 only for debugging: // int my_min_frames = (min_frames < 0 ) ? tomogram.frameCount / 2 : min_frames; - //SHWS 24jan2024 only for debugging: // if (tomogram.isVisibleFirstFrames(traj, boxSize / 2.0, my_min_frames)) std::vector isVisible; if (tomogram.getVisibilityMinFramesMaxDose(traj, binning * cropSize / 2.0, maxDose, min_frames, isVisible)) { @@ -347,6 +391,7 @@ void SubtomoProgram::writeParticleSet( std::vector isVisibleInt(isVisible.size(), 0); for (int f = 0; f < tomogram.frameCount; f++) if (isVisible[f]) isVisibleInt[f] = 1; + copy.partTable.setValue(EMDL_TOMO_VISIBLE_FRAMES, isVisibleInt); } @@ -356,14 +401,20 @@ void SubtomoProgram::writeParticleSet( const std::string filenameRoot = getOutputFilename( part_id, t, particleSet, tomogramSet); + std::string outCtf; std::string outData = (do_stack2d) ? filenameRoot + "_stack2d.mrcs" : filenameRoot + "_data.mrc"; std::string outWeight = (do_stack2d) ? "" : filenameRoot + "_weights.mrc"; - copy.setImageFileNames(outData, outWeight, new_id); + if (do_real_subtomo) + { + outData = filenameRoot + "_subtomo.mrc"; + outCtf = filenameRoot + "_ctf.mrc"; + copy.setImageFileNames(outData, outCtf, new_id); + } + const d3Vector pos = particleSet.getPosition(part_id, tomogram.centre, apply_offsets); if (apply_offsets) { - const d3Vector pos = particleSet.getPosition(part_id, tomogram.centre, true); copy.setParticleOffset(new_id, d3Vector(0,0,0)); copy.setParticleCoordDecenteredPixel(new_id, pos, tomogram.centre, tiltSeriesPixelSize); } @@ -385,12 +436,16 @@ void SubtomoProgram::writeParticleSet( if (do_real_subtomo) { // Also make a particle star file for 2D classification - mintilt_idx = tomogramSet.getImageIndexWithSmallestVisibleTiltAngle(t, isVisible); - copy2d.partTable.addObject( copy.partTable.getObject(new_id.value) ); - - std::string outData2d = integerToString(mintilt_idx+1) + "@" + outData; + std::string outData2d = integerToString(p+1) + "@" + outProj; copy2d.partTable.setValue(EMDL_IMAGE_NAME, outData2d); + + // And get the defocus of the untilted image + CTF ctf = tomogram.getCtf(least_tilt_frame, pos); + copy2d.partTable.setValue(EMDL_CTF_DEFOCUSU, ctf.DeltafU); + copy2d.partTable.setValue(EMDL_CTF_DEFOCUSV, ctf.DeltafV); + copy2d.partTable.setValue(EMDL_CTF_DEFOCUS_ANGLE, ctf.azimuthal_angle); + } } else @@ -412,14 +467,9 @@ void SubtomoProgram::writeParticleSet( for (int og = 0; og < copy.numberOfOpticsGroups(); og++) { - bool is_premultiplied = (do_stack2d) ? do_ctf : true; - if (do_real_subtomo) - { - is_premultiplied = false; - copy.optTable.setValue(EMDL_OPTIMISER_DATA_ARE_CTF_CORRECTED, true, og); - } + bool is_premultiplied = (do_stack2d) ? do_ctf : false; copy.optTable.setValue(EMDL_OPTIMISER_DATA_ARE_CTF_PREMULTIPLIED, is_premultiplied, og); - int datadim = (do_stack2d || do_real_subtomo) ? 2 : 3; + int datadim = (do_stack2d) ? 2 : 3; copy.optTable.setValue(EMDL_IMAGE_DIMENSIONALITY, datadim, og); RFLOAT mybinning = (do_real_subtomo) ? real_subtomo_binning : binning; @@ -430,7 +480,6 @@ void SubtomoProgram::writeParticleSet( int mysize = (do_real_subtomo) ? cropSize_tomogram : cropSize; copy.optTable.setValue(EMDL_IMAGE_SIZE, mysize, og); - } if (copy.partTable.containsLabel(EMDL_IMAGE_COORD_X)) copy.partTable.deactivateLabel(EMDL_IMAGE_COORD_X); @@ -451,6 +500,9 @@ void SubtomoProgram::writeParticleSet( copy2d.optTable.clear(); copy2d.optTable = copy.optTable; + for (int og = 0; og < copy.numberOfOpticsGroups(); og++) + copy2d.optTable.setValue(EMDL_IMAGE_DIMENSIONALITY, 2, og); + copy2d.write(outDir + "particles_for_class2d.star"); } @@ -465,16 +517,16 @@ void SubtomoProgram::writeParticleSet( optimisationSet.write(outDir + "optimisation_set.star"); } -BufferedImage SubtomoProgram::extractSubtomogramsAndReProject( +BufferedImage SubtomoProgram::extractRealSubtomograms( ParticleIndex part_id, MultidimArray &recTomo, const Tomogram& tomogram, const ParticleSet &particleSet, - const std::vector &isVisible, RFLOAT tomogram_angpix) + RFLOAT tomogram_angpix, BufferedImage &ctfImage, BufferedImage &projImage) { // get decentered coordinates of the particle (in tilt series pixels) d3Vector pos = particleSet.getPosition(part_id, tomogram.centre, apply_offsets); // convert from tilt series pixel to tomogram pixel - pos *= tomogram.optics.pixelSize / tomogram_angpix; + d3Vector tomopos = pos * (tomogram.optics.pixelSize / tomogram_angpix); const float sign = flip_value ? -1.f : 1.f; @@ -499,9 +551,9 @@ BufferedImage SubtomoProgram::extractSubtomogramsAndReProject( for (long int i= FIRST_XMIPP_INDEX(cropSize_tomogram); i<= LAST_XMIPP_INDEX(cropSize_tomogram); i++) for (long int j= FIRST_XMIPP_INDEX(cropSize_tomogram); j<= LAST_XMIPP_INDEX(cropSize_tomogram); j++) { - int kp = k + pos.z; - int ip = i + pos.y; - int jp = j + pos.x; + int kp = k + tomopos.z; + int ip = i + tomopos.y; + int jp = j + tomopos.x; long int r2 = k*k + i*i + j*j; if (r2 <= r2_max && jp > 0 && jp < XSIZE(recTomo) && @@ -531,9 +583,9 @@ BufferedImage SubtomoProgram::extractSubtomogramsAndReProject( for (long int i= FIRST_XMIPP_INDEX(cropSize_tomogram); i<= LAST_XMIPP_INDEX(cropSize_tomogram); i++) for (long int j= FIRST_XMIPP_INDEX(cropSize_tomogram); j<= LAST_XMIPP_INDEX(cropSize_tomogram); j++) { - int kp = k + pos.z; - int ip = i + pos.y; - int jp = j + pos.x; + int kp = k + tomopos.z; + int ip = i + tomopos.y; + int jp = j + tomopos.x; long int r2 = k*k + i*i + j*j; if (r2 <= r2_max && jp > 0 && jp < XSIZE(recTomo) && @@ -553,44 +605,116 @@ BufferedImage SubtomoProgram::extractSubtomogramsAndReProject( //Image It; //It()= subtom; - //It.write("subtom.spi"); + //It.write("subtom.mrc"); //exit(0); - MultidimArray dummy; - Projector projector(cropSize_tomogram); - projector.computeFourierTransformMap(subtom, dummy); + // Make 2D projection along Z-axis + BufferedImage resultImg; + resultImg.resize(cropSize_tomogram, cropSize_tomogram, cropSize_tomogram); + projImage.resize(cropSize_tomogram, cropSize_tomogram); + ctfImage.resize(cropSize_tomogram / 2 + 1, cropSize_tomogram, cropSize_tomogram); + FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY3D(subtom) + { + projImage(i, j) += DIRECT_A3D_ELEM(subtom, k, i, j); + resultImg(j, i, k) = DIRECT_A3D_ELEM(subtom, k, i, j); + } - MultidimArray img(cropSize_tomogram, cropSize_tomogram); + // Normalise the projected image to zero-mean and unity-stddev + RFLOAT psum = 0., psum2 = 0., pn = 0.; + FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(projImage) + { + psum += projImage(i, j); + psum2 += projImage(i, j) * projImage(i, j); + pn += 1.; + } + psum /= pn; + psum2 = sqrt( (psum2 / pn) - psum * psum); + if (psum2 > 0.) + { + FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(projImage) + { + projImage(i, j) = (projImage(i, j) - psum) / psum2; + } + } + + // Now make 3D-CTF and store in ctfImage + BackProjector backprojector(cropSize_tomogram, 3, "C1", TRILINEAR, + 1, 10, 0, 1.9, 15., 2, true); + backprojector.initZeros(); + + MultidimArray Fw(cropSize_tomogram, cropSize_tomogram/2 + 1), Fctf(cropSize_tomogram, cropSize_tomogram/2 + 1); MultidimArray F2D; - FourierTransformer transformer; - transformer.setReal(img); - transformer.getFourierAlias(F2D); + F2D.initZeros(cropSize_tomogram, cropSize_tomogram/2 + 1); + Fw.initConstant(1.); + + BufferedImage doseWeights = tomogram.computeDoseWeight(cropSize_tomogram, binning); - BufferedImage resultImg(cropSize_tomogram, cropSize_tomogram, tomogram.frameCount); for (int f = 0; f < tomogram.frameCount; f++) { - if (!isVisible[f]) continue; - d4Matrix Aproj = tomogram.projectionMatrices[f]; Matrix2D A(3,3); for (int row= 0; row < 3; row++) for (int col = 0; col < 3; col++) MAT_ELEM(A, row, col) = Aproj(row, col); - // Get the 2D slice out of the 3D Fourier transform - F2D.initZeros(); - projector.get2DFourierTransform(F2D, A); - shiftImageInFourierTransform(F2D, F2D, cropSize_tomogram, cropSize_tomogram/2, cropSize_tomogram/2); - transformer.inverseFourierTransform(); + CTF ctf = tomogram.getCtf(f, pos); + BufferedImage ctfImg(cropSize_tomogram/2 + 1, cropSize_tomogram); + ctf.draw(cropSize_tomogram, cropSize_tomogram, tomogram_angpix, 0, &ctfImg(0, 0, 0)); - FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(img) + FOR_ALL_DIRECT_ELEMENTS_IN_ARRAY2D(Fctf) { - resultImg(j, i, f) = DIRECT_A2D_ELEM(img, i, j); + RFLOAT c = ctfImg(j, i) * doseWeights(j, i, f); + DIRECT_A2D_ELEM(F2D, i, j) = c * c; } + backprojector.set2DFourierTransform(F2D, A, &Fw); + + } + + // Do division in 3D + MultidimArray CTF3D; + CTF3D.initZeros(cropSize_tomogram, cropSize_tomogram, cropSize_tomogram); + CTF3D.setXmippOrigin(); + FOR_ALL_ELEMENTS_IN_ARRAY3D(CTF3D) + { + int jp = j; + int ip = i; + int kp = k; + + // for negative j's: use inverse + if (j < 0) + { + jp = -j; + ip = -i; + kp = -k; + } + + if (jp >= STARTINGX(backprojector.data) && jp <= FINISHINGX(backprojector.data) && + ip >= STARTINGY(backprojector.data) && ip <= FINISHINGY(backprojector.data) && + kp >= STARTINGZ(backprojector.data) && kp <= FINISHINGZ(backprojector.data)) + { + if (A3D_ELEM(backprojector.weight, kp, ip, jp) > 0.01) + { + A3D_ELEM(CTF3D, k, i, j) = sqrt(A3D_ELEM(backprojector.data, kp, ip, jp) / A3D_ELEM(backprojector.weight, kp, ip, jp)); + } + else + { + A3D_ELEM(CTF3D, k, i, j) = 0.; + } + } } + // FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM + for (long int k = 0, kp = 0; k recTomo; @@ -675,7 +799,7 @@ void SubtomoProgram::processTomograms( particleSet.checkTrajectoryLengths(particles[t], fc, "subtomo"); - BufferedImage doseWeights = tomogram.computeDoseWeight(s2D, binning); + BufferedImage doseWeights = tomogram.computeDoseWeight(s2D, binning); BufferedImage noiseWeights; if (do_whiten) @@ -701,6 +825,20 @@ void SubtomoProgram::processTomograms( omp_lock_t writelock; if (do_sum_all) omp_init_lock(&writelock); + BufferedImage proj2d; + std::string outProj; + if (do_real_subtomo) + { + int cropSize_tomogram = ROUND(cropSize * binning * tomogram.optics.pixelSize / tomogram_angpix); + if (cropSize_tomogram%2 != 0) + { + if ( (cropSize * binning * tomogram.optics.pixelSize / tomogram_angpix) - cropSize_tomogram >= 0. ) cropSize_tomogram++; + else cropSize_tomogram--; + } + proj2d.resize(cropSize_tomogram, cropSize_tomogram, pc); + outProj = outDir + "Subtomograms/" + tomogram.name + "/proj2d.mrcs"; + } + #pragma omp parallel for num_threads(outer_thread_num) for (int p = 0; p < pc; p++) { const int th = omp_get_thread_num(); @@ -714,7 +852,13 @@ void SubtomoProgram::processTomograms( const std::string filenameRoot = getOutputFilename( part_id, t, particleSet, tomogramSet); + std::string outCtf; std::string outData = (do_stack2d) ? filenameRoot + "_stack2d.mrcs" : filenameRoot + "_data.mrc"; + if (do_real_subtomo) + { + outData = filenameRoot + "_subtomo.mrc"; + outCtf = filenameRoot + "_ctf.mrc"; + } std::string outWeight = (do_stack2d) ? "" : filenameRoot + "_weights.mrc"; std::string outCTF = filenameRoot + "_CTF2.mrc"; std::string outDiv = filenameRoot + "_div.mrc"; @@ -740,13 +884,15 @@ void SubtomoProgram::processTomograms( if (do_real_subtomo) { - // This will extract the true subtomograms and calculate their FTs in the directions of the tilt series - BufferedImage subtomo_reprojs = extractSubtomogramsAndReProject(part_id, recTomo(), - tomogram, particleSet, isVisible, tomogram_angpix); - BufferedImage visible_reprojs = NewStackHelper::getVisibleSlices(subtomo_reprojs, isVisible); - visible_reprojs.write(outData, tomogram_angpix, write_float16); - + BufferedImage ctfImage, projImage; + BufferedImage subtomo = extractRealSubtomograms(part_id, recTomo(), + tomogram, particleSet, tomogram_angpix, + ctfImage, projImage); + + subtomo.write(outData, tomogram_angpix, write_float16); + ctfImage.write(outCtf, tomogram_angpix, write_float16); + NewStackHelper::insertSliceZ(projImage, proj2d, p); } else { @@ -769,7 +915,8 @@ void SubtomoProgram::processTomograms( d3Matrix A; - if (apply_orientations) { + if (apply_orientations) + { A = particleSet.getMatrix3x3(part_id); } else { A = particleSet.getSubtomogramMatrix(part_id); @@ -777,16 +924,18 @@ void SubtomoProgram::processTomograms( projPart[f] = projCut[f] * d4Matrix(A); - if (do_ctf) { + if (do_ctf) + { const d3Vector pos = particleSet.getPosition(part_id, tomogram.centre, apply_offsets); - CTF ctf = tomogram.getCtf(f, pos); BufferedImage ctfImg(sh2D, s2D); ctf.draw(s2D, s2D, binnedPixelSize, gammaOffset, &ctfImg(0, 0, 0)); // Apply doseWeigths until Nyquist frequency! Otherwise, convolution artefacts when do_circle_crop invFFT/FFT below - for (int y = 0; y < s2D; y++) { - for (int x = 0; x < sh2D; x++) { + for (int y = 0; y < s2D; y++) + { + for (int x = 0; x < sh2D; x++) + { const double c = ctfImg(x, y) * doseWeights(x, y, f); particleStack(x, y, f) *= sign * c; @@ -801,7 +950,8 @@ void SubtomoProgram::processTomograms( aberrationsCache.correctObservations(particleStack, og); - if (do_whiten) { + if (do_whiten) + { particleStack *= noiseWeights; weightStack *= noiseWeights; } @@ -812,28 +962,34 @@ void SubtomoProgram::processTomograms( const int boundary = (boxSize - cropSize) / 2; BufferedImage particlesRS; - if (do_gridding_precorrection || do_circle_crop || do_stack2d) { + if (do_gridding_precorrection || do_circle_crop || do_stack2d) + { particlesRS = NewStackHelper::inverseFourierTransformStack(particleStack); } - if (do_circle_crop) { + if (do_circle_crop) + { const double crop_boundary = do_narrow_circle_crop ? boundary : 0.0; TomoExtraction::cropCircle(particlesRS, crop_boundary, 5, num_threads); } - if (do_gridding_precorrection) { + if (do_gridding_precorrection) + { TomoExtraction::griddingPreCorrect(particlesRS, boundary, num_threads); } - if (do_stack2d) { + if (do_stack2d) + { BufferedImage cropParticlesRS = Padding::unpadCenter2D_full(particlesRS, boundary); BufferedImage cropParticlesRS2 = NewStackHelper::getVisibleSlices(cropParticlesRS, isVisible); cropParticlesRS2.write(outData, binnedPixelSize, write_float16); - } else { + } + else + { if (do_gridding_precorrection || do_circle_crop) { @@ -974,7 +1130,9 @@ void SubtomoProgram::processTomograms( } // end if do_real_subtomo } // end loop particles p - if (verbosity > 0) + if (do_real_subtomo) proj2d.write(outProj, tomogram_angpix, write_float16); + + if (verbosity > 0) { Log::endProgress(); Log::endSection(); // tomogram diff --git a/src/jaz/tomography/programs/subtomo.h b/src/jaz/tomography/programs/subtomo.h index 3402ceaf5..b1ee53dc1 100644 --- a/src/jaz/tomography/programs/subtomo.h +++ b/src/jaz/tomography/programs/subtomo.h @@ -7,7 +7,7 @@ #include #include #include -#include +#include @@ -31,13 +31,16 @@ class SubtomoProgram int boxSize, cropSize, + binnedSizePixel, min_frames, num_threads; double SNR, binning, - taper, + boxSizeAngst, + precropSizeAngst, + taper, env_sigma, cone_slope, cone_sig0, @@ -74,6 +77,7 @@ class SubtomoProgram void readBasicParameters(IOParser& parser); virtual void readParameters(int argc, char *argv[]); + virtual void setBoxsizes(TomogramSet &tomogramSet, bool verb = true); virtual void run(); @@ -85,10 +89,10 @@ class SubtomoProgram const TomogramSet& tomogramSet, bool verbose = true); - BufferedImage extractSubtomogramsAndReProject( + BufferedImage extractRealSubtomograms( ParticleIndex part_id, MultidimArray &recTomo, const Tomogram& tomogram, const ParticleSet &particleSet, - const std::vector &isVisible, RFLOAT tomogram_angpix); + RFLOAT tomogram_angpix, BufferedImage &ctfImage, BufferedImage &projImage); void processTomograms( const std::vector& tomoIndices, diff --git a/src/jaz/tomography/programs/subtomo_mpi.cpp b/src/jaz/tomography/programs/subtomo_mpi.cpp index a7e60c2f0..0f85668eb 100644 --- a/src/jaz/tomography/programs/subtomo_mpi.cpp +++ b/src/jaz/tomography/programs/subtomo_mpi.cpp @@ -75,7 +75,7 @@ void SubtomoProgramMpi::run() ParticleSet particleSet(optimisationSet.particles, optimisationSet.trajectories, node->isLeader(), &tomogramSet); std::vector > particles = particleSet.splitByTomogram(tomogramSet, node->isLeader()); - if (cropSize < 0) cropSize = boxSize; + setBoxsizes(tomogramSet, node->isLeader()); const long int s2D = boxSize; diff --git a/src/jaz/tomography/tomogram_set.cpp b/src/jaz/tomography/tomogram_set.cpp index e19425aa7..913ba083f 100644 --- a/src/jaz/tomography/tomogram_set.cpp +++ b/src/jaz/tomography/tomogram_set.cpp @@ -151,7 +151,7 @@ void TomogramSet::removeTomogram(std::string tomogramName) } Tomogram TomogramSet::loadTomogram(int index, bool loadImageData, bool loadEvenFramesOnly, bool loadOddFramesOnly, - int _w0, int _h0, int _d0) const //Set loadEven/OddFramesOnly to True to loadImageData from rlnTomoMicrographNameEven/Odd rather than rlnMicrographName + int _w0, int _h0, int _d0, bool ignore_tomo_size) const //Set loadEven/OddFramesOnly to True to loadImageData from rlnTomoMicrographNameEven/Odd rather than rlnMicrographName { Tomogram out; @@ -175,11 +175,9 @@ Tomogram TomogramSet::loadTomogram(int index, bool loadImageData, bool loadEvenF globalTable.getValueSafely(EMDL_TOMO_SIZE_Y, out.h0, index); globalTable.getValueSafely(EMDL_TOMO_SIZE_Z, out.d0, index); } - else + else if (!ignore_tomo_size) { - out.w0 = -999; - out.h0 = -999; - out.d0 = -999; + REPORT_ERROR("ERROR loadTomogram: tomogram sizes have not been set for tomogram " + tomoName); } // Select only a subset of the tilt series images with the lowest dose @@ -690,18 +688,18 @@ int TomogramSet::getImageIndexWithSmallestVisibleTiltAngle(int index, std::vecto RFLOAT mindiff = 999.; int nr_idx = tomogramTables[index].numberOfObjects(); - if (nr_idx != isVisible.size()) REPORT_ERROR("BUG: incofrrect number of elements in isVisible vector..."); + if ( isVisible.size() > 0 && nr_idx != isVisible.size()) REPORT_ERROR("BUG: incofrrect number of elements in isVisible vector..."); int nr_invisible = 0; for (int idx = 0; idx < nr_idx; idx++) { - if (!isVisible[idx]) + if (isVisible.size() > 0 && !isVisible[idx]) { nr_invisible++; continue; } RFLOAT tilt; - tomogramTables[index].getValue(EMDL_TOMO_NOMINAL_TILT_STAGE_ANGLE, tilt, idx); + tomogramTables[index].getValue(EMDL_TOMO_YTILT, tilt, idx); if (fabs(tilt) < mindiff) { mindiff = fabs(tilt); @@ -769,6 +767,10 @@ void TomogramSet::generateSingleMetaDataTable(MetaDataTable &MDout, ObservationM MDout.clear(); for (long int t = 0; t < tomogramTables.size(); t++) { + + //Make sure we order tilt series on pre-exposure, as we'll also do this when combining everything at the end + tomogramTables[t].newSort(EMDL_MICROGRAPH_PRE_EXPOSURE); + // Store all the necessary optics stuff in an opticsGroup per tomogram RFLOAT moviePixelSize, voltage, Cs, Q0; std::string tomo_name = getTomogramName(t); diff --git a/src/jaz/tomography/tomogram_set.h b/src/jaz/tomography/tomogram_set.h index b3d16962c..391dc1e59 100644 --- a/src/jaz/tomography/tomogram_set.h +++ b/src/jaz/tomography/tomogram_set.h @@ -27,7 +27,7 @@ class TomogramSet void removeTomogram(std::string tomogramName); // If max_dose is positive, then only images with cumulativeDose less than or equal to max_dose will be loaded. - Tomogram loadTomogram(int index, bool loadImageData, bool loadEvenFrames = false, bool loadOddFrames = false, int w0 = -999, int h0 =-999, int d0 = -999 ) const; + Tomogram loadTomogram(int index, bool loadImageData, bool loadEvenFrames = false, bool loadOddFrames = false, int w0 = -999, int h0 =-999, int d0 = -999, bool ignore_tomo_size = false) const; int size() const; void setProjectionAngles(int tomogramIndex, int frame, RFLOAT xtilt, RFLOAT ytilt, RFLOAT zrot, RFLOAT xshift_angst, RFLOAT yshift_angst); diff --git a/src/local_symmetry.cpp b/src/local_symmetry.cpp index b5b769bb1..021a8bd0d 100644 --- a/src/local_symmetry.cpp +++ b/src/local_symmetry.cpp @@ -355,12 +355,14 @@ void readRelionFormatMasksAndOperators( FileName fn_info, std::vector& fn_mask_list, std::vector > >& ops, + std::vector >& weights, RFLOAT angpix, bool verb) { MetaDataTable MD; FileName fn_mask; std::vector > dummy; + std::vector dummyw; Matrix1D op, op_i; bool is_maskname_found = false; RFLOAT aa = 0., bb = 0., gg = 0., dx = 0., dy = 0., dz = 0.; @@ -368,8 +370,10 @@ void readRelionFormatMasksAndOperators( // Initialisation fn_mask_list.clear(); ops.clear(); + weights.clear(); MD.clear(); dummy.clear(); + dummyw.clear(); op.clear(); op_i.clear(); @@ -417,7 +421,8 @@ void readRelionFormatMasksAndOperators( op_i.initZeros(NR_LOCALSYM_PARAMETERS); for (int id_mask = 0; id_mask < fn_mask_list.size(); id_mask++) { - dummy.clear(); + dummy.clear(); + dummyw.clear(); if (verb) { std::cout << " * Mask #" << (id_mask + 1) << " = " << fn_mask_list[id_mask] << std::endl; @@ -441,7 +446,11 @@ void readRelionFormatMasksAndOperators( MD.getValue(EMDL_ORIENT_ORIGIN_Y_ANGSTROM, dy); MD.getValue(EMDL_ORIENT_ORIGIN_Z_ANGSTROM, dz); - // Re-calculate angles so that they follow the conventions in RELION! + // Get weight if present + RFLOAT weight = 1.; + if (MD.containsLabel(EMDL_LOCSYM_WEIGHT)) MD.getValue(EMDL_LOCSYM_WEIGHT, weight); + + // Re-calculate angles so that they follow the conventions in RELION! standardiseEulerAngles(aa, bb, gg, aa, bb, gg); Localsym_composeOperator(op, aa, bb, gg, dx, dy, dz); @@ -460,11 +469,13 @@ void readRelionFormatMasksAndOperators( // Push back the operator dummy.push_back(op); + dummyw.push_back(weight); } if (dummy.size() < 1) REPORT_ERROR("ERROR: Please provide at least one non-identical operator for mask file " + fn_mask_list[id_mask] + " !"); - ops.push_back(dummy); + ops.push_back(dummy); + weights.push_back(dummyw); } // Verify mask filenames and operators (detect duplication) @@ -1151,6 +1162,7 @@ void applyLocalSymmetry(MultidimArray& sym_map, const MultidimArray& ori_map, const std::vector fn_masks, const std::vector > > ops, + const std::vector > weights, RFLOAT radius, RFLOAT cosine_width_pix) { @@ -1186,6 +1198,7 @@ void applyLocalSymmetry(MultidimArray& sym_map, for (int imask = 0; imask < fn_masks.size(); imask++) { vol1 = ori_map; + RFLOAT sumweight = 1.; // Loop over all operators for this mask RFLOAT nr_ops = RFLOAT(ops[imask].size()); @@ -1207,7 +1220,11 @@ void applyLocalSymmetry(MultidimArray& sym_map, translate(ori_map, vol2, trans_vec, DONT_WRAP); selfApplyGeometry(vol2, op_mat, IS_NOT_INV, DONT_WRAP); #endif - vol1 += vol2; + if (weights[imask][iop] > 0.) + { + vol1 += weights[imask][iop] * vol2; + sumweight += weights[imask][iop]; + } } // Load this mask @@ -1231,7 +1248,8 @@ void applyLocalSymmetry(MultidimArray& sym_map, // This voxel is inside the mask if (mask_val > (XMIPP_EQUAL_ACCURACY)) { - DIRECT_A3D_ELEM(vol1, k, i, j) *= mask_val / (nr_ops + 1.); // "mask-weighted sum" - wsum + //DIRECT_A3D_ELEM(vol1, k, i, j) *= mask_val / (nr_ops + 1.); // "mask-weighted sum" - wsum + DIRECT_A3D_ELEM(vol1, k, i, j) *= mask_val / sumweight; // "mask-weighted sum" - wsum } else { @@ -1329,11 +1347,12 @@ void applyLocalSymmetry( MultidimArray& map, const std::vector fn_masks, const std::vector > > ops, + const std::vector > weights, RFLOAT radius, RFLOAT cosine_width_pix) { MultidimArray vol; - applyLocalSymmetry(vol, map, fn_masks, ops, radius, cosine_width_pix); + applyLocalSymmetry(vol, map, fn_masks, ops, weights, radius, cosine_width_pix); map = vol; } @@ -2212,6 +2231,7 @@ void local_symmetry_parameters::run() FileName fn_parsed, fn_tmp; std::vector fn_mask_list; std::vector > > op_list; + std::vector > weights; fn_mask_list.clear(); op_list.clear(); @@ -2251,13 +2271,16 @@ void local_symmetry_parameters::run() // Parse mask info file if (fn_info_in.getExtension() == "star") { - readRelionFormatMasksAndOperators(fn_info_in, fn_mask_list, op_list, angpix_image, do_verb); + readRelionFormatMasksAndOperators(fn_info_in, fn_mask_list, op_list, weights, angpix_image, do_verb); } else { fn_parsed = fn_info_in + std::string(".") + fn_info_in_parsed_ext; parseDMFormatMasksAndOperators(fn_info_in, fn_parsed); readDMFormatMasksAndOperators(fn_parsed, fn_mask_list, op_list, angpix_image, do_verb); + weights.resize(op_list.size()); + for (int i=0; i < op_list.size(); i++) + weights[i].resize(op_list[i].size(), 1.); } unsym_map.clear(); @@ -2267,7 +2290,7 @@ void local_symmetry_parameters::run() int box_size = ((XSIZE(unsym_map())) < (YSIZE(unsym_map()))) ? (XSIZE(unsym_map())) : (YSIZE(unsym_map())); box_size = (box_size < (ZSIZE(unsym_map()))) ? box_size : (ZSIZE(unsym_map())); - applyLocalSymmetry(sym_map(), unsym_map(), fn_mask_list, op_list, (RFLOAT(box_size) * sphere_percentage) / 2., width_edge_pix); + applyLocalSymmetry(sym_map(), unsym_map(), fn_mask_list, op_list, weights, (RFLOAT(box_size) * sphere_percentage) / 2., width_edge_pix); sym_map().setXmippOrigin(); sym_map.setSamplingRateInHeader(angpix_image, angpix_image, angpix_image); @@ -2296,14 +2319,17 @@ void local_symmetry_parameters::run() // Parse mask info file if (fn_info_in.getExtension() == "star") { - readRelionFormatMasksAndOperators(fn_info_in, fn_mask_list, op_list, angpix_image, do_verb); + readRelionFormatMasksAndOperators(fn_info_in, fn_mask_list, op_list, weights, angpix_image, do_verb); } else { fn_parsed = fn_info_in + std::string(".") + fn_info_in_parsed_ext; parseDMFormatMasksAndOperators(fn_info_in, fn_parsed); readDMFormatMasksAndOperators(fn_parsed, fn_mask_list, op_list, angpix_image, do_verb); - } + weights.resize(op_list.size()); + for (int i=0; i < op_list.size(); i++) + weights[i].resize(op_list[i].size(), 1.); + } map_in.clear(); //map_out.clear(); @@ -2408,7 +2434,7 @@ void local_symmetry_parameters::run() { if (fn_info_in.getExtension() == "star") { - readRelionFormatMasksAndOperators(fn_info_in, fn_mask_list, op_list, angpix_image, true); + readRelionFormatMasksAndOperators(fn_info_in, fn_mask_list, op_list, weights, angpix_image, true); } else { diff --git a/src/local_symmetry.h b/src/local_symmetry.h index 6c63a2bad..f08b4cbaa 100644 --- a/src/local_symmetry.h +++ b/src/local_symmetry.h @@ -136,6 +136,7 @@ void readRelionFormatMasksAndOperators( FileName fn_info, std::vector& fn_mask_list, std::vector > >& ops, + std::vector >& weights, RFLOAT angpix = 1., bool verb = false); @@ -183,6 +184,7 @@ void applyLocalSymmetry( const MultidimArray& ori_map, const std::vector fn_masks, const std::vector > > ops, + const std::vector > weights, RFLOAT radius = -1., RFLOAT cosine_width_pix = 5.); @@ -190,6 +192,7 @@ void applyLocalSymmetry( MultidimArray& map, const std::vector fn_masks, const std::vector > > ops, + const std::vector > weights, RFLOAT radius = -1., RFLOAT cosine_width_pix = 5.); diff --git a/src/local_symmetry_mpi.cpp b/src/local_symmetry_mpi.cpp index 2e7f7ba33..e8ae91abd 100644 --- a/src/local_symmetry_mpi.cpp +++ b/src/local_symmetry_mpi.cpp @@ -29,6 +29,7 @@ void local_symmetry_parameters_mpi::run() Matrix1D op_search_ranges, op, com0_int, com1_int, com1_float, com1_diff, vecR3; std::vector fn_mask_list; std::vector > > op_list; + std::vector > weights; std::vector > op_mask_list; std::vector > op_samplings, op_samplings_batch; MultidimArray op_samplings_batch_packed, src_cropped, dest_cropped, mask_cropped; @@ -39,6 +40,7 @@ void local_symmetry_parameters_mpi::run() op_search_ranges.clear(); op.clear(); com0_int.clear(); com1_int.clear(); com1_float.clear(); com1_diff.clear(); vecR3.clear(); fn_mask_list.clear(); op_list.clear(); + weights.clear(); op_mask_list.clear(); op_samplings.clear(); op_samplings_batch.clear(); op_samplings_batch_packed.clear(); src_cropped.clear(); dest_cropped.clear(); mask_cropped.clear(); @@ -107,14 +109,16 @@ void local_symmetry_parameters_mpi::run() { if (fn_info_in.getExtension() == "star") { - readRelionFormatMasksAndOperators(fn_info_in, fn_mask_list, op_list, angpix_image, true); + readRelionFormatMasksAndOperators(fn_info_in, fn_mask_list, op_list, weights, angpix_image, true); } else { fn_parsed = fn_info_in + std::string(".") + fn_info_in_parsed_ext; parseDMFormatMasksAndOperators(fn_info_in, fn_parsed); readDMFormatMasksAndOperators(fn_parsed, fn_mask_list, op_list, angpix_image, true); - } + for (int i=0; i < op_list.size(); i++) + weights[i].resize(op_list[i].size(), 1.); + } } else { diff --git a/src/macros.h b/src/macros.h index 835dedc14..6afeeb5ae 100644 --- a/src/macros.h +++ b/src/macros.h @@ -45,7 +45,7 @@ #ifndef MACROS_H #define MACROS_H -#define RELION_SHORT_VERSION "5.0.1" +#define RELION_SHORT_VERSION "5.1.0" extern const char *g_RELION_VERSION; #include diff --git a/src/manualpicker.cpp b/src/manualpicker.cpp index 882437b95..c3e21c39d 100644 --- a/src/manualpicker.cpp +++ b/src/manualpicker.cpp @@ -24,6 +24,7 @@ std::vector imics; std::vector global_fn_mics; std::vector global_fn_picks; std::vector global_fn_ctfs; +std::vector global_fn_foms; std::vector selected; std::vector number_picked; std::vector viewmic_buttons; @@ -37,6 +38,7 @@ int last_ctf_viewed; bool global_has_ctf; bool global_pick_startend; +bool global_pick_lines; RFLOAT global_angpix; RFLOAT global_coord_scale; RFLOAT global_lowpass; @@ -143,12 +145,14 @@ void cb_viewmic(Fl_Widget* w, void* data) command += " --angpix " + floatToString(global_angpix); if (global_pick_startend) command += " --pick_start_end "; + else if (global_pick_lines) + command += " --pick_lines "; if (fabs(global_minimum_fom + 9999.) > 1e-6) { command += " --minimum_pick_fom " + floatToString(global_minimum_fom); } - if (global_color_label != "") + if (global_fn_foms.size() ==0 & global_color_label != "") { command += " --color_label " + global_color_label; command += " --blue " + floatToString(global_blue_value); @@ -156,6 +160,12 @@ void cb_viewmic(Fl_Widget* w, void* data) if (global_fn_color != "") command += " --color_star " + global_fn_color; } + if (global_fn_foms.size() > 0) + { + command += " --fom_img " + global_fn_foms[mymic]; + command += " --fom_min " + floatToString(global_blue_value); + command += " --fom_max " + floatToString(global_red_value); + } command += " &"; //std::cerr << " command= " << command << std::endl; @@ -187,7 +197,7 @@ void cb_viewctf(Fl_Widget* w, void* data) command = "relion_display --i " + global_fn_ctfs[imic]; command += " --scale " + floatToString(global_ctfscale); command += " --sigma_contrast " + floatToString(global_ctfsigma); - command += " &"; + command += " &"; int res = system(command.c_str()); last_ctf_viewed = imic; @@ -273,7 +283,7 @@ int manualpickerGuiWindow::fill() global_has_ctf = MDin.containsLabel(EMDL_CTF_IMAGE); - FileName fn_mic, fn_pick, fn_ctf; + FileName fn_mic, fn_pick, fn_ctf, fn_fom; int ystep = 35; imics.clear(); @@ -286,6 +296,7 @@ int manualpickerGuiWindow::fill() global_fn_mics.clear(); global_fn_picks.clear(); global_fn_ctfs.clear(); + global_fn_foms.clear(); text_displays.clear(); viewmic_buttons.clear(); viewctf_buttons.clear(); @@ -311,6 +322,12 @@ int manualpickerGuiWindow::fill() } global_fn_picks.push_back(fn_pick); + if (MDin.containsLabel(EMDL_MICROGRAPH_AUTOPICK_FOM)) + { + MDin.getValue(EMDL_MICROGRAPH_AUTOPICK_FOM, fn_fom); + global_fn_foms.push_back(fn_fom); + } + Fl_Check_Button *mycheck = new Fl_Check_Button(4, current_y, ystep-8, ystep-8, ""); mycheck->callback(cb_selectmic, &(imics[imic])); mycheck->value(1); @@ -458,7 +475,8 @@ void manualpickerGuiWindow::writeOutputStarfiles(bool verb) if (!do_allow_save) return; MDcoords.clear(); - MetaDataTable MDmics, MDselect; + MDcoords.setName("coordinate_files"); + MetaDataTable MDmics, MDselect; int c = 0; for (int imic = 0; imic < selected.size(); imic++) { @@ -496,10 +514,23 @@ void manualpickerGuiWindow::writeOutputStarfiles(bool verb) FileName fn_select = global_fn_odir + "local_selection.star"; MDselect.write(fn_select); - FileName fn_coords = global_fn_odir + global_pickname + ".star"; - MDcoords.setName("coordinate_files"); - MDcoords.write(fn_coords); - if (verb) std::cout << " Saved list with " << c << " coordinate files in: " << fn_coords << std::endl; + + std::string picktype("particles"); + if (global_pick_lines) picktype = "lines"; + else if (global_pick_startend) picktype = "startend"; + MetaDataTable MDhead; + MDhead.setName("general"); + MDhead.setIsList(true); + MDhead.addObject(); + MDhead.setValue(EMDL_MICROGRAPH_PICKTYPE, picktype); + + std::vector MDins; + MDins.push_back(MDhead); + MDins.push_back(MDcoords); + FileName fn_coords = global_fn_odir + global_pickname + ".star"; + writeMultipleTablesToStar(MDins, fn_coords); + + if (verb) std::cout << " Saved list with " << c << " coordinate files in: " << fn_coords << std::endl; } void manualpickerGuiWindow::cb_menubar_save(Fl_Widget* w, void* v) @@ -693,6 +724,7 @@ void ManualPicker::read(int argc, char **argv) global_coord_scale = textToFloat(parser.getOption("--coord_scale", "Scale coordinates before display", "1.0")); global_particle_diameter = textToFloat(parser.getOption("--particle_diameter", "Diameter of the circles that will be drawn around each picked particle (in Angstroms)")); global_pick_startend = parser.checkOption("--pick_start_end", "Pick start-end coordinates of helices"); + global_pick_lines = parser.checkOption("--pick_lines", "Pick lines for curvy helices"); do_allow_save = parser.checkOption("--allow_save", "Allow saving of the selected micrographs"); do_fast_save = parser.checkOption("--fast_save", "Save a default selection of all micrographs immediately"); global_nr_simultaneous = textToInteger(parser.getOption("--open_simultaneous", "Open this many of the next micrographs simultaneously when pressing CTRL and a Pick button", "10")); @@ -728,7 +760,40 @@ void ManualPicker::initialise() { if (fn_in.isStarFile()) { - // First try 2-column list of coordinate files as in relion-3.2+ + MetaDataTable MDhead; + if (MDhead.read(fn_in, "general")) + { + std::string picktype; + MDhead.getValue(EMDL_MICROGRAPH_PICKTYPE, picktype); + if (picktype == "particles") + { + if (global_pick_startend || global_pick_lines) + std::cerr << "WARNING: coordinate file states these are particles, ignoring --from_startend or --from_lines "<< std::endl; + global_pick_startend = global_pick_lines = false; + } + else if (picktype == "startend") + { + if (global_pick_lines) + std::cerr << "WARNING: coordinate file states these are startend, ignoring --from_lines "<< std::endl; + global_pick_startend = true; + global_pick_lines = false; + } + else if (picktype == "lines") + { + if (global_pick_startend) + std::cerr << "WARNING: coordinate file states these are lines, ignoring --from_startend "<< std::endl; + global_pick_startend = false; + global_pick_lines = true; + } + else + { + REPORT_ERROR("ERROR: unrecognised micrograph picktype from the general table of the coordinate file"); + } + + } + + + // First try 2-column list of coordinate files as in relion-3.2+ MDin.read(fn_in, "coordinate_files"); if (MDin.numberOfObjects() > 0) { diff --git a/src/metadata_label.h b/src/metadata_label.h index 9c37aec7d..9168c4ff7 100644 --- a/src/metadata_label.h +++ b/src/metadata_label.h @@ -156,7 +156,9 @@ enum EMDLabel EMDL_CTF_ENERGY_LOSS, ///< Energy loss EMDL_CTF_FOM, ///< ctffind FOM (CC) for quality of CTF-fit EMDL_CTF_IMAGE, ///< name of an image describing the CTF model - EMDL_CTF_ICERINGDENSITY, ///< sum of image power in ice ring + EMDL_CTF_ICERINGDENSITY, ///< sum of image power in ice ring + EMDL_CTF_ICERINGPOWERFRACTION, ///< fraction of power in ice ring, relative to above and below bands + EMDL_CTF_ICERINGKURTOSIS, ///< kurtosis of power values in ice ring EMDL_CTF_LENS_STABILITY, ///< Lens stability EMDL_CTF_MAGNIFICATION, ///< Magnification used for CTF-determination (deprecated) EMDL_CTF_PHASESHIFT, ///< Phase-shift from a phase plate @@ -230,6 +232,8 @@ enum EMDLabel EMDL_JOBOPTION_DIRECTORY, EMDL_JOBOPTION_MENUOPTIONS, + EMDL_LOCSYM_WEIGHT, + EMDL_MATRIX_1_1, EMDL_MATRIX_1_2, EMDL_MATRIX_1_3, @@ -266,6 +270,11 @@ enum EMDLabel EMDL_MICROGRAPH_END_FRAME, EMDL_MICROGRAPH_SHIFT_X, EMDL_MICROGRAPH_SHIFT_Y, + EMDL_MICROGRAPH_AUTOPICK_FOM, + EMDL_MICROGRAPH_AUTOPICK_PSI, + EMDL_MICROGRAPH_PICKTYPE, + EMDL_MICROGRAPH_SCORE_KURTOSIS, + EMDL_MICROGRAPH_SCORE_SKEWNESS, EMDL_MICROGRAPH_MOTION_COEFFS_IDX, EMDL_MICROGRAPH_MOTION_COEFF, EMDL_MICROGRAPH_EER_UPSAMPLING, @@ -884,7 +893,9 @@ class StaticInitialization EMDL::addLabel(EMDL_CTF_ENERGY_LOSS, EMDL_DOUBLE, "rlnEnergyLoss", "Energy loss (in eV)"); EMDL::addLabel(EMDL_CTF_FOM, EMDL_DOUBLE, "rlnCtfFigureOfMerit", "Figure of merit for the fit of the CTF (not used inside relion_refine)"); EMDL::addLabel(EMDL_CTF_IMAGE, EMDL_STRING, "rlnCtfImage", "Name of an image with all CTF values"); - EMDL::addLabel(EMDL_CTF_ICERINGDENSITY, EMDL_DOUBLE, "rlnCtfIceRingDensity", "Power of the image in the ice ring frequency range (0.25-0.28 A-1)"); + EMDL::addLabel(EMDL_CTF_ICERINGDENSITY, EMDL_DOUBLE, "rlnCtfIceRingDensity", "Power of the image in the ice ring frequency range (0.25-0.28 A-1)"); + EMDL::addLabel(EMDL_CTF_ICERINGPOWERFRACTION, EMDL_DOUBLE, "rlnCtfIceRingPowerFraction", "Fraction of power in ice ring, relative to above and below resolution bands"); + EMDL::addLabel(EMDL_CTF_ICERINGKURTOSIS, EMDL_DOUBLE, "rlnCtfIceRingKurtosis", "Kurtosis of power values within the ice ring"); EMDL::addLabel(EMDL_CTF_LENS_STABILITY, EMDL_DOUBLE, "rlnLensStability", "Lens stability (in ppm)"); EMDL::addLabel(EMDL_CTF_MAGNIFICATION, EMDL_DOUBLE, "rlnMagnification", "Magnification at the detector (in times)"); EMDL::addLabel(EMDL_CTF_PHASESHIFT, EMDL_DOUBLE, "rlnPhaseShift", "Phase-shift from a phase-plate (in degrees)"); @@ -960,8 +971,10 @@ class StaticInitialization EMDL::addLabel(EMDL_JOBOPTION_DIRECTORY, EMDL_STRING, "rlnJobOptionDirectoryDefault", "Default directory for file browser of a joboption"); EMDL::addLabel(EMDL_JOBOPTION_MENUOPTIONS, EMDL_STRING, "rlnJobOptionMenuOptions", "Options for pull-down menu"); - EMDL::addLabel(EMDL_MATRIX_1_1, EMDL_DOUBLE, "rlnMatrix_1_1", "Matrix element (1,1) of a 3x3 matrix"); - EMDL::addLabel(EMDL_MATRIX_1_2, EMDL_DOUBLE, "rlnMatrix_1_2", "Matrix element (1,2) of a 3x3 matrix"); + EMDL::addLabel(EMDL_LOCSYM_WEIGHT, EMDL_DOUBLE, "rlnLocalSymmetryWeight", "Relative weight for local symmetry operator (main one is 1)"); + + EMDL::addLabel(EMDL_MATRIX_1_1, EMDL_DOUBLE, "rlnMatrix_1_1", "Matrix element (1,1) of a 3x3 matrix"); + EMDL::addLabel(EMDL_MATRIX_1_2, EMDL_DOUBLE, "rlnMatrix_1_2", "Matrix element (1,2) of a 3x3 matrix"); EMDL::addLabel(EMDL_MATRIX_1_3, EMDL_DOUBLE, "rlnMatrix_1_3", "Matrix element (1,3) of a 3x3 matrix"); EMDL::addLabel(EMDL_MATRIX_2_1, EMDL_DOUBLE, "rlnMatrix_2_1", "Matrix element (2,1) of a 3x3 matrix"); EMDL::addLabel(EMDL_MATRIX_2_2, EMDL_DOUBLE, "rlnMatrix_2_2", "Matrix element (2,1) of a 3x3 matrix"); @@ -996,7 +1009,12 @@ class StaticInitialization EMDL::addLabel(EMDL_MICROGRAPH_END_FRAME, EMDL_INT, "rlnMicrographEndFrame", "End frame of a motion model"); EMDL::addLabel(EMDL_MICROGRAPH_SHIFT_X, EMDL_DOUBLE, "rlnMicrographShiftX", "X shift of a (patch of) micrograph"); EMDL::addLabel(EMDL_MICROGRAPH_SHIFT_Y, EMDL_DOUBLE, "rlnMicrographShiftY", "Y shift of a (patch of) micrograph"); - EMDL::addLabel(EMDL_MICROGRAPH_MOTION_COEFFS_IDX, EMDL_INT, "rlnMotionModelCoeffsIdx", "Index of a coefficient of a motion model"); + EMDL::addLabel(EMDL_MICROGRAPH_AUTOPICK_FOM, EMDL_STRING, "rlnMicrographFomImage", "Filename of the FOM image of micrograph autopicking "); + EMDL::addLabel(EMDL_MICROGRAPH_AUTOPICK_PSI, EMDL_STRING, "rlnMicrographPsiImage", "Filename of the PSI image of micrograph autopicking"); + EMDL::addLabel(EMDL_MICROGRAPH_PICKTYPE, EMDL_STRING, "rlnMicrographPickType", "Type of micrograph coordinates (particles, startend or lines)"); + EMDL::addLabel(EMDL_MICROGRAPH_SCORE_KURTOSIS, EMDL_DOUBLE, "rlnMicrographScoreKurtosis", "(Excess) kurtosis in micrograph autopick FOM scores"); + EMDL::addLabel(EMDL_MICROGRAPH_SCORE_SKEWNESS, EMDL_DOUBLE, "rlnMicrographScoreSkewness", "Skewness in micrograph autopick FOM scores"); + EMDL::addLabel(EMDL_MICROGRAPH_MOTION_COEFFS_IDX, EMDL_INT, "rlnMotionModelCoeffsIdx", "Index of a coefficient of a motion model"); EMDL::addLabel(EMDL_MICROGRAPH_MOTION_COEFF, EMDL_DOUBLE, "rlnMotionModelCoeff", "A coefficient of a motion model"); EMDL::addLabel(EMDL_MICROGRAPH_EER_UPSAMPLING, EMDL_INT, "rlnEERUpsampling", "EER upsampling ratio (1 = physical, 2 = 2x super-resolution)"); EMDL::addLabel(EMDL_MICROGRAPH_EER_GROUPING, EMDL_INT, "rlnEERGrouping", "The number of hardware frames to group"); diff --git a/src/metadata_table.cpp b/src/metadata_table.cpp index 0818bf4d9..78da79024 100644 --- a/src/metadata_table.cpp +++ b/src/metadata_table.cpp @@ -2217,4 +2217,28 @@ MetaDataTable removeDuplicatedParticles(MetaDataTable &MDin, EMDLabel mic_label, return MDout; } +void writeMultipleTablesToStar(std::vector &MDins, FileName fn_out) +{ + + // Write to temporary file first + FileName fn_tmp = fn_out + ".tmp"; + + std::ofstream fh; + fh.open((fn_tmp).c_str(), std::ios::out); + if (!fh) + REPORT_ERROR( (std::string)"MetaDataTable::write: cannot write to file: " + fn_tmp); + + // Write all the tables + for (int i = 0; i < MDins.size(); i++) + { + MDins[i].write(fh); + } + + fh.close(); + + // Rename to prevent errors with programs in pipeliner reading in incomplete STAR files + std::rename(fn_tmp.c_str(), fn_out.c_str()); + + +} diff --git a/src/metadata_table.h b/src/metadata_table.h index 78c94aa26..c528756e6 100644 --- a/src/metadata_table.h +++ b/src/metadata_table.h @@ -390,6 +390,9 @@ MetaDataTable subsetMetaDataTable(MetaDataTable &MDin, EMDLabel label, std::stri // OriginX/Y are multiplied by origin_scale before added to CoordinateX/Y to compensate for down-sampling MetaDataTable removeDuplicatedParticles(MetaDataTable &MDin, EMDLabel mic_label, RFLOAT threshold, RFLOAT origin_scale=1.0, FileName fn_removed="", bool verb=true); +// Write multiple tables into a star file, with writing to .tmp file for file completion checking in pipeliner +void writeMultipleTablesToStar(std::vector &MDins, FileName fn_out); + // This flag should be enabled via "cmake -DMDT_TYPE_CHECK=ON" #ifdef METADATA_TABLE_TYPE_CHECK //#pragma message("typecheck enabled") diff --git a/src/ml_optimiser.cpp b/src/ml_optimiser.cpp index fb33d84f8..1179c6374 100644 --- a/src/ml_optimiser.cpp +++ b/src/ml_optimiser.cpp @@ -44,19 +44,19 @@ #include "src/error.h" #include "src/ml_optimiser.h" #ifdef _CUDA_ENABLED -#include "src/acc/cuda/cuda_ml_optimiser.h" -#ifdef CUDA_PROFILING -#include -#include -#endif + #include "src/acc/cuda/cuda_ml_optimiser.h" + #ifdef CUDA_PROFILING + #include + #include + #endif #elif _HIP_ENABLED -#include "src/acc/hip/hip_ml_optimiser.h" -#include + #include "src/acc/hip/hip_ml_optimiser.h" + #include #elif _SYCL_ENABLED - #include - #include - #include - #include + #include + #include + #include + #include #include "src/acc/sycl/sycl_ml_optimiser.h" #elif ALTCPU #include @@ -431,6 +431,11 @@ void MlOptimiser::parseContinue(int argc, char **argv) else do_center_classes = false; + if (parser.checkOption("--keep_priors_fixed", "Keep priors fixed, even for local angular searches?")) + keep_angular_priors_fixed = true; + else + keep_angular_priors_fixed = false; + do_skip_maximization = parser.checkOption("--skip_maximize", "Skip maximization step (only write out data.star file)?"); int corrections_section = parser.addSection("Corrections"); @@ -589,6 +594,7 @@ void MlOptimiser::parseContinue(int argc, char **argv) skip_realspace_helical_sym = parser.checkOption("--skip_realspace_helical_sym", "", "false", true); do_blush = parser.checkOption("--blush", "Perform the reconstruction with the Blush algorithm."); + blush_model = parser.getOption("--blush_model", "File location of a non-standard blush model", ""); skip_spectral_trailing = parser.checkOption("--blush_skip_spectral_trailing", "Skip spectral trailing during Blush reconstruction (WARNING: This may inflate resolution estimates)"); do_external_reconstruct = parser.checkOption("--external_reconstruct", "Perform the reconstruction step outside relion_refine, e.g. for learned priors?)"); @@ -770,6 +776,7 @@ void MlOptimiser::parseInitial(int argc, char **argv) do_skip_rotate = parser.checkOption("--skip_rotate", "Skip rotational assignment (only translate and classify)?"); do_bimodal_psi = parser.checkOption("--bimodal_psi", "Do bimodal searches of psi angle?"); // Oct07,2015 - Shaoda, bimodal psi do_skip_maximization = false; + keep_angular_priors_fixed = parser.checkOption("--keep_priors_fixed", "Keep priors fixed, even for local angular searches?"); // Helical reconstruction int helical_section = parser.addSection("Helical reconstruction (in development...)"); @@ -1010,6 +1017,7 @@ void MlOptimiser::parseInitial(int argc, char **argv) failsafe_threshold = textToInteger(parser.getOption("--failsafe_threshold", "Maximum number of particles permitted to be handled by fail-safe mode, due to zero sum of weights, before exiting with an error (GPU only).", "40")); do_blush = parser.checkOption("--blush", "Perform the reconstruction with the Blush algorithm."); + blush_model = parser.getOption("--blush_model", "File location of a non-standard blush model", ""); skip_spectral_trailing = parser.checkOption("--blush_skip_spectral_trailing", "Skip spectral trailing during Blush reconstruction (WARNING: This may inflate resolution estimates)"); do_external_reconstruct = parser.checkOption("--external_reconstruct", "Perform the reconstruction step outside relion_refine, e.g. for learned priors?)"); @@ -2032,11 +2040,23 @@ void MlOptimiser::initialiseGeneral(int rank) char *env_blush_args = getenv("RELION_BLUSH_ARGS"); if (env_blush_args != nullptr) + { blush_args += std::string(env_blush_args); + } + + if (blush_model != "") + blush_args += std::string(" -m " + blush_model); if (skip_spectral_trailing) blush_args += " --skip-spectral-trailing "; + if (verb > 0 && blush_args != "") + { + std::cout << " + Passing the below additional arguments to blush: " << std::endl; + std::cout << " + " << blush_args << std::endl; + } + + if (do_gpu) { blush_args += " --gpu "; @@ -2116,7 +2136,7 @@ void MlOptimiser::initialiseGeneral(int rank) fn_local_symmetry_masks.clear(); fn_local_symmetry_operators.clear(); if (fn_local_symmetry != "None") - readRelionFormatMasksAndOperators(fn_local_symmetry, fn_local_symmetry_masks, fn_local_symmetry_operators, mymodel.pixel_size, false); + readRelionFormatMasksAndOperators(fn_local_symmetry, fn_local_symmetry_masks, fn_local_symmetry_operators, local_symmetry_weights, mymodel.pixel_size, false); // For multi-body refinement: Read in the masks in the input STAR file, add a soft-edge to them, and write them to disc with the standard name if (do_initialise_bodies) @@ -4749,7 +4769,7 @@ void MlOptimiser::symmetriseReconstructions() wsum_model.BPref[ith_recons].applyHelicalSymmetry( mymodel.helical_nr_asu, mymodel.helical_twist[ith_recons], - mymodel.helical_rise[ith_recons] / mymodel.pixel_size); + mymodel.helical_rise[ith_recons] / mymodel.pixel_size, nr_threads); if (fn_multi_sym.size() > ith_recons) // Always false if size=0 { @@ -4773,7 +4793,7 @@ void MlOptimiser::symmetriseReconstructions() wsum_model.BPref[iclass_half].applyHelicalSymmetry( mymodel.helical_nr_asu, mymodel.helical_twist[ith_recons], - mymodel.helical_rise[ith_recons] / mymodel.pixel_size); + mymodel.helical_rise[ith_recons] / mymodel.pixel_size, nr_threads); if (fn_multi_sym.size() > ith_recons) // Always false if size=0 { @@ -4810,7 +4830,7 @@ void MlOptimiser::applyLocalSymmetryForEachRef() { // either ibody or iclass can be larger than 0, never 2 at the same time! int ith_recons = (mymodel.nr_bodies > 1) ? ibody : iclass; - applyLocalSymmetry(mymodel.Iref[ith_recons], fn_local_symmetry_masks, fn_local_symmetry_operators); + applyLocalSymmetry(mymodel.Iref[ith_recons], fn_local_symmetry_masks, fn_local_symmetry_operators, local_symmetry_weights); } } } @@ -5985,11 +6005,11 @@ void MlOptimiser::getFourierTransformsAndCtfs( // If there were no defined priors (i.e. their values were 999.), then use the "normal" angles // Also do this for local angular searches when not doing helical refinement (e.g. for subtomograms picked on certain geometries) // Note that helical refinement deals with priors in a special manner... So leave that untouched... - if ( (prior_rot > 998.99 && prior_rot < 999.01) || (!do_helical_refine && do_local_angular_searches) ) + if ( (prior_rot > 998.99 && prior_rot < 999.01) || (!do_helical_refine && do_local_angular_searches && !keep_angular_priors_fixed) ) prior_rot = DIRECT_A2D_ELEM(exp_metadata, metadata_offset, METADATA_ROT); - if ( (prior_tilt > 998.99 && prior_tilt < 999.01) || (!do_helical_refine && do_local_angular_searches) ) + if ( (prior_tilt > 998.99 && prior_tilt < 999.01) || (!do_helical_refine && do_local_angular_searches && !keep_angular_priors_fixed) ) prior_tilt = DIRECT_A2D_ELEM(exp_metadata, metadata_offset, METADATA_TILT); - if ( (prior_psi > 998.99 && prior_psi < 999.01) || (!do_helical_refine && do_local_angular_searches) ) + if ( (prior_psi > 998.99 && prior_psi < 999.01) || (!do_helical_refine && do_local_angular_searches && !keep_angular_priors_fixed) ) prior_psi = DIRECT_A2D_ELEM(exp_metadata, metadata_offset, METADATA_PSI); if (prior_psi_flip_ratio > 998.99 && prior_psi_flip_ratio < 999.01) prior_psi_flip_ratio = 0.5; diff --git a/src/ml_optimiser.h b/src/ml_optimiser.h index 3004cdedf..118c86cfc 100644 --- a/src/ml_optimiser.h +++ b/src/ml_optimiser.h @@ -505,7 +505,8 @@ class MlOptimiser /** Perform reconstruction using the Blush algorithm */ bool do_blush; - bool skip_spectral_trailing; + bool skip_spectral_trailing; + std::string blush_model; /** Argumetns to pass to the Blush call */ std::string blush_args; @@ -531,6 +532,9 @@ class MlOptimiser */ RFLOAT adaptive_fraction; + // Keep rot, tilt psi priors fixed relative to entries in particle starfile, even when performing local angular searches? + bool keep_angular_priors_fixed; + // Seed for random number generator int random_seed; @@ -730,6 +734,7 @@ class MlOptimiser // Local symmetry - list of operators std::vector > > fn_local_symmetry_operators; + std::vector > local_symmetry_weights; //Maximum number of particles permitted to be drop, due to zero sum of weights, before exiting with an error (GPU only). int failsafe_threshold; diff --git a/src/ml_optimiser_mpi.cpp b/src/ml_optimiser_mpi.cpp index 656ddb786..e84666a81 100644 --- a/src/ml_optimiser_mpi.cpp +++ b/src/ml_optimiser_mpi.cpp @@ -2506,7 +2506,7 @@ void MlOptimiserMpi::maximization() // Apply local symmetry according to a list of masks and their operators if ( (fn_local_symmetry_masks.size() != 0) && (fn_local_symmetry_operators.size() != 0) && (!has_converged) ) - applyLocalSymmetry(mymodel.Iref[ith_recons], fn_local_symmetry_masks, fn_local_symmetry_operators); + applyLocalSymmetry(mymodel.Iref[ith_recons], fn_local_symmetry_masks, fn_local_symmetry_operators, local_symmetry_weights); // Shaoda Jul26,2015 - Helical symmetry local refinement if ( (iter > 1) && (do_helical_refine) && (!ignore_helical_symmetry) && (do_helical_symmetry_local_refinement) && mymodel.ref_dim != 2) @@ -2640,7 +2640,7 @@ void MlOptimiserMpi::maximization() // Apply local symmetry according to a list of masks and their operators if ( (fn_local_symmetry_masks.size() != 0) && (fn_local_symmetry_operators.size() != 0) && (!has_converged) ) - applyLocalSymmetry(mymodel.Iref[ith_recons], fn_local_symmetry_masks, fn_local_symmetry_operators); + applyLocalSymmetry(mymodel.Iref[ith_recons], fn_local_symmetry_masks, fn_local_symmetry_operators, local_symmetry_weights); // Shaoda Jul26,2015 - Helical symmetry local refinement if ( (iter > 1) && (do_helical_refine) && (!ignore_helical_symmetry) && (do_helical_symmetry_local_refinement) && mymodel.ref_dim != 2 ) @@ -4125,7 +4125,8 @@ void MlOptimiserMpi::iterate() { if ( (do_helical_refine) && (!do_skip_align) && (!do_skip_rotate) && mymodel.ref_dim == 3) { - updatePriorsForHelicalReconstruction( + // Only update rot priors in local averaging for 1-start filaments, otherwise centre around rot from previous iteration + updatePriorsForHelicalReconstruction( mydata.MDimg, helical_sigma_distance * ((RFLOAT)(mymodel.ori_size)), mymodel.helical_rise, diff --git a/src/particle_subtractor.cpp b/src/particle_subtractor.cpp index 888eef923..c85cc309a 100644 --- a/src/particle_subtractor.cpp +++ b/src/particle_subtractor.cpp @@ -398,7 +398,7 @@ void ParticleSubtractor::saveStarFile(int myrank) } #ifdef DEBUG - std::cout << "myrank = " << myrank << " size = " << size << " my_first = " << my_first << " my_last = " << my_last << " num_items = " << MD.numberOfObjects() << " writing to " << fn_star << std::endl; + std::cout << "myrank = " << myrank << " size = " << size << std::endl; #endif } diff --git a/src/pipeline_jobs.cpp b/src/pipeline_jobs.cpp index caa5c34cf..0c39068b0 100644 --- a/src/pipeline_jobs.cpp +++ b/src/pipeline_jobs.cpp @@ -810,7 +810,7 @@ void RelionJob::initialise(int _job_type) else if (type == PROC_AUTOPICK) { has_mpi = true; - has_thread = false; + has_thread = true; initialiseAutopickJob(); } else if (type == PROC_EXTRACT) @@ -1443,6 +1443,9 @@ bool RelionJob::getCommandsImportJob(std::string &outputname, std::vector1). And this second job only runs on GPUs."); + joboptions["do_amyloid_fom"] = JobOption("Calculate amyloid FOM images (on CPU)? ", true, "Calculate FOM images with 4.7A Fourier signal for all input micrographs? Note this code runs only on the CPU, and best multi-threaded (any n with 36/n being an integer is a good number; we often use 18 threads on our cluster). You need to run a first job to calculate FOM images using this option, before you can use its output as input for a second job to trace the filaments, using the option below."); + joboptions["do_amyloid_tracing"] = JobOption("Trace amyloids in FOM images (on GPU)? ", false, "Trace amyloids (as lines) in the FOM images that were calculated in a first (CPU-based) job? Note this part of the code runs on the GPU. This job takes the micrographs_autopick.star output file from the first job as input (or a subset selection thereof, e.g. with rlnMicrographScoreSkewness>1)."); + joboptions["amyloid_gpu_ids"] = JobOption("Which GPUs to use for tracing:", std::string(""), "This argument is not necessary. If left empty, the job itself will try to allocate available GPU resources. You can override the default allocation by providing a list of which GPUs to use. MPI-processes are separated by ':'. For example: 0:1:2:3. Note, only the amyloid tracing part of the job is run on the GPU; FOM calculation has only been implemented for the CPU."); + joboptions["amyloid_threshold"] = JobOption("Amyloid pick threshold (sigma): ", 0.25, 0.05, 1, 0.05, "How many sigma does the peaks need to be above the mean for the filament tracing to include a coordinate?"); + joboptions["do_amyloid_plot"] = JobOption("Plot results per micrograph?", false, "Set this option to Yes to visualise intermediate results for amyloid tracing, which may help with setting values for filament length, width and picking threshold. This writes a PNG file for each micrograph, next to its output star file, so you may want to limit the number of input micrographs."); + joboptions["amyloid_width"] = JobOption("Minimum distance between filaments (A): ", 100, 50, 1000, 10, "Minimum distance between ends of traced filaments (in Angstroms). "); + joboptions["amyloid_length"] = JobOption("Minimum filament length (A): ", 500, 100, 1000, 10, "Length (in Angstroms) used for FOM calculation, and minimum length of filaments for tracing."); + joboptions["do_amyloid_carbon"] = JobOption("Ignore filaments on carbon?", false, "Set to Yes if you want to use automated carbon detection to avoid picking filaments on carbon."); + joboptions["amyloid_carbon_threshold"] = JobOption("Carbon threshold: ", 0.9, 0.05, 1, 0.05, "At what probability should pixels in the micrographs be deemed carbon? Use lower values to have more areas exclude from the picking."); + } bool RelionJob::getCommandsAutopickJob(std::string &outputname, std::vector &commands, @@ -2144,9 +2161,94 @@ bool RelionJob::getCommandsAutopickJob(std::string &outputname, std::vector 1) + command="`which relion_find_amyloid_mpi`"; + else + command="`which relion_find_amyloid`"; + if (error_message != "") return false; + + if (joboptions["do_amyloid_plot"].getBoolean()) + { + if (joboptions["nr_mpi"].getNumber(error_message) > 1 || joboptions["do_queue"].getBoolean()) + { + error_message = "You cannot use parallel execution or job submission when plotting intermediate results."; + return false; + } + } + + command += " --odir " + outputname; + command += " --pickname autopick"; + + + if (joboptions["do_amyloid_fom"].getBoolean()) + { + + if (joboptions["do_amyloid_tracing"].getBoolean()) + { + error_message = "ERROR: you need to run a separate FOM calculation job, followed by a tracing job. FOM is CPU-only; tracing is GPU-only!"; + return false; + } + + command += " --j " + joboptions["nr_threads"].getString(); + + // Also output micrographs.star file with kurtosis and skewness of the autopicking scores + Node node3c(outputname + "micrographs_autopick.star", joboptions["fn_input_autopick"].node_type); + outputNodes.push_back(node3c); + + } + else + { + command += " --skip_fom "; + } + + + if (joboptions["do_amyloid_tracing"].getBoolean()) + { + // Output new version: no longer save coords_suffix nodetype, but 2-column list of micrographs and coordinate files + Node node3(outputname + "autopick.star", LABEL_AUTOPICK_COORDS); + outputNodes.push_back(node3); + + command += " --trace_filament_length " + joboptions["amyloid_length"].getString(); + command += " --trace_filament_width " + joboptions["amyloid_width"].getString(); + command += " --threshold " + joboptions["amyloid_threshold"].getString(); + command += " --gpu \"" + joboptions["amyloid_gpu_ids"].getString() + "\""; + + if (joboptions["do_amyloid_carbon"].getBoolean()) + { + command += " --detect_carbon --carbon_threshold " + joboptions["amyloid_carbon_threshold"].getString(); + } + + if (joboptions["do_amyloid_plot"].getBoolean()) command += " --plot "; + + } + else + { + command += " --skip_tracing "; + } + + command += " --i " + joboptions["fn_input_autopick"].getString(); + Node node(joboptions["fn_input_autopick"].getString(), joboptions["fn_input_autopick"].node_type); + inputNodes.push_back(node); + + // PDF with histograms of the eigenvalues + Node node3b(outputname + "logfile.pdf", LABEL_AUTOPICK_LOG); + outputNodes.push_back(node3b); + + // If this is a continue job, then only process unfinished micrographs + if (is_continue) + command += " --only_do_unfinished "; + + + } + else { - // Run autopicking + + // Run autopicking if (joboptions["nr_mpi"].getNumber(error_message) > 1) command="`which relion_autopick_mpi`"; else @@ -2157,11 +2259,12 @@ bool RelionJob::getCommandsAutopickJob(std::string &outputname, std::vector 0) { @@ -4040,38 +4129,33 @@ bool RelionJob::getCommandsClass3DJob(std::string &outputname, std::vector 0.) - command += " --helical_twist_inistep " + joboptions["helical_twist_inistep"].getString(); + float twist_inistep = joboptions["helical_twist_inistep"].getNumber(error_message); + if (error_message != "") return false; + if (twist_inistep > 0.) + command += " --helical_twist_inistep " + joboptions["helical_twist_inistep"].getString(); - command += " --helical_rise_min " + joboptions["helical_rise_min"].getString(); - command += " --helical_rise_max " + joboptions["helical_rise_max"].getString(); + command += " --helical_rise_min " + joboptions["helical_rise_min"].getString(); + command += " --helical_rise_max " + joboptions["helical_rise_max"].getString(); - float rise_inistep = joboptions["helical_rise_inistep"].getNumber(error_message); - if (error_message != "") return false; - if (rise_inistep > 0.) - command += " --helical_rise_inistep " + joboptions["helical_rise_inistep"].getString(); - } - } - else - command += " --ignore_helical_symmetry"; + float rise_inistep = joboptions["helical_rise_inistep"].getNumber(error_message); + if (error_message != "") return false; + if (rise_inistep > 0.) + command += " --helical_rise_inistep " + joboptions["helical_rise_inistep"].getString(); + } if (joboptions["keep_tilt_prior_fixed"].getBoolean()) command += " --helical_keep_tilt_prior_fixed"; if ( (joboptions["dont_skip_align"].getBoolean()) && (!joboptions["do_local_ang_searches"].getBoolean()) ) @@ -4097,7 +4181,11 @@ bool RelionJob::getCommandsClass3DJob(std::string &outputname, std::vector 0.) + { command += " --helical_sigma_distance " + floatToString(val / 3.); + int nstart = joboptions["helical_nstart"].getNumber(error_message); + command += " --helical_nstart " + floatToString(nstart); + } } } @@ -4201,6 +4289,7 @@ High-resolution refinements (e.g. ribosomes or other large complexes in 3D auto- masked half-maps are used and a post-processing-like correction of the FSC curves (with phase-randomisation) is performed every iteration. This only works when a reference mask is provided on the I/O tab. \ This may yield higher-resolution maps, especially when the mask contains only a relatively small volume inside the box."); joboptions["do_blush"] = JobOption("Use Blush regularisation?", false, "If set to Yes, relion_refine will use a neural network to perform regularisation by denoising at every iteration, instead of the standard smoothness regularisation."); + joboptions["blush_version"] = JobOption("Blush network version:", job_blush_version_options, 0, "Which version of the Blush network to use. v1.0 is the original version published in Kiamnius et al (2024) Nature Methods; amy-v1.0 is a newer version that was trained specifically for use with amyloid filaments."); joboptions["sampling"] = JobOption("Initial angular sampling:", job_sampling_options, 2, "There are only a few discrete \ angular samplings possible because we use the HealPix library to generate the sampling of the first two Euler angles on the sphere. \ @@ -4254,7 +4343,6 @@ in the previous iteration will get higher weights than those further away.\n\nTh rot, tilt and psi angles in the first few iterations (global searches for orientations) in 3D helical reconstruction. \ Values of 9 or 15 degrees are commonly used. Higher values are recommended for more flexible structures and more memory and computation time will be used. \ A range of 15 degrees means sigma = 5 degrees.\n\nThese options will be invalid if you choose to perform local angular searches or not to perform image alignment on 'Sampling' tab."); - joboptions["do_apply_helical_symmetry"] = JobOption("Apply helical symmetry?", true, "If set to Yes, helical symmetry will be applied in every iteration. Set to No if you have just started a project, helical symmetry is unknown or not yet estimated."); joboptions["helical_nr_asu"] = JobOption("Number of unique asymmetrical units:", 1, 1, 100, 1, "Number of unique helical asymmetrical units in each segment box. If the inter-box distance (set in segment picking step) \ is 100 Angstroms and the estimated helical rise is ~20 Angstroms, then set this value to 100 / 20 = 5 (nearest integer). This integer should not be less than 1. The correct value is essential in measuring the \ signal to noise ratio in helical reconstruction."); @@ -4285,8 +4373,10 @@ does not guarantee convergence. The program cannot find a reasonable symmetry if joboptions["helical_rise_inistep"] = JobOption("Helical rise search (A) - Step:", std::string("0"), "Minimum, maximum and initial step for helical rise search. Helical rise is a positive value in Angstroms. \ Generally it is not necessary for the user to provide an initial step (less than 1% the initial helical rise, 5~1000 samplings as default). But it needs to be set manually if the default value \ does not guarantee convergence. The program cannot find a reasonable symmetry if the true helical parameters fall out of the given ranges. Note that the final reconstruction can still converge if wrong helical and point group symmetry are provided."); - joboptions["helical_range_distance"] = JobOption("Range factor of local averaging:", -1., 1., 5., 0.1, "Local averaging of orientations and translations will be performed within a range of +/- this value * the box size. Polarities are also set to be the same for segments coming from the same tube during local refinement. \ -Values of ~ 2.0 are recommended for flexible structures such as MAVS-CARD filaments, ParM, MamK, etc. This option might not improve the reconstructions of helices formed from curled 2D lattices (TMV and VipA/VipB). Set to negative to disable this option."); + joboptions["helical_range_distance"] = JobOption("Local averaging - range (box)", std::string("-1"), "Local averaging of orientations and translations will be performed within a range of +/- this value * the box size. This also requires providing the N-start number of the helical symmetry (e.g. 2 for tau PHFs and 1 for tau SFs). Polarities are also set to be the same for segments coming from the same tube during local refinement. \ +Values of ~ 2.0 are recommended for the range. Set the range to negative to disable local averaging (in which case the Nstart number is also ignored)."); + joboptions["helical_nstart"] = JobOption("Local averaging - N-start symmetry", std::string("1"), "Local averaging of orientations and translations will be performed within a range of +/- this value * the box size. This also requires providing the N-start number of the helical symmetry (e.g. 2 for tau PHFs and 1 for tau SFs). Polarities are also set to be the same for segments coming from the same tube during local refinement. \ +Values of ~ 2.0 are recommended for the range. Set the range to negative to disable local averaging (in which case the Nstart number is also ignored)."); joboptions["keep_tilt_prior_fixed"] = JobOption("Keep tilt-prior fixed:", true, "If set to yes, the tilt prior will not change during the optimisation. If set to No, at each iteration the tilt prior will move to the optimal tilt value for that segment from the previous iteration."); joboptions["do_parallel_discio"] = JobOption("Use parallel disc I/O?", true, "If set to Yes, all MPI followers will read their own images from disc. \ @@ -4361,7 +4451,7 @@ bool RelionJob::getCommandsAutorefineJob(std::string &outputname, std::vector 0.) - command += " --helical_twist_inistep " + joboptions["helical_twist_inistep"].getString(); - - command += " --helical_rise_min " + joboptions["helical_rise_min"].getString(); - command += " --helical_rise_max " + joboptions["helical_rise_max"].getString(); - - float rise_inistep = joboptions["helical_rise_inistep"].getNumber(error_message); - if (error_message != "") return false; - if (rise_inistep > 0.) - command += " --helical_rise_inistep " + joboptions["helical_rise_inistep"].getString(); - } - } - else - command += " --ignore_helical_symmetry"; + if (joboptions["do_local_search_helical_symmetry"].getBoolean()) + { + command += " --helical_symmetry_search"; + command += " --helical_twist_min " + joboptions["helical_twist_min"].getString(); + command += " --helical_twist_max " + joboptions["helical_twist_max"].getString(); + + float twist_inistep = joboptions["helical_twist_inistep"].getNumber(error_message); + if (error_message != "") return false; + if (twist_inistep > 0.) + command += " --helical_twist_inistep " + joboptions["helical_twist_inistep"].getString(); + + command += " --helical_rise_min " + joboptions["helical_rise_min"].getString(); + command += " --helical_rise_max " + joboptions["helical_rise_max"].getString(); + + float rise_inistep = joboptions["helical_rise_inistep"].getNumber(error_message); + if (error_message != "") return false; + if (rise_inistep > 0.) + command += " --helical_rise_inistep " + joboptions["helical_rise_inistep"].getString(); + } float val; if (sampling != auto_local_sampling) @@ -4580,7 +4666,11 @@ bool RelionJob::getCommandsAutorefineJob(std::string &outputname, std::vector 0.) + { command += " --helical_sigma_distance " + floatToString(val / 3.); + int nstart = joboptions["helical_nstart"].getNumber(error_message); + command += " --helical_nstart " + floatToString(nstart); + } if (joboptions["keep_tilt_prior_fixed"].getBoolean()) command += " --helical_keep_tilt_prior_fixed"; @@ -4646,6 +4736,7 @@ Also note that larger bodies should be above smaller bodies in the STAR file. Fo joboptions["do_subtracted_bodies"] = JobOption("Reconstruct subtracted bodies?", true, "If set to Yes, then the reconstruction of each of the bodies will use the subtracted images. This may give \ useful insights about how well the subtraction worked. If set to No, the original particles are used for reconstruction (while the subtracted ones are still used for alignment). This will result in fuzzy densities for bodies outside the one used for refinement."); joboptions["do_blush"] = JobOption("Use Blush regularisation?", false, "If set to Yes, relion_refine will use a neural network to perform regularisation by denoising at every iteration, instead of the standard smoothness regularisation."); + joboptions["blush_version"] = JobOption("Blush network version:", job_blush_version_options, 0, "Which version of the Blush network to use. v1.0 is the original version published in Kiamnius et al (2024) Nature Methods; amy-v1.0 is a newer version that was trained specifically for use with amyloid filaments."); joboptions["sampling"] = JobOption("Initial angular sampling:", job_sampling_options, 4, "There are only a few discrete \ angular samplings possible because we use the HealPix library to generate the sampling of the first two Euler angles on the sphere. \ @@ -4770,7 +4861,10 @@ bool RelionJob::getCommandsMultiBodyJob(std::string &outputname, std::vector"); joboptions["do_proj"] = JobOption("Also write 2D sums of central Z-slices?:", true, "When set to Yes, this option will result in the calculation of 2D sums of Z-slices from the reconstructed tomograms. These may be useful to quickly screen for bad tomograms using the relion_display program."); @@ -6750,9 +6866,13 @@ bool RelionJob::getCommandsTomoReconstructTomogramsJob(std::string &outputname, { command += " --ctf_intact_first_peak "; } + if (joboptions["do_skip_wiener"].getBoolean()) + { + command += " --skip_fourier_wiener "; + } } - if (joboptions["do_proj"].getBoolean()) + if (joboptions["do_proj"].getBoolean()) { command += " --do_proj "; command += " --centre_proj " + joboptions["centre_proj"].getString(); @@ -6936,6 +7056,20 @@ bool RelionJob::getCommandsTomoPickTomogramsJob(std::string &outputname, std::ve if (error_message != "") return false; + if (joboptions["in_tomoset"].getString() == "") + { + error_message = "ERROR: you need to provide an input STAR file"; + return false; + } + + MetaDataTable MDtest; + MDtest.read(joboptions["in_tomoset"].getString(), "global"); + if (!MDtest.containsLabel(EMDL_TOMO_RECONSTRUCTED_TOMOGRAM_FILE_NAME)) + { + error_message = "ERROR: the tomogram star file does not contain the label rlnTomoReconstructedTomogram"; + return false; + } + if (joboptions["pick_mode"].getString() == "particles" && joboptions["in_star_file"].getString().length() > 0) { command0 = "`which relion_python_tomo_get_particle_poses`"; @@ -6953,12 +7087,6 @@ bool RelionJob::getCommandsTomoPickTomogramsJob(std::string &outputname, std::ve command="`which relion_python_tomo_pick` "; - if (joboptions["in_tomoset"].getString() == "") - { - error_message = "ERROR: you need to provide an input STAR file"; - return false; - } - /* if (joboptions["pick_mode"].getString() == "surfaces" || joboptions["pick_mode"].getString() == "filaments") { @@ -7055,14 +7183,15 @@ void RelionJob::initialiseTomoSubtomoJob() addTomoInputOptions(true, true, true, false); - joboptions["binning"] = JobOption("Binning factor:", 1, 1, 16, 1, "The tilt series images will be binned by this (real-valued) factor and then reconstructed in the specified box size above. Note that thereby the reconstructed region becomes larger when specifying binning factors larger than one."); - joboptions["box_size"] = JobOption("Box size (binned pix):", 128, 32, 512, 16, "The initial box size of the reconstruction. A sufficiently large box size allows more of the high-frequency signal to be captured that has been delocalised by the CTF."); - joboptions["crop_size"] = JobOption("Cropped box size (binned pix):", -1, -1, 512, 16, "If set to a positive value, after construction, the resulting pseudo subtomograms are cropped to this size. A smaller box size allows the (generally expensive) refinement using relion_refine to proceed more rapidly."); + + joboptions["box_size_angst"] = JobOption("Box size (A):", 128, 32, 512, 16, "The final particle box size in Angstrom."); + joboptions["binned_size_pix"] = JobOption("Binning to box size (pixels):", 64, 16, 256, 16, "The box size above will be binned to yield the number of pixels given here. Smaller boxes will refine faster and occupy less space, but will be limited to lower Nyquist frequency."); + joboptions["precrop_size_angst"] = JobOption("Pre-cropping box size (A):", -1, -1, 512, 16, "If set to a positive value, then a larger box size can be used to extract 2D slices out of the micrograph, pre-multiply these with the CTF, and then crop to the box size above. A sufficiently large pre-crop box size therefore will allow more of the high-frequency signal to be captured that has been delocalised by the CTF. "); joboptions["max_dose"] = JobOption("Maximum dose (e/A^2):", -1, -1, 200, 1, "Tilt series frames with a dose higher than this maximum dose (in electrons per squared Angstroms) will not be included in the 3D pseudo-subtomogram, or in the 2D stack. For the latter, this will disc I/O operations and increase speed."); joboptions["min_frames"] = JobOption("Minimum nr. frames:", 1, 1, 40, 1, "Each selected pseudo-subtomogram need to be visible in at least this number of tilt series frames with doses below the maximum dose"); - joboptions["do_stack2d"] = JobOption("Write output as 2D stacks?", true ,"If set to Yes, this program will write output subtomograms as 2D substacks. This is new as of relion-4.1, and the preferred way of generating subtomograms. If set to No, then relion-4.0 3D pseudo-subtomograms will be written out. Either can be used in subsequent refinements and classifications."); + joboptions["subtomo_format"] = JobOption("Subtomogram format:", job_subtomo_format_options, 0, "Format of the extracted subtomograms. Relion-5 type 2D stacks, relion-4 type 3D pseudo-subtomograms, or relion-3 type real-space subtomograms. Some people have reported that real-space 3D subtomograms are better for initial alignments than 2D stacks or 3D pseudo-subtomograms. You may want to use AreTomo2 reconstructions for extracting real-space subtomograms. They can be made as part of the Align tilt-series job."); joboptions["do_float16"] = JobOption("Write output in float16?", true ,"If set to Yes, this program will write output images in float16 MRC format. This will save a factor of two in disk space compared to the default of writing in float32. Note that RELION and CCPEM will read float16 images, but other programs may not (yet) do so."); } @@ -7092,14 +7221,9 @@ bool RelionJob::getCommandsTomoSubtomoJob(std::string &outputname, std::vector 0.) command += " --crop " + joboptions["crop_size"].getString(); - - command += " --bin " + joboptions["binning"].getString(); + command += " --box_size_A " + joboptions["box_size_angst"].getString(); + command += " --precrop_size_A " + joboptions["precrop_size_angst"].getString(); + command += " --binned_size_pix " + joboptions["binned_size_pix"].getString(); float max_dose = joboptions["max_dose"].getNumber(error_message); if (error_message != "") return false; @@ -7109,17 +7233,24 @@ bool RelionJob::getCommandsTomoSubtomoJob(std::string &outputname, std::vector 0.) command += " --min_frames " + joboptions["min_frames"].getString(); - if (joboptions["do_float16"].getBoolean()) - { - command += " --float16 "; - } + if (strcmp((joboptions["subtomo_format"].getString()).c_str(), job_subtomo_format_options[0].c_str()) == 0) + { + command += " --stack2d "; + } + else if (strcmp((joboptions["subtomo_format"].getString()).c_str(), job_subtomo_format_options[2].c_str()) == 0) + { + command += " --real_subtomo "; - if (joboptions["do_stack2d"].getBoolean()) - { - command += " --stack2d "; - } + Node node2(outputname+"particles_for_class2d.star", LABEL_CLASS2D_PARTS); + outputNodes.push_back(node2); + } - if (is_continue) + if (joboptions["do_float16"].getBoolean()) + { + command += " --float16 "; + } + + if (is_continue) { command += " --only_do_unfinished "; } diff --git a/src/pipeline_jobs.h b/src/pipeline_jobs.h index b9a1e4201..e9ef7fbb4 100644 --- a/src/pipeline_jobs.h +++ b/src/pipeline_jobs.h @@ -159,6 +159,17 @@ static const std::vector job_modelangelo_alphabet_options{ "RNA" }; +static const std::vector job_subtomo_format_options{ + "2D stacks", + "3D pseudo-subtomos", + "3D subtomos" +}; + +static const std::vector job_blush_version_options{ + "v1.0", + "amy-v1.0" +}; + // To have a line on the GUI to change the minimum number of dedicated in a job static bool do_allow_change_minimum_dedicated; diff --git a/src/preprocessing.cpp b/src/preprocessing.cpp index cb3fb1f7f..36af904da 100644 --- a/src/preprocessing.cpp +++ b/src/preprocessing.cpp @@ -93,8 +93,9 @@ void Preprocessing::read(int argc, char **argv, int rank) int helix_section = parser.addSection("Helix extraction"); do_extract_helix = parser.checkOption("--helix", "Extract helical segments"); - helical_tube_outer_diameter = textToFloat(parser.getOption("--helical_outer_diameter", "Outer diameter of helical tubes in Angstroms (for masks of helical segments)", "-1.")); - do_extract_helical_tubes = parser.checkOption("--helical_tubes", "Extract helical segments from tube coordinates"); + helical_tube_outer_diameter = textToFloat(parser.getOption("--helical_outer_diameter", "Outer diameter of helical tubes in Angstroms (for masks of helical segments)", "-1.")); + do_startend = parser.checkOption("--from_startend", "Extract helical segments from tube start-end coordinates"); + do_lines = parser.checkOption("--from_lines", "Extract helical segments from picked lines"); helical_nr_asu = textToInteger(parser.getOption("--helical_nr_asu", "Number of helical asymmetrical units", "1")); helical_rise = textToFloat(parser.getOption("--helical_rise", "Helical rise (in Angstroms)", "0.")); helical_bimodal_angular_priors = parser.checkOption("--helical_bimodal_angular_priors", "Add bimodal angular priors for helical segments"); @@ -209,8 +210,37 @@ void Preprocessing::initialise() // Either get coordinate filenames from coord_list, or from the fn_coord_suffix if (fn_coord_list != "") { - MetaDataTable MDcoords; - MDcoords.read(fn_coord_list); + MetaDataTable MDhead; + if (MDhead.read(fn_coord_list, "general")) + { + MDhead.getValue(EMDL_MICROGRAPH_PICKTYPE, picktype); + if (picktype == "particles") + { + if (do_startend || do_lines) + std::cerr << "WARNING: coordinate file states these are particles, ignoring --from_startend or --from_lines "<< std::endl; + do_startend = do_lines = false; + } + else if (picktype == "startend") + { + if (do_lines) + std::cerr << "WARNING: coordinate file states these are startend, ignoring --from_lines "<< std::endl; + do_startend = true; + do_lines = false; + } + else if (picktype == "lines") + { + if (do_startend) + std::cerr << "WARNING: coordinate file states these are lines, ignoring --from_startend "<< std::endl; + do_startend = false; + do_lines = true; + } + else + { + REPORT_ERROR("ERROR: unrecognised micrograph picktype from the general table of the coordinate file"); + } + } + MetaDataTable MDcoords; + MDcoords.read(fn_coord_list, "coordinate_files"); FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDcoords) { FileName fn_mic, fn_coord; @@ -524,7 +554,7 @@ void Preprocessing::runExtractParticles() progress_bar(imic); TIMING_TIC(TIMING_TOP); - micIsUsed = extractParticlesFromFieldOfView(fn_mic, imic); + micIsUsed = extractParticlesFromFieldOfView(fn_mic, imic); TIMING_TOC(TIMING_TOP); if(micIsUsed) @@ -630,6 +660,118 @@ void Preprocessing::readCoordinates(FileName fn_coord, MetaDataTable &MD) } } +void Preprocessing::addOneHelicalSegment(MetaDataTable &MD, RFLOAT xcoord, RFLOAT ycoord, int tube_id, + RFLOAT psi_prior, RFLOAT helix_length, RFLOAT psi_prior_flip_ratio) +{ + MD.addObject(); + MD.setValue(EMDL_IMAGE_COORD_X, xcoord); + MD.setValue(EMDL_IMAGE_COORD_Y, ycoord); + MD.setValue(EMDL_PARTICLE_HELICAL_TUBE_ID, tube_id); + MD.setValue(EMDL_ORIENT_TILT_PRIOR, 90.); + MD.setValue(EMDL_ORIENT_PSI_PRIOR, psi_prior); + MD.setValue(EMDL_PARTICLE_HELICAL_TRACK_LENGTH_ANGSTROM, helix_length); + MD.setValue(EMDL_ORIENT_PSI_PRIOR_FLIP_RATIO, psi_prior_flip_ratio); + +} + +void Preprocessing::convertHelicalLineCoordsToMetaDataTable( + FileName& fn_in, MetaDataTable& MD_out, int& total_segments, int& total_tubes, + int nr_asu, RFLOAT rise_A, RFLOAT pixel_size_A, RFLOAT Xdim, RFLOAT Ydim, RFLOAT box_size_pix, + bool bimodal_angular_priors, bool cut_into_segments) +{ + + // Check parameters and open files + if ( (nr_asu < 1) || (rise_A < 0.001) || (pixel_size_A < 0.01) ) + REPORT_ERROR("Preprocessing::convertHelicalLineCoordsToMetaDataTable: Wrong parameters!"); + if ( (box_size_pix < 2) || (Xdim < box_size_pix) || (Ydim < box_size_pix)) + REPORT_ERROR("Preprocessing::convertHelicalLineCoordsToMetaDataTable: Wrong dimensions or box size!"); + if (fn_in.getExtension() != "star") + REPORT_ERROR("Preprocessing::convertHelicalLineCoordsToMetaDataTable: MetadataTable should have .star extension. Error(s) in " + fn_in); + + // Read input STAR file + MetaDataTable MD_in; + MD_in.read(fn_in); + if (MD_in.numberOfObjects() < 1) // Handle empty input files + return; + + if ( (!MD_in.containsLabel(EMDL_IMAGE_COORD_X)) || (!MD_in.containsLabel(EMDL_IMAGE_COORD_Y)) || + (!MD_in.containsLabel(EMDL_PARTICLE_SELECTION_TYPE)) ) + REPORT_ERROR("Preprocessing::convertHelicalLineCoordsToMetaDataTable: Input STAR file does not contain X, Y coordinates or particle selection type! Error(s) in " + fn_in); + + MD_out.clear(); + MD_out.addLabel(EMDL_IMAGE_COORD_X); + MD_out.addLabel(EMDL_IMAGE_COORD_Y); + MD_out.addLabel(EMDL_PARTICLE_HELICAL_TUBE_ID); + MD_out.addLabel(EMDL_ORIENT_TILT_PRIOR); + MD_out.addLabel(EMDL_ORIENT_PSI_PRIOR); + MD_out.addLabel(EMDL_PARTICLE_HELICAL_TRACK_LENGTH_ANGSTROM); + MD_out.addLabel(EMDL_ORIENT_PSI_PRIOR_FLIP_RATIO); + RFLOAT psi_prior_flip_ratio = (bimodal_angular_priors) ? BIMODAL_PSI_PRIOR_FLIP_RATIO : UNIMODAL_PSI_PRIOR_FLIP_RATIO; + + int filament_id=0; + RFLOAT filament_length = 0.; + RFLOAT remaining_step = 0.; + RFLOAT step_A = nr_asu * rise_A; + RFLOAT step_pix = step_A / pixel_size_A; + + total_tubes = total_segments = 0; + int my_type=0, my_prev_type= 0; + bool is_first = false; + RFLOAT my_xcoord, my_ycoord, prev_xcoord, prev_ycoord; + FOR_ALL_OBJECTS_IN_METADATA_TABLE(MD_in) + { + MD_in.getValue(EMDL_IMAGE_COORD_X, my_xcoord); + MD_in.getValue(EMDL_IMAGE_COORD_Y, my_ycoord); + MD_in.getValue(EMDL_PARTICLE_SELECTION_TYPE, my_type); + if (my_type != my_prev_type) + { + if (is_first) + { + std::cerr << "WARNING: encountered a filament with only a single point in " << fn_in << std::endl; + continue; + } + + // start a new filament (initialise psi to zero!!) + is_first = true; + filament_length = 0.; + remaining_step = 0.; + filament_id++; + total_tubes++; + total_segments++; + //std::cerr << "is_first= "<= YSIZE(Imic()) || xF < 0 || x0 >= XSIZE(Imic()) || + if (!do_recenter) + { + if (yF < 0 || y0 >= YSIZE(Imic()) || xF < 0 || x0 >= XSIZE(Imic()) || (dimensionality==3 && (zF < 0 || z0 >= ZSIZE(Imic())) ) ) - { - std::cerr << " micrograph x,y,z,n-size= " << XSIZE(Imic()) << " , " << YSIZE(Imic()) << " , " << ZSIZE(Imic()) << " , " << NSIZE(Imic()) << std::endl; - std::cerr << " particle position= " << xpos << " , " << ypos; - if (dimensionality == 3) - std::cerr << " , " << zpos; - std::cerr << std::endl; - REPORT_ERROR("Preprocessing::extractParticlesFromOneFrame ERROR: particle" + integerToString(ipos+1) + " lies completely outside micrograph " + fn_mic); - } + { + std::cerr << " micrograph x,y,z,n-size= " << XSIZE(Imic()) << " , " << YSIZE(Imic()) << " , " << ZSIZE(Imic()) << " , " << NSIZE(Imic()) << std::endl; + std::cerr << " particle position= " << xpos << " , " << ypos; + if (dimensionality == 3) + std::cerr << " , " << zpos; + std::cerr << std::endl; + REPORT_ERROR("Preprocessing::extractParticlesFromOneFrame ERROR: particle" + integerToString(ipos+1) + " lies completely outside micrograph " + fn_mic); + } + } // Read per-particle CTF if (MDin_has_ctf && !keep_ctf_from_micrographs) @@ -1244,7 +1394,7 @@ MetaDataTable Preprocessing::getCoordinateMetaDataTable(FileName fn_mic) } RFLOAT mag2, dstep2, particle_angpix, rescale_fndata = 1.0; - if (MDresult.numberOfObjects() > 0) + if (MDresult.numberOfObjects() > 0) { MDresult.goToObject(0); @@ -1352,6 +1502,35 @@ MetaDataTable Preprocessing::getCoordinateMetaDataTable(FileName fn_mic) } // end if recenter } // end loop all objects + + // Check whether do_center has moved some particles outside the micrograph and remove those + if (do_recenter) + { + + Image Imic; + Imic.read(fn_mic, false); + + MetaDataTable MDcopy; + MDcopy.setName(MDresult.getName()); + FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDresult) + { + RFLOAT xcoord, ycoord, zcoord = 0.; + MDresult.getValue(EMDL_IMAGE_COORD_X, xcoord); + MDresult.getValue(EMDL_IMAGE_COORD_Y, ycoord); + if (dimensionality == 3) + MDresult.getValue(EMDL_IMAGE_COORD_Z, zcoord); + + // Discard particles that are completely outside the micrograph and print a warning + if (ycoord >= 0 && ycoord < YSIZE(Imic()) && xcoord >= 0 && xcoord < XSIZE(Imic())) + { + if (dimensionality == 2 || (zcoord >= 0 && zcoord < ZSIZE(Imic())) ) + MDcopy.addObject(MDresult.getObject()); + } + } + MDresult = MDcopy; + + } + } return MDresult; diff --git a/src/preprocessing.h b/src/preprocessing.h index 4d98e84b9..907227b7f 100644 --- a/src/preprocessing.h +++ b/src/preprocessing.h @@ -161,11 +161,17 @@ class Preprocessing // Extract helical segments bool do_extract_helix; + // Extract filament segments from picked lines + bool do_lines; + // Outer diameter of helical tubes in Angstroms (for masks of helical segments) RFLOAT helical_tube_outer_diameter; - // Extract helical segments from tube coordinates - bool do_extract_helical_tubes; + // Picking type + std::string picktype; + + // Extract helical segments from tube coordinates + bool do_startend; // Number of helical asymmetrical units int helical_nr_asu; @@ -208,6 +214,23 @@ class Preprocessing // Read coordinates from text files void readCoordinates(FileName fn_coord, MetaDataTable &MD); + void addOneHelicalSegment(MetaDataTable &MD, RFLOAT xcoord, RFLOAT ycoord, int tube_id, + RFLOAT psi_prior, RFLOAT helix_length, RFLOAT psi_prior_flip_ratio); + + void convertHelicalLineCoordsToMetaDataTable( + FileName& fn_in, + MetaDataTable& MD_out, + int& total_segments, + int& total_tubes, + int nr_asu, + RFLOAT rise_A, + RFLOAT pixel_size_A, + RFLOAT Xdim, + RFLOAT Ydim, + RFLOAT box_size_pix, + bool bimodal_angular_priors = true, + bool cut_into_segments = true); + // Read helical coordinates from text files void readHelicalCoordinates(FileName fn_mic, FileName fn_coord, MetaDataTable &MD); diff --git a/src/reconstructor.cpp b/src/reconstructor.cpp index dacb8d87f..f21eedcfd 100644 --- a/src/reconstructor.cpp +++ b/src/reconstructor.cpp @@ -90,6 +90,7 @@ void Reconstructor::read(int argc, char **argv) do_debug = parser.checkOption("--write_debug_output", "Write out arrays with data and weight terms prior to reconstruct"); do_external_reconstruct = parser.checkOption("--external_reconstruct", "Write out BP denominator and numerator for external_reconstruct program"); verb = textToInteger(parser.getOption("--verb", "Verbosity", "1")); + nr_threads = textToInteger(parser.getOption("--j", "Number of threads (only for symmetrisation for now)", "1")); // Hidden r_min_nn = textToInteger(getParameter(argc, argv, "--r_min_nn", "10")); @@ -768,7 +769,7 @@ void Reconstructor::reconstruct() if (verb > 0) std::cout << " + Starting the reconstruction ..." << std::endl; - backprojector.symmetrise(nr_helical_asu, helical_twist, helical_rise/angpix); + backprojector.symmetrise(nr_helical_asu, helical_twist, helical_rise/angpix, nr_threads); if (do_reconstruct_ctf) { diff --git a/src/reconstructor.h b/src/reconstructor.h index fb3aa426c..a06890db2 100644 --- a/src/reconstructor.h +++ b/src/reconstructor.h @@ -45,7 +45,7 @@ class Reconstructor int r_max, r_min_nn, blob_order, ref_dim, interpolator, iter, debug_ori_size, debug_size, ctf_dim, nr_helical_asu, newbox, width_mask_edge, nr_sectors, subset, chosen_class, - data_dim, output_boxsize, verb; + data_dim, output_boxsize, verb, nr_threads; RFLOAT blob_radius, blob_alpha, angular_error, shift_error, angpix, maxres, helical_rise, helical_twist; diff --git a/src/tomography_python_programs/get_particle_poses/filaments.py b/src/tomography_python_programs/get_particle_poses/filaments.py index 01f599dc9..69839e5cb 100644 --- a/src/tomography_python_programs/get_particle_poses/filaments.py +++ b/src/tomography_python_programs/get_particle_poses/filaments.py @@ -28,8 +28,8 @@ def get_poses_along_filament_backbones( ..., help="spacing between particles along filaments in angstroms." ), filament_polarity_known: bool = typer.Option( - True, help="Whether filament polarity from annotations should be fixed " - "during refinement." + False, help="Whether filament polarity from annotations should be fixed " + "during refinement (i.e. filaments have been picked front->end)." ) ): global_df = starfile.read(tilt_series_star_file, diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9a501492d..400dba53f 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -7,7 +7,7 @@ target_link_libraries(tests relion_lib) target_link_libraries(tests ${FFTW_LIBRARIES}) target_link_libraries(tests ${TIFF_LIBRARIES}) -#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++17") include_directories(tests PRIVATE ${CMAKE_SOURCE_DIR} ${CMAKE_SOURCE_DIR}/tests) include_directories(tests PRIVATE ${FFTW_INCLUDES})