diff --git a/CMake/mitkFunctionGetLibrarySearchPaths.cmake b/CMake/mitkFunctionGetLibrarySearchPaths.cmake index 81e3704f79..8dc9fdc243 100644 --- a/CMake/mitkFunctionGetLibrarySearchPaths.cmake +++ b/CMake/mitkFunctionGetLibrarySearchPaths.cmake @@ -1,169 +1,172 @@ macro(_find_package package_name) find_package(${package_name} REQUIRED PATHS ${${package_name}_DIR} PATH_SUFFIXES ${package_name} NO_DEFAULT_PATH NO_MODULE QUIET) if(NOT ${package_name}_FOUND) find_package(${package_name} REQUIRED) endif() endmacro() function(mitkFunctionGetLibrarySearchPaths search_path intermediate_dir) set(_dir_candidates "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${MITK_CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}" "${MITK_CMAKE_LIBRARY_OUTPUT_DIRECTORY}/plugins" ) if(MITK_EXTERNAL_PROJECT_PREFIX) list(APPEND _dir_candidates "${MITK_EXTERNAL_PROJECT_PREFIX}/bin" "${MITK_EXTERNAL_PROJECT_PREFIX}/lib" ) endif() # Determine the Qt4/5 library installation prefix set(_qmake_location ) if(MITK_USE_Qt4) set(_qmake_location ${QT_QMAKE_EXECUTABLE}) elseif(MITK_USE_Qt5 AND TARGET ${Qt5Core_QMAKE_EXECUTABLE}) get_property(_qmake_location TARGET ${Qt5Core_QMAKE_EXECUTABLE} PROPERTY IMPORT_LOCATION) endif() if(_qmake_location) if(NOT _qt_install_libs) if(WIN32) execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_BINS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) else() execute_process(COMMAND ${_qmake_location} -query QT_INSTALL_LIBS OUTPUT_VARIABLE _qt_install_libs OUTPUT_STRIP_TRAILING_WHITESPACE) endif() file(TO_CMAKE_PATH "${_qt_install_libs}" _qt_install_libs) set(_qt_install_libs ${_qt_install_libs} CACHE INTERNAL "Qt library installation prefix" FORCE) endif() if(_qt_install_libs) list(APPEND _dir_candidates ${_qt_install_libs}) endif() elseif(MITK_USE_QT) message(WARNING "The qmake executable could not be found.") endif() get_property(_additional_paths GLOBAL PROPERTY MITK_ADDITIONAL_LIBRARY_SEARCH_PATHS) if(MITK_USE_HDF5) _find_package(HDF5) get_target_property(_location hdf5 LOCATION) get_filename_component(_location ${_location} PATH) list(APPEND _additional_paths ${_location}) # This is a work-around. The hdf5-config.cmake file is not robust enough # to be included several times via find_pakcage calls. set(HDF5_LIBRARIES ${HDF5_LIBRARIES} PARENT_SCOPE) endif() if(MITK_USE_Vigra) # we cannot use _find_package(Vigra) here because the vigra-config.cmake file # always includes the target-exports files without using an include guard. This # would lead to errors when another find_package(Vigra) call is processed. The # (bad) assumption here is that for the time being, only the Classification module # is using Vigra. if(UNIX) list(APPEND _additional_paths ${Vigra_DIR}/lib) else() list(APPEND _additional_paths ${Vigra_DIR}/bin) endif() endif() if(_additional_paths) list(APPEND _dir_candidates ${_additional_paths}) endif() # The code below is sub-optimal. It makes assumptions about # the structure of the build directories, pointed to by # the *_DIR variables. Instead, we should rely on package # specific "LIBRARY_DIRS" variables, if they exist. - if(WIN32) if(SOFA_DIR) list(APPEND _dir_candidates "${SOFA_DIR}/bin") endif() + if(REDLAND_INSTALL_DIR) + list(APPEND _dir_candidates "${REDLAND_INSTALL_DIR}/bin") + endif() + list(APPEND _dir_candidates "${ITK_DIR}/bin") else() if(SOFA_DIR) list(APPEND _dir_candidates "${SOFA_DIR}/lib") endif() endif() if(OpenCV_DIR) set(_opencv_link_directories "${OpenCV_LIB_DIR_DBG}" "${OpenCV_LIB_DIR_OPT}" "${OpenCV_3RDPARTY_LIB_DIR_DBG}" "${OpenCV_3RDPARTY_LIB_DIR_OPT}") list(REMOVE_DUPLICATES _opencv_link_directories) if(WIN32) foreach(_opencv_link_directory ${_opencv_link_directories}) list(APPEND _dir_candidates "${_opencv_link_directory}/../bin") endforeach() else() list(APPEND _dir_candidates ${_opencv_link_directories}) endif() endif() if(MITK_USE_Python) list(APPEND _dir_candidates "${CTK_DIR}/CMakeExternals/Install/bin") list(APPEND _dir_candidates "${MITK_EXTERNAL_PROJECT_PREFIX}/lib/python2.7/bin") endif() if(MITK_USE_TOF_PMDO3 OR MITK_USE_TOF_PMDCAMCUBE OR MITK_USE_TOF_PMDCAMBOARD) list(APPEND _dir_candidates "${MITK_PMD_SDK_DIR}/plugins" "${MITK_PMD_SDK_DIR}/bin") endif() if(MITK_USE_CTK) list(APPEND _dir_candidates "${CTK_LIBRARY_DIRS}") foreach(_ctk_library ${CTK_LIBRARIES}) if(${_ctk_library}_LIBRARY_DIRS) list(APPEND _dir_candidates "${${_ctk_library}_LIBRARY_DIRS}") endif() endforeach() endif() if(MITK_USE_BLUEBERRY) if(DEFINED CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY) if(IS_ABSOLUTE "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") list(APPEND _dir_candidates "${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") else() list(APPEND _dir_candidates "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${CTK_PLUGIN_RUNTIME_OUTPUT_DIRECTORY}") endif() endif() endif() if(MITK_LIBRARY_DIRS) list(APPEND _dir_candidates ${MITK_LIBRARY_DIRS}) endif() list(REMOVE_DUPLICATES _dir_candidates) set(_search_dirs ) foreach(_dir ${_dir_candidates}) if(EXISTS "${_dir}/${intermediate_dir}") list(APPEND _search_dirs "${_dir}/${intermediate_dir}") else() list(APPEND _search_dirs "${_dir}") endif() endforeach() # Special handling for "internal" search dirs. The intermediate directory # might not have been created yet, so we can't check for its existence. # Hence we just add it for Windows without checking. set(_internal_search_dirs "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/plugins") if(WIN32) foreach(_dir ${_internal_search_dirs}) set(_search_dirs "${_dir}/${intermediate_dir}" ${_search_dirs}) endforeach() else() set(_search_dirs ${_internal_search_dirs} ${_search_dirs}) endif() list(REMOVE_DUPLICATES _search_dirs) set(${search_path} ${_search_dirs} PARENT_SCOPE) endfunction() diff --git a/Modules/AppUtil/src/mitkBaseApplication.cpp b/Modules/AppUtil/src/mitkBaseApplication.cpp index eb2a4288c0..efefe64dc6 100644 --- a/Modules/AppUtil/src/mitkBaseApplication.cpp +++ b/Modules/AppUtil/src/mitkBaseApplication.cpp @@ -1,787 +1,787 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkBaseApplication.h" #include "mitkLogMacros.h" #include "mitkProvisioningInfo.h" #include "QmitkSafeApplication.h" #include "QmitkSingleApplication.h" #include #include #include #include #include #include #include #include #include #include #include #include #include namespace mitk { QString BaseApplication::ARG_NEWINSTANCE = "BlueBerry.newInstance"; QString BaseApplication::ARG_CLEAN = "BlueBerry.clean"; QString BaseApplication::ARG_APPLICATION = "BlueBerry.application"; QString BaseApplication::ARG_PRODUCT = "BlueBerry.product"; QString BaseApplication::ARG_HOME = "BlueBerry.home"; QString BaseApplication::ARG_STORAGE_DIR = "BlueBerry.storageDir"; QString BaseApplication::ARG_PLUGIN_CACHE = "BlueBerry.plugin_cache_dir"; QString BaseApplication::ARG_PLUGIN_DIRS = "BlueBerry.plugin_dirs"; QString BaseApplication::ARG_FORCE_PLUGIN_INSTALL = "BlueBerry.forcePlugins"; QString BaseApplication::ARG_PRELOAD_LIBRARY = "BlueBerry.preloadLibrary"; QString BaseApplication::ARG_PROVISIONING = "BlueBerry.provisioning"; QString BaseApplication::ARG_DEBUG = "BlueBerry.debug"; QString BaseApplication::ARG_CONSOLELOG = "BlueBerry.consoleLog"; QString BaseApplication::ARG_TESTPLUGIN = "BlueBerry.testplugin"; QString BaseApplication::ARG_TESTAPPLICATION = "BlueBerry.testapplication"; QString BaseApplication::ARG_NO_REGISTRY_CACHE = "BlueBerry.noRegistryCache"; QString BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING = "BlueBerry.noLazyRegistryCacheLoading"; QString BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE = "BlueBerry.registryMultiLanguage"; QString BaseApplication::ARG_XARGS = "xargs"; QString BaseApplication::PROP_NEWINSTANCE = BaseApplication::ARG_NEWINSTANCE; QString BaseApplication::PROP_FORCE_PLUGIN_INSTALL = BaseApplication::ARG_FORCE_PLUGIN_INSTALL; QString BaseApplication::PROP_NO_REGISTRY_CACHE = BaseApplication::ARG_NO_REGISTRY_CACHE; QString BaseApplication::PROP_NO_LAZY_REGISTRY_CACHE_LOADING = BaseApplication::ARG_NO_LAZY_REGISTRY_CACHE_LOADING; QString BaseApplication::PROP_REGISTRY_MULTI_LANGUAGE = BaseApplication::ARG_REGISTRY_MULTI_LANGUAGE; QString BaseApplication::PROP_PRODUCT = "blueberry.product"; QString BaseApplication::PROP_APPLICATION = "blueberry.application"; QString BaseApplication::PROP_TESTPLUGIN = "BlueBerry.testplugin"; QString BaseApplication::PROP_TESTAPPLICATION = "BlueBerry.testapplication"; struct BaseApplication::Impl { ctkProperties m_FWProps; QScopedPointer m_QApp; int m_Argc; char** m_Argv; QString m_AppName; QString m_OrgaName; QString m_OrgaDomain; bool m_SingleMode; bool m_SafeMode; QStringList m_PreloadLibs; QString m_ProvFile; Impl(int argc, char** argv) : m_Argc(argc) , m_Argv(argv) , m_SingleMode(false) , m_SafeMode(true) { #ifdef Q_OS_MAC /* * This is a workaround for bug 19080: * On Mac OS X the prosess serial number is passed as an commandline argument (-psn_) * if the application is started via the.app bundle. * This option is unknown, which causes a Poco exception. * Since this is done by the system we have to manually remove the argument here. */ int newArgc = m_Argc-1; char** newArgs = new char*[newArgc]; bool argFound (false); for (int i = 0; i < m_Argc; ++i) { - if (QString::fromAscii(m_Argv[i]).contains("-psn")) + if (QString::fromLatin1(m_Argv[i]).contains("-psn")) { argFound = true; } else { newArgs[i] = m_Argv[i]; } } if (argFound) { m_Argc = newArgc; m_Argv = newArgs; } #endif } QVariant getProperty(const QString& property) const { auto iter = m_FWProps.find(property); return iter == m_FWProps.end() ? QVariant() : iter.value(); } void handleBooleanOption(const std::string& name, const std::string& /*value*/) { QString fwKey = QString::fromStdString(name); // translate some keys to proper framework properties if (fwKey == ARG_CONSOLELOG) { fwKey = ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG; } // For all other options we use the command line option name as the // framework property key. m_FWProps[fwKey] = true; } void handlePreloadLibraryOption(const std::string& /*name*/, const std::string& value) { m_PreloadLibs.push_back(QString::fromStdString(value)); } void handleClean(const std::string& /*name*/, const std::string& /*value*/) { m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN] = ctkPluginConstants::FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT; } void initializeCTKPluginFrameworkProperties(Poco::Util::LayeredConfiguration& configuration) { // add all configuration key / value pairs as framework properties Poco::Util::LayeredConfiguration::Keys keys; Poco::Util::LayeredConfiguration::Keys keyStack; configuration.keys(keyStack); std::vector keyChain; while(!keyStack.empty()) { std::string currSubKey = keyStack.back(); if (!keyChain.empty() && keyChain.back() == currSubKey) { keyChain.pop_back(); keyStack.pop_back(); continue; } Poco::Util::LayeredConfiguration::Keys subKeys; configuration.keys(currSubKey, subKeys); if (subKeys.empty()) { keyStack.pop_back(); std::string finalKey; for (auto k = keyChain.begin(); k != keyChain.end(); ++k) { finalKey += *k + "."; } finalKey += currSubKey; keys.push_back(finalKey); } else { keyChain.push_back(currSubKey); for (auto s : subKeys) { keyStack.push_back(s); } } } for (auto key : keys) { QString qKey = QString::fromStdString(key); if (configuration.hasProperty(key)) { // ini and command line options overwrite already inserted keys m_FWProps[qKey] = QString::fromStdString(configuration.getString(key)); } } } void parseProvisioningFile(const QString& filePath) { // Skip parsing if the file path is empty if (filePath.isEmpty()) return; bool consoleLog = this->getProperty(ctkPluginFrameworkLauncher::PROP_CONSOLE_LOG).toBool(); // read initial plugins from a provisioning file QStringList pluginsToStart; QFileInfo provFile(filePath); if (provFile.exists()) { MITK_INFO(consoleLog) << "Using provisioning file: " << qPrintable(provFile.absoluteFilePath()); ProvisioningInfo provInfo(provFile.absoluteFilePath()); // it can still happen, that the encoding is not compatible with the fromUtf8 function ( i.e. when manipulating the LANG variable // in such case, the QStringList in provInfo is empty which we can easily check for if( provInfo.getPluginDirs().empty() ) { MITK_ERROR << "Cannot search for provisioning file, the retrieved directory list is empty.\n" << "This can occur if there are some special (non-ascii) characters in the install path."; } else { foreach(QString pluginPath, provInfo.getPluginDirs()) { ctkPluginFrameworkLauncher::addSearchPath(pluginPath); } //bool forcePluginOverwrite = this->getProperty(ARG_FORCE_PLUGIN_INSTALL).toBool(); QList pluginUrlsToStart = provInfo.getPluginsToStart(); for(auto url : pluginUrlsToStart) { pluginsToStart.push_back(url.toString()); } //foreach(QUrl pluginUrl, provInfo.getPluginsToInstall()) //{ // TODO for "uninstall", we need a proper configuration agent, e.g. a dedicated // plug-in for provisioning of the platform /* if (forcePluginOverwrite) { uninstallPugin(pluginUrl, context); } */ //try //{ //MITK_INFO(consoleLog) << "Installing CTK plug-in from: " << pluginUrl.toString().toStdString(); /* QSharedPointer plugin = context->installPlugin(pluginUrl); if (pluginsToStart.contains(pluginUrl)) { m_CTKPluginsToStart << plugin->getPluginId(); } */ /* } catch (const ctkPluginException& e) { QString errorMsg; QDebug dbg(&errorMsg); dbg << e.printStackTrace(); BERRY_ERROR << qPrintable(errorMsg); } */ //} } } else { MITK_INFO(consoleLog) << "No provisioning file set."; } if(!pluginsToStart.isEmpty()) { m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS] = pluginsToStart; // Use transient start with declared activation policy (this helps when // the provisioning file changes and some plug-ins should not be installed // in the application any more). ctkPlugin::StartOptions startOptions(ctkPlugin::START_TRANSIENT | ctkPlugin::START_ACTIVATION_POLICY); m_FWProps[ctkPluginFrameworkLauncher::PROP_PLUGINS_START_OPTIONS] = static_cast(startOptions); } } }; BaseApplication::BaseApplication(int argc, char** argv) : Application() , d(new Impl(argc, argv)) { } BaseApplication::~BaseApplication() { } void BaseApplication::printHelp(const std::string& /*name*/, const std::string& /*value*/) { Poco::Util::HelpFormatter help(this->options()); help.setAutoIndent(); help.setCommand(this->commandName()); help.format(std::cout); exit(EXIT_OK); } void BaseApplication::setApplicationName(const QString& name) { if (qApp) { qApp->setApplicationName(name); } d->m_AppName = name; } QString BaseApplication::getApplicationName() const { if (qApp) { return qApp->applicationName(); } return d->m_AppName; } void BaseApplication::setOrganizationName(const QString& name) { if (qApp) { qApp->setOrganizationName(name); } d->m_OrgaName = name; } QString BaseApplication::getOrganizationName() const { if (qApp) return qApp->organizationName(); return d->m_OrgaName; } void BaseApplication::setOrganizationDomain(const QString& domain) { if (qApp) { qApp->setOrganizationDomain(domain); } d->m_OrgaDomain = domain; } QString BaseApplication::getOrganizationDomain() const { if (qApp) return qApp->organizationDomain(); return d->m_OrgaDomain; } void BaseApplication::setSingleMode(bool singleMode) { if (qApp) return; d->m_SingleMode = singleMode; } bool BaseApplication::getSingleMode() const { return d->m_SingleMode; } void BaseApplication::setSafeMode(bool safeMode) { if (qApp && !d->m_QApp) return; d->m_SafeMode = safeMode; if (d->m_QApp) { if (getSingleMode()) { static_cast(d->m_QApp.data())->setSafeMode(safeMode); } else { static_cast(d->m_QApp.data())->setSafeMode(safeMode); } } } bool BaseApplication::getSafeMode() const { return d->m_SafeMode; } void BaseApplication::setPreloadLibraries(const QStringList& libraryBaseNames) { d->m_PreloadLibs = libraryBaseNames; } QStringList BaseApplication::getPreloadLibraries() const { return d->m_PreloadLibs; } void BaseApplication::setProvisioningFilePath(const QString& filePath) { d->m_ProvFile = filePath; } QString BaseApplication::getProvisioningFilePath() const { QString provFilePath = d->m_ProvFile; // A null QString means look up a default provisioning file if (provFilePath.isNull() && qApp) { QFileInfo appFilePath(QCoreApplication::applicationFilePath()); QDir basePath(QCoreApplication::applicationDirPath()); QString provFileName = appFilePath.baseName() + ".provisioning"; QFileInfo provFile(basePath.absoluteFilePath(provFileName)); #ifdef Q_OS_MAC /* * On Mac, if started from the build directory the .provisioning file is located at: * * but the executable path is: * * In this case we have to cdUp threetimes. * * During packaging however the MitkWorkbench.provisioning file is placed at the same * level like the executable, hence nothing has to be done. */ if (!provFile.exists()) { basePath.cdUp(); basePath.cdUp(); basePath.cdUp(); provFile = basePath.absoluteFilePath(provFileName); } #endif if (provFile.exists()) { provFilePath = provFile.absoluteFilePath(); } #ifdef CMAKE_INTDIR else { basePath.cdUp(); provFile.setFile(basePath.absoluteFilePath(provFileName)); if (provFile.exists()) { provFilePath = provFile.absoluteFilePath(); } } #endif } return provFilePath; } void BaseApplication::initializeQt() { if (qApp) return; // If previously parameters have been set we have to store them // to hand them through to the application QString appName = this->getApplicationName(); QString orgName = this->getOrganizationName(); QString orgDomain = this->getOrganizationDomain(); // Create a QCoreApplication instance this->getQApplication(); // provide parameters to QCoreApplication this->setApplicationName(appName); this->setOrganizationName(orgName); this->setOrganizationDomain(orgDomain); } void BaseApplication::initialize(Poco::Util::Application& self) { // 1. Call the super-class method Poco::Util::Application::initialize(self); // 2. Initialize the Qt framework (by creating a QCoreApplication) this->initializeQt(); // 3. Seed the random number generator, once at startup. QTime time = QTime::currentTime(); qsrand((uint)time.msec()); // 4. Load the "default" configuration, which involves parsing // an optional .ini file and parsing any // command line arguments this->loadConfiguration(); // 5. Add configuration data from the command line and the // optional .ini file as CTK plugin // framework properties. d->initializeCTKPluginFrameworkProperties(this->config()); // 6. Set the custom CTK Plugin Framework storage directory QString storageDir = this->getCTKFrameworkStorageDir(); if (!storageDir.isEmpty()) { d->m_FWProps[ctkPluginConstants::FRAMEWORK_STORAGE] = storageDir; } // 7. Set the library search paths and the pre-load library property this->initializeLibraryPaths(); QStringList preloadLibs = this->getPreloadLibraries(); if (!preloadLibs.isEmpty()) { d->m_FWProps[ctkPluginConstants::FRAMEWORK_PRELOAD_LIBRARIES] = preloadLibs; } // 8. Initialize the CppMicroServices library. // The initializeCppMicroServices() method reuses the // FRAMEWORK_STORAGE property, so we call it after the // getCTKFrameworkStorageDir method. this->initializeCppMicroServices(); // 9. Parse the (optional) provisioning file and set the // correct framework properties. d->parseProvisioningFile(this->getProvisioningFilePath()); // Finally, set the CTK Plugin Framework properties ctkPluginFrameworkLauncher::setFrameworkProperties(d->m_FWProps); } void BaseApplication::uninitialize() { QSharedPointer pfw = this->getFramework(); if (pfw) { pfw->stop(); // wait 10 seconds for the CTK plugin framework to stop pfw->waitForStop(10000); } Poco::Util::Application::uninitialize(); } int BaseApplication::getArgc() const { return d->m_Argc; } char**BaseApplication::getArgv() const { return d->m_Argv; } QString BaseApplication::getCTKFrameworkStorageDir() const { QString storageDir; if (this->getSingleMode()) { // This function checks if an instance is already running // and either sends a message to it (containing the command // line arguments) or checks if a new instance was forced by // providing the BlueBerry.newInstance command line argument. // In the latter case, a path to a temporary directory for // the new application's storage directory is returned. storageDir = handleNewAppInstance(static_cast(d->m_QApp.data()), d->m_Argc, d->m_Argv, ARG_NEWINSTANCE); } if (storageDir.isEmpty()) { // This is a new instance and no other instance is already running. We specify // the storage directory here (this is the same code as in berryInternalPlatform.cpp // so that we can re-use the location for the persistent data location of the // the CppMicroServices library. // Append a hash value of the absolute path of the executable to the data location. // This allows to start the same application from different build or install trees. #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) storageDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation) + "/" + this->getOrganizationName() + "/" + this->getApplicationName() + '_'; #else storageDir = QDesktopServices::storageLocation(QDesktopServices::DataLocation) + '_'; #endif storageDir += QString::number(qHash(QCoreApplication::applicationDirPath())) + "/"; } return storageDir; } void BaseApplication::initializeCppMicroServices() { QString storageDir = this->getProperty(ctkPluginConstants::FRAMEWORK_STORAGE).toString(); if (!storageDir.isEmpty()) { us::ModuleSettings::SetStoragePath((storageDir + QString("us") + QDir::separator()).toStdString()); } } QCoreApplication* BaseApplication::getQApplication() const { QCoreApplication* qCoreApp = qApp; if (!qCoreApp) { if (getSingleMode()) { qCoreApp = new QmitkSingleApplication(d->m_Argc, d->m_Argv, getSafeMode()); } else { auto safeApp = new QmitkSafeApplication(d->m_Argc, d->m_Argv); safeApp->setSafeMode(d->m_SafeMode); qCoreApp = safeApp; } d->m_QApp.reset(qCoreApp); } return qCoreApp; } void BaseApplication::initializeLibraryPaths() { QStringList suffixes; suffixes << "plugins"; #ifdef Q_OS_WINDOWS suffixes << "bin/plugins"; #ifdef CMAKE_INTDIR suffixes << "bin/" CMAKE_INTDIR "/plugins"; #endif #else suffixes << "lib/plugins"; #ifdef CMAKE_INTDIR suffixes << "lib/" CMAKE_INTDIR "/plugins"; #endif #endif #ifdef Q_OS_MAC suffixes << "../../plugins"; #endif // we add a couple of standard library search paths for plug-ins QDir appDir(QCoreApplication::applicationDirPath()); // walk one directory up and add bin and lib sub-dirs; this // might be redundant appDir.cdUp(); foreach(QString suffix, suffixes) { ctkPluginFrameworkLauncher::addSearchPath(appDir.absoluteFilePath(suffix)); } } int BaseApplication::main(const std::vector& /*args*/) { // Start the plugin framework and all installed plug-ins according with // their auto-start setting. return ctkPluginFrameworkLauncher::run().toInt(); } void BaseApplication::defineOptions(Poco::Util::OptionSet& options) { Poco::Util::Option helpOption("help", "h", "print this help text"); helpOption.callback(Poco::Util::OptionCallback(this, &BaseApplication::printHelp)); options.addOption(helpOption); Poco::Util::Option newInstanceOption(ARG_NEWINSTANCE.toStdString(), "", "forces a new instance of this application"); newInstanceOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(newInstanceOption); Poco::Util::Option cleanOption(ARG_CLEAN.toStdString(), "", "cleans the plugin cache"); cleanOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleClean)); options.addOption(cleanOption); Poco::Util::Option productOption(ARG_PRODUCT.toStdString(), "", "the id of the product to be launched"); productOption.argument("").binding(PROP_PRODUCT.toStdString()); options.addOption(productOption); Poco::Util::Option appOption(ARG_APPLICATION.toStdString(), "", "the id of the application extension to be executed"); appOption.argument("").binding(PROP_APPLICATION.toStdString()); options.addOption(appOption); Poco::Util::Option provOption(ARG_PROVISIONING.toStdString(), "", "the location of a provisioning file"); provOption.argument("").binding(ARG_PROVISIONING.toStdString()); options.addOption(provOption); Poco::Util::Option storageDirOption(ARG_STORAGE_DIR.toStdString(), "", "the location for storing persistent application data"); storageDirOption.argument("").binding(ctkPluginConstants::FRAMEWORK_STORAGE.toStdString()); options.addOption(storageDirOption); Poco::Util::Option consoleLogOption(ARG_CONSOLELOG.toStdString(), "", "log messages to the console"); consoleLogOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(consoleLogOption); Poco::Util::Option debugOption(ARG_DEBUG.toStdString(), "", "enable debug mode"); debugOption.argument("", false).binding(ctkPluginFrameworkLauncher::PROP_DEBUG.toStdString()); options.addOption(debugOption); Poco::Util::Option forcePluginOption(ARG_FORCE_PLUGIN_INSTALL.toStdString(), "", "force installing plug-ins with same symbolic name"); forcePluginOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(forcePluginOption); Poco::Util::Option preloadLibsOption(ARG_PRELOAD_LIBRARY.toStdString(), "", "preload a library"); preloadLibsOption.argument("").repeatable(true).callback(Poco::Util::OptionCallback(d.data(), &Impl::handlePreloadLibraryOption)); options.addOption(preloadLibsOption); Poco::Util::Option testPluginOption(ARG_TESTPLUGIN.toStdString(), "", "the plug-in to be tested"); testPluginOption.argument("").binding(PROP_TESTPLUGIN.toStdString()); options.addOption(testPluginOption); Poco::Util::Option testAppOption(ARG_TESTAPPLICATION.toStdString(), "", "the application to be tested"); testAppOption.argument("").binding(PROP_TESTAPPLICATION.toStdString()); options.addOption(testAppOption); Poco::Util::Option noRegistryCacheOption(ARG_NO_REGISTRY_CACHE.toStdString(), "", "do not use a cache for the registry"); noRegistryCacheOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(noRegistryCacheOption); Poco::Util::Option noLazyRegistryCacheLoadingOption(ARG_NO_LAZY_REGISTRY_CACHE_LOADING.toStdString(), "", "do not use lazy cache loading for the registry"); noLazyRegistryCacheLoadingOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(noLazyRegistryCacheLoadingOption); Poco::Util::Option registryMultiLanguageOption(ARG_REGISTRY_MULTI_LANGUAGE.toStdString(), "", "enable multi-language support for the registry"); registryMultiLanguageOption.callback(Poco::Util::OptionCallback(d.data(), &Impl::handleBooleanOption)); options.addOption(registryMultiLanguageOption); Poco::Util::Option xargsOption(ARG_XARGS.toStdString(), "", "Extended argument list"); xargsOption.argument("").binding(ARG_XARGS.toStdString()); options.addOption(xargsOption); Poco::Util::Application::defineOptions(options); } QSharedPointer BaseApplication::getFramework() const { return ctkPluginFrameworkLauncher::getPluginFramework(); } ctkPluginContext* BaseApplication::getFrameworkContext() const { QSharedPointer framework = getFramework(); if (framework) return framework->getPluginContext(); return nullptr; } QHash BaseApplication::getFrameworkProperties() const { return d->m_FWProps; } int BaseApplication::run() { this->init(d->m_Argc, d->m_Argv); return Application::run(); } void BaseApplication::setProperty(const QString& property, const QVariant& value) { d->m_FWProps[property] = value; } QVariant BaseApplication::getProperty(const QString& property) const { return d->getProperty(property); } } diff --git a/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp b/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp index 345fd6ddfe..6d407eb210 100644 --- a/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp +++ b/Modules/IGT/Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp @@ -1,344 +1,350 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataToIGTLMessageFilter.h" #include "igtlQuaternionTrackingDataMessage.h" #include "igtlTrackingDataMessage.h" #include "igtlTransformMessage.h" #include "igtlPositionMessage.h" #include #include mitk::NavigationDataToIGTLMessageFilter::NavigationDataToIGTLMessageFilter() { mitk::IGTLMessage::Pointer output = mitk::IGTLMessage::New(); this->SetNumberOfRequiredOutputs(1); this->SetNthOutput(0, output.GetPointer()); this->SetNumberOfRequiredInputs(1); // m_OperationMode = Mode3D; m_CurrentTimeStep = 0; // m_RingBufferSize = 50; //the default ring buffer size // m_NumberForMean = 100; } mitk::NavigationDataToIGTLMessageFilter::~NavigationDataToIGTLMessageFilter() { } void mitk::NavigationDataToIGTLMessageFilter::GenerateData() { switch (m_OperationMode) { case ModeSendQTDataMsg: this->GenerateDataModeSendQTDataMsg(); break; case ModeSendTDataMsg: this->GenerateDataModeSendTDataMsg(); break; case ModeSendQTransMsg: this->GenerateDataModeSendQTransMsg(); break; case ModeSendTransMsg: this->GenerateDataModeSendTransMsg(); break; default: break; } } void mitk::NavigationDataToIGTLMessageFilter::SetInput(const NavigationData* nd) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput(0, const_cast(nd)); this->CreateOutputsForAllInputs(); } void mitk::NavigationDataToIGTLMessageFilter::SetInput(unsigned int idx, const NavigationData* nd) { // Process object is not const-correct so the const_cast is required here this->ProcessObject::SetNthInput(idx, const_cast(nd)); this->CreateOutputsForAllInputs(); } const mitk::NavigationData* mitk::NavigationDataToIGTLMessageFilter::GetInput( void ) { if (this->GetNumberOfInputs() < 1) return NULL; return static_cast(this->ProcessObject::GetInput(0)); } const mitk::NavigationData* mitk::NavigationDataToIGTLMessageFilter::GetInput( unsigned int idx ) { if (this->GetNumberOfInputs() < 1) return NULL; return static_cast(this->ProcessObject::GetInput(idx)); } void mitk::NavigationDataToIGTLMessageFilter::CreateOutputsForAllInputs() { switch (m_OperationMode) { case ModeSendQTDataMsg: // create one message output for all navigation data inputs this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); // set the type for this filter this->SetType("QTDATA"); break; case ModeSendTDataMsg: // create one message output for all navigation data inputs this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); // set the type for this filter this->SetType("TDATA"); break; case ModeSendQTransMsg: // create one message output for all navigation data input together this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); // set the type for this filter this->SetType("POSITION"); break; case ModeSendTransMsg: // create one message output for all navigation data input together this->SetNumberOfIndexedOutputs(this->GetNumberOfIndexedInputs()); // set the type for this filter this->SetType("TRANS"); break; default: break; } for (unsigned int idx = 0; idx < this->GetNumberOfIndexedOutputs(); ++idx) { if (this->GetOutput(idx) == NULL) { DataObjectPointer newOutput = this->MakeOutput(idx); this->SetNthOutput(idx, newOutput); } this->Modified(); } } void ConvertAffineTransformationIntoIGTLMatrix(mitk::AffineTransform3D* trans, igtl::Matrix4x4 igtlTransform) { const mitk::AffineTransform3D::MatrixType& matrix = trans->GetMatrix(); mitk::Vector3D position = trans->GetOffset(); //copy the data into a matrix type that igtl understands for ( unsigned int r = 0; r < 3; r++ ) { for ( unsigned int c = 0; c < 3; c++ ) { igtlTransform[r][c] = matrix(r,c); } igtlTransform[r][3] = position[r]; } for ( unsigned int c = 0; c < 3; c++ ) { igtlTransform[3][c] = 0.0; } igtlTransform[3][3] = 1.0; } void mitk::NavigationDataToIGTLMessageFilter::GenerateDataModeSendQTransMsg() { // for each output message for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs() ; ++i) { mitk::IGTLMessage* output = this->GetOutput(i); assert(output); const mitk::NavigationData* input = this->GetInput(i); assert(input); // do not add navigation data to message if input is invalid if (input->IsDataValid() == false) continue; //get the navigation data components mitk::NavigationData::PositionType pos = input->GetPosition(); mitk::NavigationData::OrientationType ori = input->GetOrientation(); //insert this information into the message igtl::PositionMessage::Pointer posMsg = igtl::PositionMessage::New(); posMsg->SetPosition(pos[0], pos[1], pos[2]); posMsg->SetQuaternion(ori[0], ori[1], ori[2], ori[3]); posMsg->SetTimeStamp((unsigned int)input->GetIGTTimeStamp(), 0); posMsg->SetDeviceName(input->GetName()); posMsg->Pack(); //add the igtl message to the mitk::IGTLMessage output->SetMessage(posMsg.GetPointer()); } } void mitk::NavigationDataToIGTLMessageFilter::GenerateDataModeSendTransMsg() { // for each output message for (unsigned int i = 0; i < this->GetNumberOfIndexedOutputs() ; ++i) { mitk::IGTLMessage* output = this->GetOutput(i); assert(output); const mitk::NavigationData* input = this->GetInput(i); assert(input); // do not add navigation data to message if input is invalid if (input->IsDataValid() == false) continue; //get the navigation data components mitk::AffineTransform3D::Pointer transform = input->GetAffineTransform3D(); mitk::NavigationData::PositionType position = transform->GetOffset(); //convert the transform into a igtl type igtl::Matrix4x4 igtlTransform; ConvertAffineTransformationIntoIGTLMatrix(transform, igtlTransform); //insert this information into the message igtl::TransformMessage::Pointer transMsg = igtl::TransformMessage::New(); transMsg->SetMatrix(igtlTransform); transMsg->SetPosition(position[0], position[1], position[2]); transMsg->SetTimeStamp((unsigned int)input->GetIGTTimeStamp(), 0); transMsg->SetDeviceName(input->GetName()); transMsg->Pack(); //add the igtl message to the mitk::IGTLMessage output->SetMessage(transMsg.GetPointer()); } } void mitk::NavigationDataToIGTLMessageFilter::GenerateDataModeSendQTDataMsg() { mitk::IGTLMessage* output = this->GetOutput(); assert(output); //create a output igtl message igtl::QuaternionTrackingDataMessage::Pointer qtdMsg = igtl::QuaternionTrackingDataMessage::New(); mitk::NavigationData::PositionType pos; mitk::NavigationData::OrientationType ori; for (unsigned int index = 0; index < this->GetNumberOfIndexedInputs(); index++) { const mitk::NavigationData* nd = GetInput(index); assert(nd); //get the navigation data components pos = nd->GetPosition(); ori = nd->GetOrientation(); //insert the information into the tracking element igtl::QuaternionTrackingDataElement::Pointer tde = igtl::QuaternionTrackingDataElement::New(); tde->SetPosition(pos[0], pos[1], pos[2]); tde->SetQuaternion(ori[0], ori[1], ori[2], ori[3]); tde->SetName(nd->GetName()); //insert this element into the tracking data message qtdMsg->AddQuaternionTrackingDataElement(tde); //copy the time stamp //todo find a better way to do that qtdMsg->SetTimeStamp((unsigned int)nd->GetIGTTimeStamp(), 0); } qtdMsg->Pack(); //add the igtl message to the mitk::IGTLMessage output->SetMessage(qtdMsg.GetPointer()); } void mitk::NavigationDataToIGTLMessageFilter::GenerateDataModeSendTDataMsg() { bool isValidData = true; mitk::IGTLMessage* output = this->GetOutput(); assert(output); //create a output igtl message igtl::TrackingDataMessage::Pointer tdMsg = igtl::TrackingDataMessage::New(); mitk::AffineTransform3D::Pointer transform; Vector3D position; igtl::Matrix4x4 igtlTransform; vnl_matrix_fixed rotationMatrix; vnl_matrix_fixed rotationMatrixTransposed; for (unsigned int index = 0; index < this->GetNumberOfIndexedInputs(); index++) { const mitk::NavigationData* nd = GetInput(index); assert(nd); //create a new tracking element igtl::TrackingDataElement::Pointer tde = igtl::TrackingDataElement::New(); //get the navigation data components transform = nd->GetAffineTransform3D(); position = transform->GetOffset(); //check the rotation matrix rotationMatrix = transform->GetMatrix().GetVnlMatrix(); rotationMatrixTransposed = rotationMatrix.transpose(); // a quadratic matrix is a rotation matrix exactly when determinant is 1 // and transposed is inverse if (!Equal(1.0, vnl_det(rotationMatrix), 0.1) || !((rotationMatrix*rotationMatrixTransposed).is_identity(0.1))) { //the rotation matrix is not valid! => invalidate the current element isValidData = false; } //convert the transform into a igtl type ConvertAffineTransformationIntoIGTLMatrix(transform, igtlTransform); //fill the tracking element with life tde->SetMatrix(igtlTransform); tde->SetPosition(position[0], position[1], position[2]); - tde->SetName(nd->GetName()); + std::stringstream name; + name << nd->GetName(); + if (name.rdbuf()->in_avail() == 0 ) + { + name << "TrackingTool" << index; + } + tde->SetName(name.str().c_str()); //insert this element into the tracking data message tdMsg->AddTrackingDataElement(tde); //copy the time stamp //todo find a better way to do that tdMsg->SetTimeStamp((unsigned int)nd->GetIGTTimeStamp(), 0); } tdMsg->Pack(); //add the igtl message to the mitk::IGTLMessage output->SetMessage(tdMsg.GetPointer()); output->SetDataValid(isValidData); } void mitk::NavigationDataToIGTLMessageFilter::SetOperationMode( OperationMode mode ) { m_OperationMode = mode; this->Modified(); this->CreateOutputsForAllInputs(); } void mitk::NavigationDataToIGTLMessageFilter::ConnectTo( mitk::NavigationDataSource* UpstreamFilter) { for (DataObjectPointerArraySizeType i = 0; i < UpstreamFilter->GetNumberOfOutputs(); i++) { this->SetInput(i, UpstreamFilter->GetOutput(i)); } } diff --git a/Modules/IGT/Algorithms/mitkNavigationDataToPointSetFilter.h b/Modules/IGT/Algorithms/mitkNavigationDataToPointSetFilter.h index 5fc6912d8c..22e9c32315 100644 --- a/Modules/IGT/Algorithms/mitkNavigationDataToPointSetFilter.h +++ b/Modules/IGT/Algorithms/mitkNavigationDataToPointSetFilter.h @@ -1,159 +1,160 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITKNAVIGATIONDATATOPOINTSETFILTER_H__ #define _MITKNAVIGATIONDATATOPOINTSETFILTER_H__ #include "mitkCommon.h" #include "mitkPointSet.h" #include "mitkPointSetSource.h" #include "mitkNavigationData.h" +#include "MitkIGTExports.h" namespace mitk { /**Documentation * * \brief This filter creates mitk::PointSet objects from mitk::NavigaitionData objects * * This filter has two modes that can be set with SetOperationMode(). * - Mode3D: every input NavigationData is processed into one output pointset. For each call to Update() a point with the ND position will be added to the PointSet * - Mode4D: one output pointset is generated that contains one point for each input NavigationData. Each call to Update() adds a new timestep to the PointSet that contains new positions for the points. * * \ingroup IGT * */ class MITKIGT_EXPORT NavigationDataToPointSetFilter : public PointSetSource { public: mitkClassMacro(NavigationDataToPointSetFilter, PointSetSource); itkFactorylessNewMacro(Self) itkCloneMacro(Self) /**Documentation * \brief There are two different operation modes. * * - Mode3D: every input NavigationData is processed into one output pointset that contains a point with the ND position for each Update() * - Mode3DMean: a defined number of input NavigationData is used to generate a mean position and processed into one output pointset that contains a point with the ND position for each Update() * - Mode4D: one output pointset is generated that contains one point for each input NavigationData. Each call to Update() adds a new timestep to the PointSet that contains new positions for the points. * The RingBufferSize limits the number of timesteps in the 4D mode. It currently does _not_ limit the number of points in the 3D mode. */ enum OperationMode { Mode3D, Mode3DMean, Mode4D }; /**Documentation * \brief Sets the size for the ring buffer. * * The size determines the maximum number of timesteps in 4D mode and the number of points in 3D mode of the output PointSet */ itkSetMacro(RingBufferSize, unsigned int) /** * \brief Sets the number of Navigation Data, which should be averaged. */ itkSetMacro(NumberForMean, unsigned int) /** * \brief Gets the number of Navigation Data, which should be averaged. */ itkGetMacro(NumberForMean, unsigned int); /** * \brief filter execute method */ virtual void GenerateData() override; using Superclass::SetInput; /** * \brief Sets one input NavigationData */ virtual void SetInput(const mitk::NavigationData *NavigationData); /** * \brief Sets the input NavigationData at a specific index */ virtual void SetInput(unsigned int idx, const NavigationData* nd); /** * \brief Returns the input of this filter */ const mitk::NavigationData* GetInput(); /** * \brief Returns the input number idx of this filter */ const mitk::NavigationData* GetInput(unsigned int idx); /** * \brief Sets the mode of this filter. * * See OperationMode for the behavior in the different modes * \warn A call to this method will change the number of outputs of the filter. * After calling this method, all previously acquired pointers to outputs are invalid * Always set the operation mode first, then get the outputs with GetOutput() */ virtual void SetOperationMode(OperationMode mode); /** * \brief returns the mode of this filter. * * See OperationMode for the behavior in the different modes */ itkGetConstMacro(OperationMode, OperationMode); void GenerateOutputInformation() override {}; ///< empty implementation to prevent calling of the superclass method that would try to copy information from the input NavigationData to the output PointSet, which makes no sense! protected: NavigationDataToPointSetFilter(); virtual ~NavigationDataToPointSetFilter(); /** * \brief Generates the output for Mode3D * */ virtual void GenerateDataMode3D(); /** * \brief Generates the output for Mode3DMean * */ virtual void GenerateDataMode3DMean(); /** * \brief Generates the output for Mode4D */ virtual void GenerateDataMode4D(); /** * \brief create output objects according to OperationMode for all inputs */ virtual void CreateOutputsForAllInputs(); OperationMode m_OperationMode; ///< Stores the mode. See enum OperationMode unsigned int m_RingBufferSize; ///< Stores the ringbuffer size unsigned int m_CurrentTimeStep; ///< Indicates the current timestamp unsigned int m_NumberForMean; ///< Number of Navigation Data, which should be averaged }; } // namespace mitk #endif // _MITKNAVIGATIONDATATOPOINTSETFILTER_H__ diff --git a/Modules/IGT/Common/mitkTrackingTypes.h b/Modules/IGT/Common/mitkTrackingTypes.h index 9472046dc9..92cb699cc1 100644 --- a/Modules/IGT/Common/mitkTrackingTypes.h +++ b/Modules/IGT/Common/mitkTrackingTypes.h @@ -1,242 +1,245 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKTRACKINGTYPES_H_HEADER_INCLUDED_ #define MITKTRACKINGTYPES_H_HEADER_INCLUDED_ #include #include #include #include namespace mitk { /**Documentation * \brief Error codes of NDI tracking devices */ enum NDIErrorCode { NDIOKAY = 0, NDIERROR = 1, SERIALINTERFACENOTSET, SERIALSENDERROR, SERIALRECEIVEERROR, SROMFILETOOLARGE, SROMFILETOOSMALL, NDICRCERROR, // reply has crc error, local computer detected the error NDIINVALIDCOMMAND, NDICOMMANDTOOLONG, NDICOMMANDTOOSHORT, NDICRCDOESNOTMATCH, // command had crc error, tracking device detected the error NDITIMEOUT, NDIUNABLETOSETNEWCOMMPARAMETERS, NDIINCORRECTNUMBEROFPARAMETERS, NDIINVALIDPORTHANDLE, NDIINVALIDTRACKINGPRIORITY, NDIINVALIDLED, NDIINVALIDLEDSTATE, NDICOMMANDINVALIDINCURRENTMODE, NDINOTOOLFORPORT, NDIPORTNOTINITIALIZED, NDISYSTEMNOTINITIALIZED, NDIUNABLETOSTOPTRACKING, NDIUNABLETOSTARTTRACKING, NDIINITIALIZATIONFAILED, NDIINVALIDVOLUMEPARAMETERS, NDICANTSTARTDIAGNOSTICMODE, NDICANTINITIRDIAGNOSTICS, NDIFAILURETOWRITESROM, NDIENABLEDTOOLSNOTSUPPORTED, NDICOMMANDPARAMETEROUTOFRANGE, NDINOMEMORYAVAILABLE, NDIPORTHANDLENOTALLOCATED, NDIPORTHASBECOMEUNOCCUPIED, NDIOUTOFHANDLES, NDIINCOMPATIBLEFIRMWAREVERSIONS, NDIINVALIDPORTDESCRIPTION, NDIINVALIDOPERATIONFORDEVICE, NDIWARNING, NDIUNKNOWNERROR, NDIUNEXPECTEDREPLY, UNKNOWNHANDLERETURNED, TRACKINGDEVICERESET, TRACKINGDEVICENOTSET }; /**Documentation * \brief identifier for tracking device. The way it is currently used * represents a product line rather than an actal type. Refactoring is a future option. */ enum TrackingDeviceType { - NDIPolaris, ///< Polaris: optical Tracker from NDI - NDIAurora, ///< Aurora: electromagnetic Tracker from NDI - ClaronMicron, ///< Micron Tracker: optical Tracker from Claron - IntuitiveDaVinci, ///< Intuitive Surgical: DaVinci Telemanipulator API Interface - AscensionMicroBird, ///< Ascension microBird / PCIBird family - VirtualTracker, ///< Virtual Tracking device class that produces random tracking coordinates - TrackingSystemNotSpecified,///< entry for not specified or initialized tracking system + NDIPolaris, ///< Polaris: optical Tracker from NDI + NDIAurora, ///< Aurora: electromagnetic Tracker from NDI + ClaronMicron, ///< Micron Tracker: optical Tracker from Claron + IntuitiveDaVinci, ///< Intuitive Surgical: DaVinci Telemanipulator API Interface + AscensionMicroBird, ///< Ascension microBird / PCIBird family + VirtualTracker, ///< Virtual Tracking device class that produces random tracking coordinates + TrackingSystemNotSpecified, ///< entry for not specified or initialized tracking system TrackingSystemInvalid, ///< entry for invalid state (mainly for testing) - NPOptitrack ///< NaturalPoint: Optitrack optical Tracking System + NPOptitrack, ///< NaturalPoint: Optitrack optical Tracking System + OpenIGTLinkTrackingDeviceConnection ///< Device which is connected via open igt link }; /**Documentation * \brief Error codes of NDI tracking devices */ enum OperationMode { ToolTracking6D, ToolTracking5D, MarkerTracking3D, HybridTracking }; /** * /brief This structure defines key variables of a device model and type. * It is specifically used to find out which models belong to which vendor, and what volume * to use for a specific Model. Leaving VolumeModelLocation set to null will instruct the Generator * to generate a field to the best of his ability. HardwareCode stands for a hexadecimal string, * that represents the tracking volume. "X" stands for "hardwarecode is not known" or "tracking device has * no hardware code". For NDI devices it is used in the SetVolume() Method in mitkNDITrackingDevice.cpp. * The Pyramid Volume has the hardwarecode "4", but it is not supported yet. */ struct TrackingDeviceData { TrackingDeviceType Line; std::string Model; std::string VolumeModelLocation; std::string HardwareCode; }; /** * Here all supported devices are defined. Dont forget to introduce new Devices into the TrackingDeviceList Array at the bottom! * If a model does not have a corresponding tracking volume yet, pass an empty string to denote "No Model". pass "cube" to render * a default cube of 400x400 px. You can define additional magic strings in the TrackingVolumeGenerator. */ //############## NDI Aurora device data ############# static TrackingDeviceData DeviceDataAuroraCompact = {NDIAurora, "Aurora Compact", "NDIAuroraCompactFG_Dome.stl", "A"}; static TrackingDeviceData DeviceDataAuroraPlanarCube = {NDIAurora, "Aurora Planar (Cube)", "NDIAurora.stl", "9"}; static TrackingDeviceData DeviceDataAuroraPlanarDome = {NDIAurora, "Aurora Planar (Dome)","NDIAuroraPlanarFG_Dome.stl", "A"}; static TrackingDeviceData DeviceDataAuroraTabletop = {NDIAurora, "Aurora Tabletop", "NDIAuroraTabletopFG_Dome.stl", "A"}; // The following entry is for the tabletop prototype, which had an lower barrier of 8cm. The new version has a lower barrier of 12cm. //static TrackingDeviceData DeviceDataAuroraTabletopPrototype = {NDIAurora, "Aurora Tabletop Prototype", "NDIAuroraTabletopFG_Prototype_Dome.stl"}; //############## NDI Polaris device data ############ static TrackingDeviceData DeviceDataPolarisOldModel = {NDIPolaris, "Polaris (Old Model)", "NDIPolarisOldModel.stl", "0"}; //full hardware code of polaris spectra: 5-240000-153200-095000+057200+039800+056946+024303+029773+999999+99999924 static TrackingDeviceData DeviceDataPolarisSpectra = {NDIPolaris, "Polaris Spectra", "NDIPolarisSpectra.stl", "5-2"}; //full hardware code of polaris spectra (extended pyramid): 5-300000-153200-095000+057200+039800+056946+024303+029773+999999+07350024 static TrackingDeviceData DeviceDataSpectraExtendedPyramid = {NDIPolaris, "Polaris Spectra (Extended Pyramid)", "NDIPolarisSpectraExtendedPyramid.stl","5-3"}; static TrackingDeviceData DeviceDataPolarisVicra = {NDIPolaris, "Polaris Vicra", "NDIPolarisVicra.stl","7"}; - //############## NDI Polaris device data ############ + //############## NP Optitrack device data ############ static TrackingDeviceData DeviceDataNPOptitrack = {NPOptitrack, "Optitrack", "cube", "X"}; //############## other device data ################## static TrackingDeviceData DeviceDataDaVinci = {IntuitiveDaVinci, "Intuitive DaVinci", "IntuitiveDaVinci.stl","X"}; static TrackingDeviceData DeviceDataMicroBird = {AscensionMicroBird, "Ascension MicroBird", "", "X"}; static TrackingDeviceData DeviceDataVirtualTracker = {VirtualTracker, "Virtual Tracker", "cube","X"}; static TrackingDeviceData DeviceDataMicronTrackerH40 = {ClaronMicron, "Micron Tracker H40", "ClaronMicron.stl", "X"}; static TrackingDeviceData DeviceDataUnspecified = {TrackingSystemNotSpecified, "Unspecified System", "cube","X"}; + static TrackingDeviceData DeviceDataOpenIGTLinkTrackingDeviceConnection = {OpenIGTLinkTrackingDeviceConnection, "OpenIGTLink Tracking Device", "cube","X"}; // Careful when changing the "invalid" device: The mitkTrackingTypeTest is using it's data. static TrackingDeviceData DeviceDataInvalid = {TrackingSystemInvalid, "Invalid Tracking System", "", "X"}; //This list should hold all devices defined above! static TrackingDeviceData TrackingDeviceList[] = {DeviceDataAuroraPlanarCube, DeviceDataAuroraPlanarDome, DeviceDataAuroraCompact, DeviceDataAuroraTabletop, DeviceDataMicronTrackerH40, DeviceDataPolarisSpectra, DeviceDataPolarisVicra, DeviceDataNPOptitrack, - DeviceDataDaVinci, DeviceDataMicroBird, DeviceDataVirtualTracker, DeviceDataUnspecified, DeviceDataSpectraExtendedPyramid, DeviceDataInvalid, DeviceDataPolarisOldModel}; + DeviceDataDaVinci, DeviceDataMicroBird, DeviceDataVirtualTracker, DeviceDataUnspecified, DeviceDataSpectraExtendedPyramid, DeviceDataInvalid, DeviceDataPolarisOldModel, + DeviceDataOpenIGTLinkTrackingDeviceConnection}; /** * /brief Returns all devices compatibel to the given Line of Devices */ MITKIGT_EXPORT std::vector GetDeviceDataForLine(TrackingDeviceType Type); /** * /brief Returns the first TracingDeviceData mathing a given line. Useful for backward compatibility * with the old way to manage Devices */ MITKIGT_EXPORT TrackingDeviceData GetFirstCompatibleDeviceDataForLine(TrackingDeviceType Type); /** * /brief Returns the device Data set matching the model name or the invalid device, if none was found */ MITKIGT_EXPORT TrackingDeviceData GetDeviceDataByName(const std::string& modelName); /**Documentation * \brief activation rate of IR illuminator for NDI Polaris tracking device */ enum IlluminationActivationRate { Hz20 = 20, Hz30 = 30, Hz60 = 60 }; /**Documentation * \brief Data transfer mode for NDI tracking devices */ enum DataTransferMode { TX = 0, BX = 1 }; /**Documentation * \brief Query mode for NDI tracking devices */ enum PHSRQueryType { ALL = 0x00, FREED = 0x01, OCCUPIED = 0x02, INITIALIZED = 0x03, ENABLED = 0x04 }; typedef itk::Point MarkerPointType; typedef std::vector MarkerPointContainerType; /** * \brief Defines the tools (arms) of the daVinci system: * PSM1 - Patient side manipulator 1 * PSM2 - Patient side manipulator 2 * ECM - Endoscopic camera manipulator * MTML - Left master target manipulator * MTMR - Right master target manipulator * PSM - Patient side manipulator 3 (if not existent, its data will always be zero) **/ enum DaVinciToolType { PSM1 = 0, PSM2 = 1, ECM = 2, MTML = 3, MTMR = 4, PSM = 5, //UIEvents = 6, }; /** definition of a colors for IGT */ static mitk::Color IGTColor_WARNING = mitk::ColorProperty::New(1.0f, 0.0f, 0.0f)->GetColor(); static mitk::Color IGTColor_VALID = mitk::ColorProperty::New(0.0f, 1.0f, 0.0f)->GetColor(); } // namespace mitk #endif /* MITKTRACKINGTYPES_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp b/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp index 45d3b67ef0..2aeb6ebe33 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp +++ b/Modules/IGT/DataManagement/mitkNavigationDataSource.cpp @@ -1,155 +1,156 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataSource.h" #include "mitkUIDGenerator.h" + //Microservices #include #include #include #include const std::string mitk::NavigationDataSource::US_INTERFACE_NAME = "org.mitk.services.NavigationDataSource"; const std::string mitk::NavigationDataSource::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; const std::string mitk::NavigationDataSource::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; const std::string mitk::NavigationDataSource::US_PROPKEY_ISACTIVE = US_INTERFACE_NAME + ".isActive"; mitk::NavigationDataSource::NavigationDataSource() : itk::ProcessObject(), m_Name("NavigationDataSource (no defined type)"), m_IsFrozen(false) { } mitk::NavigationDataSource::~NavigationDataSource() { } mitk::NavigationData* mitk::NavigationDataSource::GetOutput() { if (this->GetNumberOfIndexedOutputs() < 1) return NULL; return static_cast(this->ProcessObject::GetPrimaryOutput()); } mitk::NavigationData* mitk::NavigationDataSource::GetOutput(DataObjectPointerArraySizeType idx) { NavigationData* out = dynamic_cast( this->ProcessObject::GetOutput(idx) ); if ( out == NULL && this->ProcessObject::GetOutput(idx) != NULL ) { itkWarningMacro (<< "Unable to convert output number " << idx << " to type " << typeid( NavigationData ).name () ); } return out; } mitk::NavigationData* mitk::NavigationDataSource::GetOutput(const std::string& navDataName) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) if (navDataName == (static_cast(it->GetPointer()))->GetName()) return static_cast(it->GetPointer()); return NULL; } itk::ProcessObject::DataObjectPointerArraySizeType mitk::NavigationDataSource::GetOutputIndex( std::string navDataName ) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) if (navDataName == (static_cast(outputs.at(i).GetPointer()))->GetName()) return i; throw std::invalid_argument("output name does not exist"); } void mitk::NavigationDataSource::RegisterAsMicroservice(){ // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator ("org.mitk.services.NavigationDataSource.id_", 16); props[ US_PROPKEY_ID ] = uidGen.GetUID(); props[ US_PROPKEY_DEVICENAME ] = m_Name; m_ServiceRegistration = context->RegisterService(this, props); } void mitk::NavigationDataSource::UnRegisterMicroservice(){ if (m_ServiceRegistration != NULL) m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } std::string mitk::NavigationDataSource::GetMicroserviceID(){ return this->m_ServiceRegistration.GetReference().GetProperty(US_PROPKEY_ID).ToString(); } void mitk::NavigationDataSource::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::NavigationDataSource::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfIndexedOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter only has " << this->GetNumberOfIndexedOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a NULL pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" ); } // Call Graft on NavigationData to copy member data output->Graft( graft ); } itk::DataObject::Pointer mitk::NavigationDataSource::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) { return mitk::NavigationData::New().GetPointer(); } itk::DataObject::Pointer mitk::NavigationDataSource::MakeOutput( const DataObjectIdentifierType & name ) { itkDebugMacro("MakeOutput(" << name << ")"); if( this->IsIndexedOutputName(name) ) { return this->MakeOutput( this->MakeIndexFromOutputName(name) ); } return static_cast(mitk::NavigationData::New().GetPointer()); } mitk::PropertyList::ConstPointer mitk::NavigationDataSource::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); // add properties to p like this: //p->SetProperty("MyFilter_MyParameter", mitk::PropertyDataType::New(m_MyParameter)); return mitk::PropertyList::ConstPointer(p); } void mitk::NavigationDataSource::Freeze() { m_IsFrozen = true; } void mitk::NavigationDataSource::UnFreeze() { m_IsFrozen = false; } diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSource.h b/Modules/IGT/DataManagement/mitkNavigationDataSource.h index 3407fd4a21..9706e9bd68 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSource.h +++ b/Modules/IGT/DataManagement/mitkNavigationDataSource.h @@ -1,185 +1,186 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNAVIGATIONDATASOURCE_H_HEADER_INCLUDED_ #define MITKNAVIGATIONDATASOURCE_H_HEADER_INCLUDED_ #include #include "mitkNavigationData.h" #include "mitkPropertyList.h" +#include "MitkIGTExports.h" // Microservices #include #include namespace mitk { /**Documentation * \brief Navigation Data source * * Base class for all navigation filters that produce NavigationData objects as output. * This class defines the output-interface for NavigationDataFilters. * \warning: if Update() is called on any output object, all NavigationData filters will * generate new output data for all outputs, not just the one on which Update() was called. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationDataSource : public itk::ProcessObject { public: mitkClassMacroItkParent(NavigationDataSource, itk::ProcessObject); /** @return Returns a human readable name of this source. There will be a default name, * or you can set the name with the method SetName() if you want to change it. */ itkGetMacro(Name,std::string); /** @brief Sets the human readable name of this source. There is also a default name, * but you can use this method if you need to define it on your own. */ itkSetMacro(Name,std::string); /** *\brief return the output (output with id 0) of the filter */ NavigationData* GetOutput(void); /** *\brief return the output with id idx of the filter */ NavigationData* GetOutput(DataObjectPointerArraySizeType idx); /** *\brief return the output with name navDataName of the filter */ NavigationData* GetOutput(const std::string& navDataName); /** *\brief return the index of the output with name navDataName, -1 if no output with that name was found * * \warning if a subclass has outputs that have different data type than mitk::NavigationData, they have to overwrite this method */ DataObjectPointerArraySizeType GetOutputIndex(std::string navDataName); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. * To unregister, call UnregisterMicroservice(). */ virtual void RegisterAsMicroservice(); /** *\brief Registers this object as a Microservice, making it available to every module and/or plugin. */ virtual void UnRegisterMicroservice(); /** *\brief Returns the id that this device is registered with. The id will only be valid, if the * NavigationDataSource has been registered using RegisterAsMicroservice(). */ std::string GetMicroserviceID(); /** *\brief These Constants are used in conjunction with Microservices */ static const std::string US_INTERFACE_NAME; static const std::string US_PROPKEY_DEVICENAME; static const std::string US_PROPKEY_ID; static const std::string US_PROPKEY_ISACTIVE; //NOT IMPLEMENTED YET! /** *\brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::GraftNthOutput for details */ virtual void GraftNthOutput(unsigned int idx, itk::DataObject *graft); /** * \brief Graft the specified DataObject onto this ProcessObject's output. * * See itk::ImageSource::Graft Output for details */ virtual void GraftOutput(itk::DataObject *graft); /** * Allocates a new output object and returns it. Currently the * index idx is not evaluated. * @param idx the index of the output for which an object should be created * @returns the new object */ virtual itk::DataObject::Pointer MakeOutput ( DataObjectPointerArraySizeType idx ) override; /** * This is a default implementation to make sure we have something. * Once all the subclasses of ProcessObject provide an appopriate * MakeOutput(), then ProcessObject::MakeOutput() can be made pure * virtual. */ virtual itk::DataObject::Pointer MakeOutput(const DataObjectIdentifierType &name) override; /** * \brief Set all filter parameters as the PropertyList p * * This method allows to set all parameters of a filter with one * method call. For the names of the parameters, take a look at * the GetParameters method of the filter * This method has to be overwritten by each MITK-IGT filter. */ virtual void SetParameters(const mitk::PropertyList*){}; /** * \brief Get all filter parameters as a PropertyList * * This method allows to get all parameters of a filter with one * method call. The returned PropertyList must be assigned to a * SmartPointer immediately, or else it will get destroyed. * Every filter must overwrite this method to create a filter-specific * PropertyList. Note that property names must be unique over all * MITK-IGT filters. Therefore each filter should use its name as a prefix * for each property name. * Secondly, each filter should list the property names and data types * in the method documentation. */ virtual mitk::PropertyList::ConstPointer GetParameters() const; /** Freezes the navigation data source which means the current state is frozen and the output * navigation data stays at it is. Calling Update() does not have any effect until UnFreeze() * is called. This also means that the data source is not updated any more. */ virtual void Freeze(); /** Unfreezes the data source. */ virtual void UnFreeze(); /** @return Returns whether the data source is currently frozen. */ itkGetMacro(IsFrozen,bool); protected: NavigationDataSource(); virtual ~NavigationDataSource(); std::string m_Name; bool m_IsFrozen; private: us::ServiceRegistration m_ServiceRegistration; }; } // namespace mitk // This is the microservice declaration. Do not meddle! MITK_DECLARE_SERVICE_INTERFACE(mitk::NavigationDataSource, "org.mitk.services.NavigationDataSource") #endif /* MITKNAVIGATIONDATASOURCE_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp index 481ef65f65..16f40bd3df 100644 --- a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp +++ b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.cpp @@ -1,334 +1,350 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTrackingDeviceSourceConfigurator.h" #include "mitkNDITrackingDevice.h" #include "mitkClaronTrackingDevice.h" #include "mitkOptitrackTrackingDevice.h" +#include "mitkOpenIGTLinkTrackingDevice.h" #include "mitkVirtualTrackingDevice.h" #include #include mitk::TrackingDeviceSourceConfigurator::TrackingDeviceSourceConfigurator(mitk::NavigationToolStorage::Pointer NavigationTools, mitk::TrackingDevice::Pointer TrackingDevice) { //make a copy of the navigation tool storage because we will modify the storage if (NavigationTools.IsNotNull()) { m_NavigationTools = mitk::NavigationToolStorage::New(); for (int i=0; iGetToolCount(); i++) { m_NavigationTools->AddTool(NavigationTools->GetTool(i)); } } m_TrackingDevice = TrackingDevice; m_ToolCorrespondencesInToolStorage = std::vector(); m_ErrorMessage = ""; } mitk::NavigationToolStorage::Pointer mitk::TrackingDeviceSourceConfigurator::GetUpdatedNavigationToolStorage() { return m_NavigationTools; } mitk::TrackingDeviceSourceConfigurator::~TrackingDeviceSourceConfigurator() { } bool mitk::TrackingDeviceSourceConfigurator::IsCreateTrackingDeviceSourcePossible() { if (m_NavigationTools.IsNull()) { m_ErrorMessage = "NavigationToolStorage is NULL!"; return false; } else if (m_TrackingDevice.IsNull()) { m_ErrorMessage = "TrackingDevice is NULL!"; return false; } else { for (int i=0; iGetToolCount(); i++) { if (m_NavigationTools->GetTool(i)->GetTrackingDeviceType() != m_TrackingDevice->GetType()) { m_ErrorMessage = "At least one tool is not of the same type like the tracking device."; return false; } } //TODO in case of Aurora: check if the tools are automatically detected by comparing the serial number return true; } } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateTrackingDeviceSource() { mitk::NavigationDataObjectVisualizationFilter::Pointer dummy; //this dummy is lost directly after creating the device return this->CreateTrackingDeviceSource(dummy); } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateTrackingDeviceSource(mitk::NavigationDataObjectVisualizationFilter::Pointer &visualizationFilter) { if (!this->IsCreateTrackingDeviceSourcePossible()) {MITK_WARN << "Cannot create tracking decive: " << m_ErrorMessage; return NULL;} mitk::TrackingDeviceSource::Pointer returnValue; //create tracking device source if (m_TrackingDevice->GetType()==mitk::NDIAurora) {returnValue = CreateNDIAuroraTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} else if (m_TrackingDevice->GetType()==mitk::NDIPolaris) {returnValue = CreateNDIPolarisTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} else if (m_TrackingDevice->GetType()==mitk::ClaronMicron) {returnValue = CreateMicronTrackerTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} else if (m_TrackingDevice->GetType()==mitk::NPOptitrack) {returnValue = CreateNPOptitrackTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} else if (m_TrackingDevice->GetType()==mitk::VirtualTracker) {returnValue = CreateVirtualTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} + else if (m_TrackingDevice->GetType()==mitk::OpenIGTLinkTrackingDeviceConnection) {returnValue = CreateOpenIGTLinkTrackingDeviceSource(m_TrackingDevice,m_NavigationTools);} //TODO: insert other tracking systems? if (returnValue.IsNull()) {MITK_WARN << "Cannot create tracking decive: " << m_ErrorMessage; return NULL;} //create visualization filter visualizationFilter = CreateNavigationDataObjectVisualizationFilter(returnValue,m_NavigationTools); if (visualizationFilter.IsNull()) {MITK_WARN << "Cannot create tracking decive: " << m_ErrorMessage; return NULL;} return returnValue; } std::string mitk::TrackingDeviceSourceConfigurator::GetErrorMessage() { return this->m_ErrorMessage; } //############################ internal help methods ######################################## mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateNDIPolarisTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::NDITrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); m_ToolCorrespondencesInToolStorage = std::vector(); //add the tools to the tracking device for (int i=0; iGetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = m_NavigationTools->GetTool(i); m_ToolCorrespondencesInToolStorage.push_back(i); bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str(),thisNavigationTool->GetCalibrationFile().c_str()); if (!toolAddSuccess) { //todo: error handling this->m_ErrorMessage = "Can't add tool, is the SROM-file valid?"; return NULL; } thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(),thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateNDIAuroraTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) { MITK_DEBUG << "Creating Aurora tracking device."; mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::NDITrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); try { //connect to aurora to dectect tools automatically thisDevice->OpenConnection(); } catch (mitk::IGTHardwareException& e) { m_ErrorMessage = std::string("Hardware error on opening the connection (") + e.GetDescription() + ")"; return NULL; } catch (mitk::IGTException& e) { m_ErrorMessage = std::string("Error on opening the connection (") + e.GetDescription() + ")"; return NULL; } //now search for automatically detected tools in the tool storage and save them mitk::NavigationToolStorage::Pointer newToolStorageInRightOrder = mitk::NavigationToolStorage::New(); std::vector alreadyFoundTools = std::vector(); m_ToolCorrespondencesInToolStorage = std::vector(); for (unsigned int i=0; iGetToolCount(); i++) { bool toolFound = false; for (int j=0; jGetToolCount(); j++) { //check if the serial number is the same to identify the tool if ((dynamic_cast(thisDevice->GetTool(i)))->GetSerialNumber() == navigationTools->GetTool(j)->GetSerialNumber()) { //check if this tool was already added to make sure that every tool is only added once (in case of same serial numbers) bool toolAlreadyAdded = false; for(unsigned int k=0; kAddTool(navigationTools->GetTool(j)); m_ToolCorrespondencesInToolStorage.push_back(j); //adapt name of tool dynamic_cast(thisDevice->GetTool(i))->SetToolName(navigationTools->GetTool(j)->GetToolName()); //set tip of tool dynamic_cast(thisDevice->GetTool(i))->SetToolTip(navigationTools->GetTool(j)->GetToolTipPosition(),navigationTools->GetTool(j)->GetToolTipOrientation()); //rember that this tool was already found alreadyFoundTools.push_back(j); toolFound = true; break; } } } if (!toolFound) { this->m_ErrorMessage = "Error: did not find every automatically detected tool in the loaded tool storage: aborting initialization."; return NULL; } } //delete all tools from the tool storage navigationTools->DeleteAllTools(); //and add only the detected tools in the right order for (int i=0; iGetToolCount(); i++) { navigationTools->AddTool(newToolStorageInRightOrder->GetTool(i)); } returnValue->SetTrackingDevice(thisDevice); MITK_DEBUG << "Number of tools of created tracking device: " << thisDevice->GetToolCount(); MITK_DEBUG << "Number of outputs of created source: " << returnValue->GetNumberOfOutputs(); return returnValue; } +mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateOpenIGTLinkTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) +{ + mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); + mitk::OpenIGTLinkTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); + thisDevice->DiscoverTools(); + if (thisDevice->GetToolCount() != navigationTools->GetToolCount()) + { + this->m_ErrorMessage = "The number of tools in the connected device differs from the tool storage, cannot add tools."; + return NULL; + } + returnValue->SetTrackingDevice(thisDevice); + return returnValue; +} + mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateMicronTrackerTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::ClaronTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); m_ToolCorrespondencesInToolStorage = std::vector(); //add the tools to the tracking device for (int i=0; iGetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = m_NavigationTools->GetTool(i); m_ToolCorrespondencesInToolStorage.push_back(i); bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str(),thisNavigationTool->GetCalibrationFile().c_str()); if (!toolAddSuccess) { //todo error handling this->m_ErrorMessage = "Can't add tool, is the toolfile valid?"; return NULL; } thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(),thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateNPOptitrackTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::OptitrackTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); m_ToolCorrespondencesInToolStorage = std::vector(); //OpenConnection with Optitrack thisDevice->OpenConnection(); //add the tools to the tracking device for (int i=0; iGetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = m_NavigationTools->GetTool(i); m_ToolCorrespondencesInToolStorage.push_back(i); bool toolAddSuccess = thisDevice->AddToolByDefinitionFile(thisNavigationTool->GetCalibrationFile()); thisDevice->GetOptitrackTool(i)->SetToolName(thisNavigationTool->GetToolName().c_str()); if (!toolAddSuccess) { //todo error handling this->m_ErrorMessage = "Can't add tool, is the toolfile valid?"; return NULL; } //thisDevice->GetTool(i)->SetToolTip(thisNavigationTool->GetToolTipPosition(),thisNavigationTool->GetToolTipOrientation()); } returnValue->SetTrackingDevice(thisDevice); return returnValue; } mitk::TrackingDeviceSource::Pointer mitk::TrackingDeviceSourceConfigurator::CreateVirtualTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::TrackingDeviceSource::Pointer returnValue = mitk::TrackingDeviceSource::New(); mitk::VirtualTrackingDevice::Pointer thisDevice = dynamic_cast(trackingDevice.GetPointer()); m_ToolCorrespondencesInToolStorage = std::vector(); //add the tools to the tracking device for (int i=0; iGetToolCount(); i++) { mitk::NavigationTool::Pointer thisNavigationTool = m_NavigationTools->GetTool(i); m_ToolCorrespondencesInToolStorage.push_back(i); bool toolAddSuccess = thisDevice->AddTool(thisNavigationTool->GetToolName().c_str()); if (!toolAddSuccess) { //todo error handling this->m_ErrorMessage = "Can't add tool, is the toolfile valid?"; return NULL; } } returnValue->SetTrackingDevice(thisDevice); return returnValue; } mitk::NavigationDataObjectVisualizationFilter::Pointer mitk::TrackingDeviceSourceConfigurator::CreateNavigationDataObjectVisualizationFilter(mitk::TrackingDeviceSource::Pointer trackingDeviceSource, mitk::NavigationToolStorage::Pointer navigationTools) { mitk::NavigationDataObjectVisualizationFilter::Pointer returnValue = mitk::NavigationDataObjectVisualizationFilter::New(); for (unsigned int i=0; iGetNumberOfIndexedOutputs(); i++) { // Note: If all tools have the same name only the first tool will always be returned and // the others won't be updated during rendering.This could potentially lead to inconstencies mitk::NavigationTool::Pointer currentTool = navigationTools->GetToolByName(trackingDeviceSource->GetOutput(i)->GetName()); if (currentTool.IsNull()) { - this->m_ErrorMessage = "Error: did not find correspondig tool in tracking device after initialization."; + this->m_ErrorMessage = "Error: did not find corresponding tool in tracking device after initialization."; return NULL; } returnValue->SetInput(i,trackingDeviceSource->GetOutput(i)); returnValue->SetRepresentationObject(i,currentTool->GetDataNode()->GetData()); } return returnValue; } int mitk::TrackingDeviceSourceConfigurator::GetToolNumberInToolStorage(unsigned int outputID) { if (outputID < m_ToolCorrespondencesInToolStorage.size()) return m_ToolCorrespondencesInToolStorage.at(outputID); else return -1; } std::string mitk::TrackingDeviceSourceConfigurator::GetToolIdentifierInToolStorage(unsigned int outputID) { if (outputID < m_ToolCorrespondencesInToolStorage.size()) return m_NavigationTools->GetTool(m_ToolCorrespondencesInToolStorage.at(outputID))->GetIdentifier(); else return ""; } std::vector mitk::TrackingDeviceSourceConfigurator::GetToolNumbersInToolStorage() { return m_ToolCorrespondencesInToolStorage; } std::vector mitk::TrackingDeviceSourceConfigurator::GetToolIdentifiersInToolStorage() { std::vector returnValue = std::vector(); for (unsigned int i=0; iGetTool(m_ToolCorrespondencesInToolStorage.at(i))->GetIdentifier());} return returnValue; } diff --git a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.h b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.h index 16a274e1dc..19414131d2 100644 --- a/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.h +++ b/Modules/IGT/DataManagement/mitkTrackingDeviceSourceConfigurator.h @@ -1,107 +1,108 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKTRACKINGDEVICESOURCECONFIGURATOR_H_HEADER_INCLUDED_ #define MITKTRACKINGDEVICESOURCECONFIGURATOR_H_HEADER_INCLUDED_ #include //itk includes #include //mitk IGT includes #include "mitkTrackingDeviceSource.h" #include "mitkNavigationToolStorage.h" #include "mitkNavigationDataObjectVisualizationFilter.h" namespace mitk { /**Documentation * \brief This class offers a factory method for objects of the class TrackingDeviceSource. It initializes this TrackingDeviceSource with * the given navigation tools and the given tracking device. The factory method also checks if all tools are valid and of the same * type like the TrackingDevice. You can do this check before trying to create the TrackingDeviceSource by calling the method * IsCreateTrackingDeviceSourcePossible(), if it returns false you might want to get the error message by calling the method * GetErrorMessage(). * \ingroup IGT */ class MITKIGT_EXPORT TrackingDeviceSourceConfigurator : public itk::Object { public: mitkClassMacroItkParent(TrackingDeviceSourceConfigurator, itk::Object); mitkNewMacro2Param(Self,mitk::NavigationToolStorage::Pointer,mitk::TrackingDevice::Pointer); /** @return Returns if it's possible to create a tracking device source, which means the tools are checked * if they are of the same type like the tracking device, etc. If it returns false you can get * the reason for this by getting the error message. */ bool IsCreateTrackingDeviceSourcePossible(); /** @return Returns a new TrackingDeviceSource. Returns NULL if there was an error on creating the * TrackingDeviceSource. If there was an error it's availiable as error message. */ mitk::TrackingDeviceSource::Pointer CreateTrackingDeviceSource(); /** @return Returns a new TrackingDeviceSource. Returns NULL if there was an error on creating the * TrackingDeviceSource. If there was an error it's availiable as error message. * @param visualizationFilter (return value) returns a visualization filter which is already connected to the tracking device source. * This filter visualises the surfaces which are availiable by the navigation tool storage. */ mitk::TrackingDeviceSource::Pointer CreateTrackingDeviceSource(mitk::NavigationDataObjectVisualizationFilter::Pointer &visualizationFilter); /** @return Returns the internal number of the corresponding tool in the tool storage of a output navigation data. Returns -1 if there was an error. */ int GetToolNumberInToolStorage(unsigned int outputID); /** @return Returns the identifier of the corresponding tool in the tool storage of a output navigation data. Returns an empty string if there was an error.*/ std::string GetToolIdentifierInToolStorage(unsigned int outputID); /** @return Returns a vector with all internal numbers of the corresponding tools in the tool storage of all outputs. * The order is the same like the order of the outputs. Returns an empty vector if there was an error. */ std::vector GetToolNumbersInToolStorage(); /** @return Returns a vector with all identifier of the corresponding tools in the tool storage of all outputs. * The order is the same like the order of the outputs. Returns an empty vector if there was an error. */ std::vector GetToolIdentifiersInToolStorage(); /** @return Returns a modified navigation tool storage which holds the tools currently in use in * the same order like the output ids of the pipline. */ mitk::NavigationToolStorage::Pointer GetUpdatedNavigationToolStorage(); /** @return Returns the current error message. Returns an empty string if there was no error. */ std::string GetErrorMessage(); protected: TrackingDeviceSourceConfigurator(mitk::NavigationToolStorage::Pointer NavigationTools, mitk::TrackingDevice::Pointer TrackingDevice); virtual ~TrackingDeviceSourceConfigurator(); mitk::NavigationToolStorage::Pointer m_NavigationTools; mitk::TrackingDevice::Pointer m_TrackingDevice; std::string m_ErrorMessage; std::vector m_ToolCorrespondencesInToolStorage; mitk::TrackingDeviceSource::Pointer CreateNDIPolarisTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); mitk::TrackingDeviceSource::Pointer CreateNDIAuroraTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); mitk::TrackingDeviceSource::Pointer CreateMicronTrackerTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); mitk::TrackingDeviceSource::Pointer CreateNPOptitrackTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); mitk::TrackingDeviceSource::Pointer CreateVirtualTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); + mitk::TrackingDeviceSource::Pointer CreateOpenIGTLinkTrackingDeviceSource(mitk::TrackingDevice::Pointer trackingDevice, mitk::NavigationToolStorage::Pointer navigationTools); mitk::NavigationDataObjectVisualizationFilter::Pointer CreateNavigationDataObjectVisualizationFilter(mitk::TrackingDeviceSource::Pointer trackingDeviceSource, mitk::NavigationToolStorage::Pointer navigationTools); }; } // namespace mitk #endif /* MITKTrackingDeviceSource_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationDataPlayer.cpp b/Modules/IGT/IO/mitkNavigationDataPlayer.cpp index ff08aaad03..7bdd597660 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayer.cpp +++ b/Modules/IGT/IO/mitkNavigationDataPlayer.cpp @@ -1,161 +1,160 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataPlayer.h" #include #include #include -#include "mitkNavigationDataReaderXML.h" #include "mitkIGTException.h" mitk::NavigationDataPlayer::NavigationDataPlayer() : m_CurPlayerState(PlayerStopped), m_StartPlayingTimeStamp(0.0), m_PauseTimeStamp(0.0) { // to get a start time mitk::IGTTimeStamp::GetInstance()->Start(this); } mitk::NavigationDataPlayer::~NavigationDataPlayer() { StopPlaying(); } void mitk::NavigationDataPlayer::GenerateData() { if ( m_NavigationDataSet->Size() == 0 ) { MITK_WARN << "Cannot do anything with empty set of navigation datas."; return; } //Only produce new output if the player is started if (m_CurPlayerState != PlayerRunning) { //The output is not valid anymore this->GraftEmptyOutput(); return; } // get elapsed time since start of playing m_TimeStampSinceStart = mitk::IGTTimeStamp::GetInstance()->GetElapsed() - m_StartPlayingTimeStamp; // add offset of the first navigation data to the timestamp to start playing // imediatly with the first navigation data (not to wait till the first time // stamp is reached) TimeStampType timeStampSinceStartWithOffset = m_TimeStampSinceStart + m_NavigationDataSet->Begin()->at(0)->GetIGTTimeStamp(); // iterate through all NavigationData objects of the given tool index // till the timestamp of the NavigationData is greater then the given timestamp for (; m_NavigationDataSetIterator != m_NavigationDataSet->End(); ++m_NavigationDataSetIterator) { // test if the timestamp of the successor is greater than the time stamp if ( m_NavigationDataSetIterator+1 == m_NavigationDataSet->End() || (m_NavigationDataSetIterator+1)->at(0)->GetIGTTimeStamp() > timeStampSinceStartWithOffset ) { break; } } for (unsigned int index = 0; index < GetNumberOfOutputs(); index++) { mitk::NavigationData* output = this->GetOutput(index); if( !output ) { mitkThrowException(mitk::IGTException) << "Output of index "<Graft(m_NavigationDataSetIterator->at(index)); } // stop playing if the last NavigationData objects were grafted if (m_NavigationDataSetIterator+1 == m_NavigationDataSet->End()) { this->StopPlaying(); // start playing again if repeat is enabled if ( m_Repeat ) { this->StartPlaying(); } } } void mitk::NavigationDataPlayer::UpdateOutputInformation() { this->Modified(); // make sure that we need to be updated Superclass::UpdateOutputInformation(); } void mitk::NavigationDataPlayer::StartPlaying() { // make sure that player is initialized before playing starts this->InitPlayer(); // set state and iterator for playing from start m_CurPlayerState = PlayerRunning; m_NavigationDataSetIterator = m_NavigationDataSet->Begin(); // reset playing timestamps m_PauseTimeStamp = 0; m_TimeStampSinceStart = 0; // timestamp for indicating playing start set to current elapsed time m_StartPlayingTimeStamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); } void mitk::NavigationDataPlayer::StopPlaying() { m_CurPlayerState = PlayerStopped; } void mitk::NavigationDataPlayer::Pause() { //player runs and pause was called -> pause the player if(m_CurPlayerState == PlayerRunning) { m_CurPlayerState = PlayerPaused; m_PauseTimeStamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed(); } else { MITK_ERROR << "Player is either not started or already is paused" << std::endl; } } void mitk::NavigationDataPlayer::Resume() { // player is in pause mode -> play at the last position if(m_CurPlayerState == PlayerPaused) { m_CurPlayerState = PlayerRunning; // in this case m_StartPlayingTimeStamp is set to the total elapsed time with NO playback m_StartPlayingTimeStamp = mitk::IGTTimeStamp::GetInstance()->GetElapsed() - (m_PauseTimeStamp - m_StartPlayingTimeStamp); } else { MITK_ERROR << "Player is not paused!" << std::endl; } } mitk::NavigationDataPlayer::PlayerState mitk::NavigationDataPlayer::GetCurrentPlayerState() { return m_CurPlayerState; } mitk::NavigationDataPlayer::TimeStampType mitk::NavigationDataPlayer::GetTimeStampSinceStart() { return m_TimeStampSinceStart; } diff --git a/Modules/IGT/IO/mitkNavigationDataPlayerBase.h b/Modules/IGT/IO/mitkNavigationDataPlayerBase.h index 401de6723e..d79419f6bc 100644 --- a/Modules/IGT/IO/mitkNavigationDataPlayerBase.h +++ b/Modules/IGT/IO/mitkNavigationDataPlayerBase.h @@ -1,118 +1,118 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNavigationDataPlayerBase_H_HEADER_INCLUDED_ #define MITKNavigationDataPlayerBase_H_HEADER_INCLUDED_ #include "mitkNavigationDataSource.h" #include "mitkNavigationDataSet.h" namespace mitk{ /** * \brief Base class for using mitk::NavigationData as a filter source. * Subclasses can play objects of mitk::NavigationDataSet. * * Each subclass has to check the state of m_Repeat and do or do not repeat * the playing accordingly. * * \ingroup IGT */ class MITKIGT_EXPORT NavigationDataPlayerBase : public NavigationDataSource { public: mitkClassMacro(NavigationDataPlayerBase, NavigationDataSource) /** * \brief Set to true if the data player should repeat the outputs. */ itkSetMacro(Repeat, bool) /** * \return Returns if the data player should repeat the outputs. */ itkGetMacro(Repeat, bool) /** * \brief Used for pipeline update just to tell the pipeline that we always have to update. */ virtual void UpdateOutputInformation() override; itkGetMacro(NavigationDataSet, NavigationDataSet::Pointer) /** * \brief Set mitk::NavigationDataSet for playing. * Player is initialized by call to mitk::NavigationDataPlayerBase::InitPlayer() * inside this method. Method must be called before this object can be used as * a filter source. * * @param navigationDataSet mitk::NavigationDataSet which will be played by this player. */ void SetNavigationDataSet(NavigationDataSet::Pointer navigationDataSet); /** * \brief Getter for the size of the mitk::NavigationDataSet used in this object. * * @return Returns the number of navigation data snapshots available in the player. */ unsigned int GetNumberOfSnapshots(); unsigned int GetCurrentSnapshotNumber(); /** * \brief This method checks if player arrived at end of file. * * @return true if last mitk::NavigationData object is in the outputs, false otherwise */ bool IsAtEnd(); protected: NavigationDataPlayerBase(); virtual ~NavigationDataPlayerBase(); /** * \brief Every subclass hast to implement this method. See ITK filter documentation for details. */ virtual void GenerateData() = 0; /** * \brief Initializes the outputs of this NavigationDataSource. * Aftwer calling this method, the first Navigationdata from the loaded Navigationdataset is loaded into the outputs. */ void InitPlayer(); /** * \brief Convenience method for subclasses. * When there are no further mitk::NavigationData objects available, this * method can be called in the implementation of mitk::NavigationDataPlayerBase::GenerateData(). */ void GraftEmptyOutput(); /** * \brief If the player should repeat outputs. Default is false. */ bool m_Repeat; NavigationDataSet::Pointer m_NavigationDataSet; /** * \brief Iterator always points to the NavigationData object which is in the outputs at the moment. */ - mitk::NavigationDataSet::NavigationDataSetIterator m_NavigationDataSetIterator; + mitk::NavigationDataSet::NavigationDataSetConstIterator m_NavigationDataSetIterator; }; } // namespace mitk #endif /* MITKNavigationDataSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/IO/mitkNavigationDataReaderInterface.h b/Modules/IGT/IO/mitkNavigationDataReaderInterface.h index 45612ebf0d..30b5d5073b 100644 --- a/Modules/IGT/IO/mitkNavigationDataReaderInterface.h +++ b/Modules/IGT/IO/mitkNavigationDataReaderInterface.h @@ -1,39 +1,40 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNavigationDataReaderInterface_H_HEADER_INCLUDED_ #define MITKNavigationDataReaderInterface_H_HEADER_INCLUDED_ #include "itkObject.h" #include "mitkCommon.h" #include "mitkNavigationDataSet.h" +#include "MitkIGTExports.h" namespace mitk { class MITKIGT_EXPORT NavigationDataReaderInterface : public itk::Object { public: mitkClassMacroItkParent(NavigationDataReaderInterface, itk::Object); virtual mitk::NavigationDataSet::Pointer Read(std::string filename) = 0; protected: NavigationDataReaderInterface(); virtual ~NavigationDataReaderInterface(); }; } #endif // MITKNavigationDataReaderInterface_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataRecorderDeprecated.h b/Modules/IGT/IO/mitkNavigationDataRecorderDeprecated.h index 269a6f7894..caaae5822b 100644 --- a/Modules/IGT/IO/mitkNavigationDataRecorderDeprecated.h +++ b/Modules/IGT/IO/mitkNavigationDataRecorderDeprecated.h @@ -1,212 +1,212 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef _MITK_NavigationDataRecorderDeprecated_H #define _MITK_NavigationDataRecorderDeprecated_H #include #include "mitkNavigationData.h" - +#include "MitkIGTExports.h" #include #include namespace mitk { /**Documentation * \brief This class records NavigationData objects. * * The output of this class is formated as a XML document. * * Internal this class uses streams for recording NavigationData objects. Therefore different types of output are possible * and can be set with the SetOutputMode() method. The default output is directed to the console. If you want to save into a * file you have to set a file name and the path. The recording is started with the call of the method StartRecording(). Now * every Update() stores the current state of the added NavigationDatas. With StopRecording() the stream is stopped. With * another call of StartRecording() the output is written to a new file with incremented filename counter. * * \warning At the moment there is no check if the file is already existing and this class will override existing files. * \ingroup IGT */ class MITKIGT_EXPORT NavigationDataRecorderDeprecated : public itk::ProcessObject { public: mitkClassMacroItkParent( NavigationDataRecorderDeprecated, itk::ProcessObject ); itkNewMacro( Self ); /**Documentation * \brief Determines where the output is directed to * * Console: std::cout * NormalFile: std::ofstream * ZipFile: Not supported yet -> std::cout */ enum RecordingMode { Console, NormalFile, ZipFile }; /**Documentation * \brief Determines the output format * * xml: XML format, also default, can be read by NavigationDataPlayer * csv: use to export in excel, matlab, etc. */ enum OutputFormatEnum { xml, csv }; /** * \brief sets the file name for the OutputMode NormalFile and ZipFile * * Any extensions will be cut * \warning existing files will be overridden * \warning do not use "." in file names at the end */ DEPRECATED( itkSetStringMacro(FileName)); /** * \brief Returns the file name of the recording file (in OutputMode NormalFile and ZipFile) */ DEPRECATED( itkGetStringMacro(FileName)); /** * \brief If true the recorder will never overwrite a file */ DEPRECATED( itkSetMacro(DoNotOverwriteFiles,bool)); /** * \brief Returns whether the NavigationDataRecorderDeprecated is recording or not */ DEPRECATED( itkGetMacro(Recording,bool)); /** * \brief Returns the recording mode */ DEPRECATED( itkGetMacro(RecordingMode,RecordingMode)); /** * \brief Returns the number of data sets / frames which were recorded by the NavigationDataRecorderDeprecated since start */ DEPRECATED( itkGetMacro(RecordCounter,int)); /** * \brief Sets a limit of recorded data sets / frames. Recording will be stopped if the number is reached. -1 disables the limit, -1 is default value as well. */ DEPRECATED( itkSetMacro(RecordCountLimit,int)); /** * \brief Adds the input NavigationDatas */ DEPRECATED( virtual void AddNavigationData(const NavigationData* nd)); /// /// set an additional attribute for a specified navigation data /// this will be written for each navigation data and may be /// updated before calling Update() /// DEPRECATED( void SetAdditionalAttribute( const NavigationData* nd, const std::string& attributeName , const std::string& attributeValue )); DEPRECATED(void RemoveAdditionalAttribute( const NavigationData* nd )); /** * Documentation * \brief Starts the recording with the presetted OutputMode. * This method calls StartRecording(std::ostream*). * Does nothing if the recorder is already recording and * the method StartRecording is called again. * @throw mitk::IGTException Throws an exception if no file name or file path is set. */ DEPRECATED( void StartRecording()); /** * Documentation * \brief Starts the recording with an own preinitialized stream * Does nothing if it is already recording and method StartRecorded is called * @throw mitk::IGTException Throws an exception if the stream is not good. */ DEPRECATED( void StartRecording(std::ostream* stream)); /**Documentation * \brief Stops the recording and closes the stream */ DEPRECATED( void StopRecording()); /**Documentation * \brief Every call of update causes one line for each added NavigationData in the output if the recording was started */ DEPRECATED( virtual void Update()); /**Documentation * \brief Sets the recording mode which causes different types of output streams * see enum RecordingMode */ DEPRECATED( void SetRecordingMode(RecordingMode mode)); /**Documentation * \brief Sets the output format which causes different formats of output streams. The XML format is default. * Also see enum OutputFormat for more information. */ DEPRECATED( itkSetMacro(OutputFormat,mitk::NavigationDataRecorderDeprecated::OutputFormatEnum)); protected: /**Documentation * \brief filter execute method here it is not used * */ virtual void GenerateData() override; NavigationDataRecorderDeprecated(); virtual ~NavigationDataRecorderDeprecated(); std::string m_FileName; ///< stores the file name and path unsigned int m_NumberOfInputs; ///< counts the numbers of added input NavigationDatas std::ostream* m_Stream; ///< the output stream bool m_StreamMustBeDeleted; RecordingMode m_RecordingMode; ///< stores the mode see enum RecordingMode OutputFormatEnum m_OutputFormat; ///< stores the output format; see enum OutputFormat bool m_Recording; ///< indicates whether the recording is started or not int m_RecordCounter; ///< counts the number of frames which are recorded since StartRecording int m_RecordCountLimit; ///< limits the number of frames, recording will be stopped if the limit is reached. -1 disables the limit bool m_firstLine; //for the csv writer to detect wether the header must be written unsigned int m_NumberOfRecordedFiles; ///< necessary for the naming of the file if there is more than one start-stop cycle mitk::RealTimeClock::Pointer m_SystemTimeClock; ///< system time clock for system time tag in output xml file bool m_DoNotOverwriteFiles; ///< do not overwrite any files if true std::map > m_AdditionalAttributes; }; } #endif // #define _MITK_POINT_SET_SOURCE_H diff --git a/Modules/IGT/Testing/files.cmake b/Modules/IGT/Testing/files.cmake index ed3cd8c6ec..dc3a16bdd3 100644 --- a/Modules/IGT/Testing/files.cmake +++ b/Modules/IGT/Testing/files.cmake @@ -1,65 +1,66 @@ set(MODULE_TESTS # IMPORTANT: If you plan to deactivate / comment out a test please write a bug number to the commented out line of code. # # Example: #mitkMyTest #this test is commented out because of bug 12345 # # It is important that the bug is open and that the test will be activated again before the bug is closed. This assures that # no test is forgotten after it was commented out. If there is no bug for your current problem, please add a new one and # mark it as critical. ################## ON THE FENCE TESTS ################################################# # none ################## DISABLED TESTS ##################################################### # mitkNavigationToolStorageDeserializerTest.cpp # This test was disabled because of bug 17303. # mitkNavigationToolStorageSerializerAndDeserializerIntegrationTest.cpp # This test was disabled because of bug 17181. # mitkNavigationToolStorageSerializerTest.cpp # This test was disabled because of bug 18671 ################# RUNNING TESTS ####################################################### mitkCameraVisualizationTest.cpp mitkClaronInterfaceTest.cpp mitkClaronToolTest.cpp mitkClaronTrackingDeviceTest.cpp mitkInternalTrackingToolTest.cpp mitkNavigationDataDisplacementFilterTest.cpp mitkNavigationDataLandmarkTransformFilterTest.cpp mitkNavigationDataObjectVisualizationFilterTest.cpp mitkNavigationDataSetTest.cpp mitkNavigationDataTest.cpp mitkNavigationDataRecorderTest.cpp mitkNavigationDataReferenceTransformFilterTest.cpp mitkNavigationDataSequentialPlayerTest.cpp mitkNavigationDataSetReaderWriterXMLTest.cpp mitkNavigationDataSetReaderWriterCSVTest.cpp mitkNavigationDataSourceTest.cpp mitkNavigationDataToMessageFilterTest.cpp mitkNavigationDataToNavigationDataFilterTest.cpp mitkNavigationDataToPointSetFilterTest.cpp mitkNavigationDataToIGTLMessageFilterTest.cpp mitkNavigationDataTransformFilterTest.cpp mitkNDIPassiveToolTest.cpp mitkNDIProtocolTest.cpp mitkNDITrackingDeviceTest.cpp mitkTimeStampTest.cpp mitkTrackingVolumeGeneratorTest.cpp mitkTrackingDeviceTest.cpp mitkTrackingToolTest.cpp mitkVirtualTrackingDeviceTest.cpp # mitkNavigationDataPlayerTest.cpp # random fails see bug 16485. # We decided to won't fix because of complete restructuring via bug 15959. mitkTrackingDeviceSourceTest.cpp mitkTrackingDeviceSourceConfiguratorTest.cpp mitkNavigationDataEvaluationFilterTest.cpp mitkTrackingTypesTest.cpp + mitkOpenIGTLinkTrackingDeviceTest.cpp # ------------------ Navigation Tool Management Tests ------------------- mitkNavigationToolStorageTest.cpp mitkNavigationToolTest.cpp #mitkNavigationToolReaderAndWriterTest.cpp #deactivated because of bug 18835 # ----------------------------------------------------------------------- ) set(MODULE_CUSTOM_TESTS mitkNDIAuroraHardwareTest.cpp mitkNDIPolarisHardwareTest.cpp mitkClaronTrackingDeviceHardwareTest.cpp ) diff --git a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp index ca4ea08df6..64cd8ce361 100644 --- a/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataRecorderTest.cpp @@ -1,143 +1,141 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include #include #include #include - -#include -#include +#include //for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" class mitkNavigationDataRecorderTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkNavigationDataRecorderTestSuite); MITK_TEST(TestRecording); MITK_TEST(TestStopRecording); MITK_TEST(TestLimiting); CPPUNIT_TEST_SUITE_END(); private: mitk::NavigationDataSet::Pointer m_NavigationDataSet; mitk::NavigationDataSequentialPlayer::Pointer m_Player; mitk::NavigationDataRecorder::Pointer m_Recorder; public: void setUp() override { - mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); std::string path = GetTestDataFilePath("IGT-Data/RecordedNavigationData.xml"); - m_NavigationDataSet = reader->Read(path); + m_NavigationDataSet = dynamic_cast (mitk::IOUtil::LoadBaseData(path).GetPointer()); + m_Player = mitk::NavigationDataSequentialPlayer::New(); m_Player->SetNavigationDataSet(m_NavigationDataSet); m_Recorder = mitk::NavigationDataRecorder::New(); m_Recorder->SetStandardizeTime(false); // connect player to recorder m_Recorder->ConnectTo(m_Player); } void tearDown() override { } void TestRecording() { m_Recorder->StartRecording(); while (!m_Player->IsAtEnd()) { m_Recorder->Update(); m_Player->GoToNextSnapshot(); } mitk::NavigationDataSet::Pointer recordedData = m_Recorder->GetNavigationDataSet(); MITK_TEST_CONDITION_REQUIRED(recordedData->Size() == m_NavigationDataSet->Size(), "Test if recorded Dataset is of equal size as original"); MITK_TEST_CONDITION_REQUIRED(compareDataSet(recordedData), "Test recorded dataset for equality with reference"); } void TestStopRecording() { // Aim is to read an xml into a pointset, play that set with a sequentialplayer, record it // again, write the result to xml , and compare the output m_Recorder->StartRecording(); int i = 0; while (i < 5) { m_Recorder->Update(); m_Player->GoToNextSnapshot(); i++; } m_Recorder->StopRecording(); MITK_TEST_CONDITION_REQUIRED(! m_Recorder->GetRecording(), "Test if StopRecording is working, part 1"); while (i < 5) { m_Recorder->Update(); m_Player->GoToNextSnapshot(); i++; } MITK_TEST_CONDITION_REQUIRED(m_Recorder->GetNavigationDataSet()->Size() == 5, "Test if StopRecording is working, part 2"); } void TestLimiting() { // Check if Limiting recording works m_Recorder->SetRecordCountLimit(30); m_Recorder->StartRecording(); while (!m_Player->IsAtEnd()) { m_Recorder->Update(); m_Player->GoToNextSnapshot(); } MITK_TEST_CONDITION_REQUIRED(m_Recorder->GetNavigationDataSet()->Size() == 30, "Test if SetRecordCountLimit works as intended."); } private: /* * private hepler method that compares the recorded Dataset against the member variable. * This is a reasonable test only under the assumption that the Data should be equal from coyping - It does not consider * homonymus Quaternions and NO FLOAT ROUNDING ISSUES */ bool compareDataSet(mitk::NavigationDataSet::Pointer recorded) { for (unsigned int tool = 0; tool < recorded->GetNumberOfTools(); tool++){ for (unsigned int i = 0; i < recorded->Size(); i++) { mitk::NavigationData::Pointer ref = m_NavigationDataSet->GetNavigationDataForIndex(i,tool); mitk::NavigationData::Pointer rec = recorded->GetNavigationDataForIndex(i,tool); if (!(ref->GetOrientation().as_vector() == rec->GetOrientation().as_vector())) {return false;} if (!(ref->GetPosition().GetVnlVector() == rec->GetPosition().GetVnlVector())) {return false;} } } return true; } }; MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataRecorder) \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp index b8bb7db227..95d007e89d 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSequentialPlayerTest.cpp @@ -1,175 +1,175 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include #include "mitkTestingMacros.h" #include -#include "mitkNavigationDataReaderXML.h" +#include #include #include //foe exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" class mitkNavigationDataSequentialPlayerTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkNavigationDataSequentialPlayerTestSuite); MITK_TEST(TestStandardWorkflow); MITK_TEST(TestRestartWithNewNavigationDataSet); MITK_TEST(TestGoToSnapshotException); MITK_TEST(TestDoubleUpdate); CPPUNIT_TEST_SUITE_END(); private: /** Members used inside the different test methods. All members are initialized via setUp().*/ mitk::NavigationDataSet::Pointer NavigationDataSet; mitk::NavigationDataSequentialPlayer::Pointer player; public: void setUp() override{ player = mitk::NavigationDataSequentialPlayer::New(); std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData_2ToolsDouble.xml"); - mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); - NavigationDataSet =reader->Read(file); + + NavigationDataSet = dynamic_cast (mitk::IOUtil::LoadBaseData(file).GetPointer()); } void tearDown() override { } bool runLoop() { player->Update(); mitk::NavigationData::Pointer nd0; mitk::NavigationData::Pointer nd1; for(unsigned int i=0; iGetNumberOfSnapshots(); ++i) { nd0 = player->GetOutput(0); nd1 = player->GetOutput(1); // test some values if(nd0.IsNull() || nd1.IsNull()) return false; //Compare data mitk::NavigationData::Pointer ref0 = NavigationDataSet->GetNavigationDataForIndex(i,0); mitk::NavigationData::Pointer ref1 = NavigationDataSet->GetNavigationDataForIndex(i,1); if (!(ref0->GetOrientation().as_vector() == nd0->GetOrientation().as_vector())) {return false;} if (!(ref1->GetOrientation().as_vector() == nd1->GetOrientation().as_vector())) {return false;} if (!(ref0->GetPosition().GetVnlVector() == nd0->GetPosition().GetVnlVector())) {return false;} if (!(ref1->GetPosition().GetVnlVector() == nd1->GetPosition().GetVnlVector())) {return false;} // Goto next Snapshot player->GoToNextSnapshot(); } return true; } void TestStandardWorkflow() { // Set NavigationDatas for player player->SetNavigationDataSet(NavigationDataSet); MITK_TEST_CONDITION(player->GetNumberOfSnapshots() == 3,"Testing if player reports correct number of Snapshots"); MITK_TEST_CONDITION(player->GetNumberOfIndexedOutputs() == 2,"Testing number of outputs"); //rest repeat player->SetRepeat(true); MITK_TEST_CONDITION(runLoop(),"Testing first run."); MITK_TEST_CONDITION(runLoop(),"Testing second run."); //repeat is on should work a second time // now test the go to snapshot function player->GoToSnapshot(2); mitk::NavigationData::Pointer nd1 = player->GetOutput(1); mitk::NavigationData::Pointer ref1 = NavigationDataSet->GetNavigationDataForIndex(2,1); MITK_TEST_CONDITION(ref1->GetPosition().GetVnlVector() == nd1->GetPosition().GetVnlVector(), "Testing GoToSnapshot() [1]"); //MITK_TEST_OUTPUT( << "Reference:" << ref1->GetPosition().GetVnlVector() << "\tObserved: " << nd1->GetPosition().GetVnlVector()); player->GoToSnapshot(0); mitk::NavigationData::Pointer nd0 = player->GetOutput(); mitk::NavigationData::Pointer ref0 = NavigationDataSet->GetNavigationDataForIndex(0,0); MITK_TEST_CONDITION(ref0->GetOrientation().as_vector() == nd0->GetOrientation().as_vector(), "Testing GoToSnapshot() [2]"); //MITK_TEST_OUTPUT( << "Reference" << ref0->GetPosition().GetVnlVector() << "\tObserved:" <GetOrientation().as_vector() ); } void TestRestartWithNewNavigationDataSet() { player->SetNavigationDataSet(NavigationDataSet); mitk::NavigationData::PositionType nd1 = player->GetOutput(0)->GetPosition(); player->SetNavigationDataSet(NavigationDataSet); mitk::NavigationData::PositionType nd2 = player->GetOutput(0)->GetPosition(); MITK_TEST_CONDITION(nd1 == nd2, "First output must be the same after setting same navigation data again."); // setting new NavigationDataSet with different tool count should result in an exception std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData.xml"); - mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); - MITK_TEST_FOR_EXCEPTION(mitk::IGTException, player->SetNavigationDataSet(reader->Read(file))); + mitk::NavigationDataSet::Pointer dataset = dynamic_cast (mitk::IOUtil::LoadBaseData(file).GetPointer()); + MITK_TEST_FOR_EXCEPTION(mitk::IGTException, player->SetNavigationDataSet(dataset)); } void TestGoToSnapshotException() { //testing GoToSnapShot for exception mitk::NavigationDataSequentialPlayer::Pointer myTestPlayer2 = mitk::NavigationDataSequentialPlayer::New(); std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData_2Tools.xml"); - mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); - myTestPlayer2->SetNavigationDataSet(reader->Read(file)); + mitk::NavigationDataSet::Pointer dataset = dynamic_cast (mitk::IOUtil::LoadBaseData(file).GetPointer()); + myTestPlayer2->SetNavigationDataSet(dataset); bool exceptionThrown2=false; try { unsigned int invalidSnapshot = 1000; myTestPlayer2->GoToSnapshot(invalidSnapshot); } catch(mitk::IGTException) { exceptionThrown2=true; } MITK_TEST_CONDITION(exceptionThrown2, "Testing if exception is thrown when GoToSnapShot method is called with an index that doesn't exist."); } void TestDoubleUpdate() { //std::string file = GetTestDataFilePath("IGT-Data/NavigationDataTestData_2Tools.xml"); //mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); //player->SetNavigationDataSet(reader->Read(file)); player->SetNavigationDataSet(NavigationDataSet); player->Update(); mitk::Quaternion nd1Orientation = player->GetOutput()->GetOrientation(); player->Update(); mitk::Quaternion nd2Orientation = player->GetOutput()->GetOrientation(); MITK_TEST_CONDITION(nd1Orientation.as_vector() == nd2Orientation.as_vector(), "Output must be the same no matter if Update() was called between."); MITK_TEST_CONDITION(player->GoToNextSnapshot(), "There must be a next snapshot available."); player->Update(); mitk::Quaternion nd3Orientation = player->GetOutput()->GetOrientation(); MITK_TEST_CONDITION(nd1Orientation.as_vector() != nd3Orientation.as_vector(), "Output must be different if GoToNextSnapshot() was called between."); } }; MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataSequentialPlayer) \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterCSVTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterCSVTest.cpp index de72d018d7..bfb6c2c5fe 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterCSVTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterCSVTest.cpp @@ -1,142 +1,133 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //testing headers //#include #include #include #include #include #include #include -#include -#include - -#include +#include #include #include #include #include #include //for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" class mitkNavigationDataSetReaderWriterCSVTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkNavigationDataSetReaderWriterCSVTestSuite); // MITK_TEST(TestCompareFunction); MITK_TEST(TestReadWrite); CPPUNIT_TEST_SUITE_END(); private: std::string pathRead; std::string pathWrite; std::string pathWrong; - mitk::NavigationDataSetWriterCSV writer; - mitk::NavigationDataReaderCSV::Pointer reader; - - mitk::NavigationDataReaderXML::Pointer xmlReader; mitk::NavigationDataSet::Pointer set; public: void setUp() override { pathRead = GetTestDataFilePath("IGT-Data/RecordedNavigationData.xml"); pathWrong = GetTestDataFilePath("IGT-Data/NavigationDataTestData.CSV"); pathWrite="C:\\test.csv"; - - reader = mitk::NavigationDataReaderCSV::New(); - xmlReader= mitk::NavigationDataReaderXML::New(); } void tearDown() override { } void TestReadWrite() { // Aim is to read an CSV into a pointset, write that CSV again, and compare the output - set = xmlReader->Read(pathRead); + set = dynamic_cast(mitk::IOUtil::LoadBaseData(pathRead).GetPointer() ); + CPPUNIT_ASSERT_MESSAGE("Testing whether something was read at all", set != nullptr); - writer.Write(pathWrite, set); + mitk::IOUtil::SaveBaseData(set, pathWrite); //FIXME: Commented out, because test fails under linux. binary comparison of files is probably not the wa to go // See Bug 17775 //CPPUNIT_ASSERT_MESSAGE( "Testing if read/write cycle creates identical files", CompareFiles(pathRead, pathWrite)); //remove(pathWrite.c_str()); } bool CompareFiles(std::string file) { - set = reader->Read(file); + set = dynamic_cast(mitk::IOUtil::LoadBaseData(file).GetPointer()); double sample[2][30] ={ {5134019.44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5134019.44, 0, 1, 101.2300034, -62.63999939, -203.2400055, -0.3059000075, 0.5752000213, 0, 0.7585999966, 5134019.44, 0, 0, 0, 0, 0, 0, 0, 0, 0}, {5134082.84, 5134073.64, 1, -172.6100006, 12.60999966, -299.4500122, -0.1588999927, 0.4370000064, 0, 0.8852000237, 5134082.84, 5134073.64, 1, 101.2300034, -62.63999939, -203.2400055, -0.3059000075, 0.5752000213, 0, 0.7585999966, 5134082.84, 5134073.64, 0, 0, 0, 0, 0, 0, 0, 0} }; bool returnValue = true; for(int line = 0 ; line < 2; line++) { for (int tool =0; tool < 3; tool ++) { mitk::NavigationData::Pointer testline = set->GetNavigationDataForIndex(line,tool) ; returnValue = returnValue && mitk::Equal( testline->GetIGTTimeStamp() , sample [line] [(tool*10)] ); returnValue = returnValue && mitk::Equal( testline->IsDataValid() , sample [line] [(tool*10)+1] ); mitk::NavigationData::PositionType pos = testline->GetPosition(); returnValue = returnValue && mitk::Equal( pos[0] , sample [line] [(tool*10)+2] ); returnValue = returnValue && mitk::Equal( pos[1] , sample [line] [(tool*10)+3] ); returnValue = returnValue && mitk::Equal( pos[2] , sample [line] [(tool*10)+4] ); mitk::NavigationData::OrientationType ori = testline->GetOrientation(); returnValue = returnValue && mitk::Equal( ori[0] , sample [line] [(tool*10)+5] ); returnValue = returnValue && mitk::Equal( ori[1] , sample [line] [(tool*10)+6] ); returnValue = returnValue && mitk::Equal( ori[2] , sample [line] [(tool*10)+7] ); returnValue = returnValue && mitk::Equal( ori[3] , sample [line] [(tool*10)+8] ); } return returnValue; } } void TestCompareFunction() { CPPUNIT_ASSERT_MESSAGE("Checking if csv-file reader is working properly", CompareFiles(pathRead)); //CPPUNIT_ASSERT_MESSAGE("Asserting that compare function for files works correctly - Negative Test", ! CompareFiles(pathWrong) ); } }; MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataSetReaderWriterCSV) \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterXMLTest.cpp b/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterXMLTest.cpp index a1c520c4eb..e120bc3b88 100644 --- a/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterXMLTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataSetReaderWriterXMLTest.cpp @@ -1,142 +1,136 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ //testing headers //#include #include #include #include #include #include #include -#include -#include +#include #include #include #include #include #include //for exceptions #include "mitkIGTException.h" #include "mitkIGTIOException.h" class mitkNavigationDataSetReaderWriterXMLTestSuite : public mitk::TestFixture { CPPUNIT_TEST_SUITE(mitkNavigationDataSetReaderWriterXMLTestSuite); MITK_TEST(TestCompareFunction); MITK_TEST(TestReadWrite); MITK_TEST(TestSetXMLStringException); CPPUNIT_TEST_SUITE_END(); private: std::string pathRead; std::string pathWrite; std::string pathWrong; - mitk::NavigationDataSetWriterXML writer; - mitk::NavigationDataReaderXML::Pointer reader; mitk::NavigationDataSet::Pointer set; public: void setUp() override { pathRead = GetTestDataFilePath("IGT-Data/RecordedNavigationData.xml"); pathWrite = pathRead; pathWrite.insert(pathWrite.end()-4,'2');;//Insert 2: IGT-Data/NavigationDataSet2.xml std::ifstream FileTest(pathWrite.c_str()); if(FileTest){ //remove file if it already exists. TODO: Löschen funktioniert nicht!!!! xxxxxxxxxxxxxxxx FileTest.close(); std::remove(pathWrite.c_str()); } pathWrong = GetTestDataFilePath("IGT-Data/NavigationDataTestData.xml"); - - reader = mitk::NavigationDataReaderXML::New(); } void tearDown() override { } void TestReadWrite() { // Aim is to read an xml into a pointset, write that xml again, and compare the output - set = reader->Read(pathRead); - writer.Write(pathWrite, set); + set = dynamic_cast (mitk::IOUtil::LoadBaseData(pathRead).GetPointer()); + mitk::IOUtil::SaveBaseData(set, pathWrite); //FIXME: Commented out, because test fails under linux. binary comparison of files is probably not the wa to go // See Bug 17775 //CPPUNIT_ASSERT_MESSAGE( "Testing if read/write cycle creates identical files", CompareFiles(pathRead, pathWrite)); remove(pathWrite.c_str()); } bool CompareFiles(std::string file1, std::string file2) { FILE* f1 = fopen (file1.c_str() , "r"); FILE* f2 = fopen (file2.c_str() , "r"); char buf1[10000]; char buf2[10000]; do { size_t r1 = fread(buf1, 1, 10000, f1); size_t r2 = fread(buf2, 1, 10000, f2); if (r1 != r2 || memcmp(buf1, buf2, r1)) { fclose(f1); fclose(f2); return false; // Files are not equal } } while (!feof(f1) && !feof(f2)); bool returnValue = feof(f1) && feof(f2); fclose(f1); fclose(f2); return returnValue; } void TestSetXMLStringException() { bool exceptionThrown3=false; try { std::string file = GetTestDataFilePath("IGT-Data/InvalidVersionNavigationDataTestData.xml"); - mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); - reader->Read(file); + mitk::NavigationDataSet::Pointer dataset = dynamic_cast (mitk::IOUtil::LoadBaseData(file).GetPointer()); } - catch(mitk::IGTIOException) + catch(mitk::Exception) { exceptionThrown3=true; } MITK_TEST_CONDITION(exceptionThrown3, "Reading an invalid XML string and expecting a exception"); } void TestCompareFunction() { CPPUNIT_ASSERT_MESSAGE("Asserting that compare function for files works correctly - Positive Test", CompareFiles(pathRead, pathRead)); CPPUNIT_ASSERT_MESSAGE("Asserting that compare function for files works correctly - Negative Test", ! CompareFiles(pathRead, pathWrong) ); } }; MITK_TEST_SUITE_REGISTRATION(mitkNavigationDataSetReaderWriterXML) \ No newline at end of file diff --git a/Modules/IGT/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp b/Modules/IGT/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp index cb37e65683..e87b3ce1e8 100644 --- a/Modules/IGT/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataToIGTLMessageFilterTest.cpp @@ -1,261 +1,260 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataToIGTLMessageFilter.h" #include "mitkNavigationDataSequentialPlayer.h" -#include "mitkNavigationDataReaderXML.h" #include #include #include #include #include #include #include /** * Simple test for the class "NavigationDataToIGTLMessageFilter". * * argc and argv are the command line parameters which were passed to * the ADD_TEST command in the CMakeLists.txt file. For the automatic * tests, argv is either empty for the simple tests or contains the filename * of a test image for the image tests (see CMakeLists.txt). */ mitk::NavigationDataToIGTLMessageFilter::Pointer m_NavigationDataToIGTLMessageFilter; static void Setup() { m_NavigationDataToIGTLMessageFilter = mitk::NavigationDataToIGTLMessageFilter::New(); } static void SetInputs() { //Build up test data mitk::NavigationData::Pointer nd0 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); mitk::NavigationData::PositionType point0; point0[0] = 1.0; point0[1] = 2.0; point0[2] = 3.0; mitk::NavigationData::OrientationType orientation0; orientation0.put(0, 1.0); orientation0.put(1, 0.0); orientation0.put(2, 0.0); orientation0.put(3, 0.0); nd0->SetPosition(point0); nd0->SetOrientation(orientation0); nd0->SetDataValid(true); mitk::NavigationData::PositionType point1; point1[0] = 4.0; point1[1] = 5.0; point1[2] = 6.0; mitk::NavigationData::OrientationType orientation1; orientation1.put(0, 21.0); orientation1.put(1, 22.0); orientation1.put(2, 23.0); orientation1.put(3, 24.0); nd1->SetPosition(point1); nd1->SetOrientation(orientation1); nd1->SetDataValid(true); mitk::NavigationData::PositionType point2; point2[0] = 7.0; point2[1] = 8.0; point2[2] = 9.0; mitk::NavigationData::OrientationType orientation2; orientation2.put(0, 31.0); orientation2.put(1, 32.0); orientation2.put(2, 33.0); orientation2.put(3, 34.0); nd2->SetPosition(point2); nd2->SetOrientation(orientation2); nd2->SetDataValid(true); mitk::NavigationData::PositionType point3; point3[0] = 10.0; point3[1] = 11.0; point3[2] = 12.0; mitk::NavigationData::OrientationType orientation3; orientation3.put(0, 0.0); orientation3.put(1, 0.0); orientation3.put(2, 0.0); orientation3.put(3, 1.0); nd3->SetPosition(point3); nd3->SetOrientation(orientation3); nd3->SetDataValid(true); m_NavigationDataToIGTLMessageFilter->SetInput(0, nd0); m_NavigationDataToIGTLMessageFilter->SetInput(1, nd1); m_NavigationDataToIGTLMessageFilter->SetInput(2, nd2); m_NavigationDataToIGTLMessageFilter->SetInput(3, nd3); } static void TestModeQTransMsg() { Setup(); SetInputs(); m_NavigationDataToIGTLMessageFilter->SetOperationMode( mitk::NavigationDataToIGTLMessageFilter::ModeSendQTransMsg); //Process mitk::IGTLMessage::Pointer msg0 = m_NavigationDataToIGTLMessageFilter->GetOutput(); mitk::IGTLMessage::Pointer msg1 = m_NavigationDataToIGTLMessageFilter->GetOutput(1); mitk::IGTLMessage::Pointer msg2 = m_NavigationDataToIGTLMessageFilter->GetOutput(2); mitk::IGTLMessage::Pointer msg3 = m_NavigationDataToIGTLMessageFilter->GetOutput(3); msg0->Update(); igtl::PositionMessage::Pointer igtlMsg0 = dynamic_cast(msg0->GetMessage().GetPointer()); igtl::PositionMessage::Pointer igtlMsg3 = dynamic_cast(msg3->GetMessage().GetPointer()); MITK_TEST_OUTPUT(<< "Testing the converted OpenIGTLink messages:"); MITK_TEST_CONDITION(igtlMsg0.IsNotNull(), "Message0 is not null?"); MITK_TEST_CONDITION(igtlMsg3.IsNotNull(), "Message3 is not null?"); //Convert the data from the igtl message back to mitk types float pos0_[3]; float orientation0_[4]; igtlMsg0->GetPosition(pos0_); igtlMsg0->GetQuaternion(orientation0_); mitk::NavigationData::PositionType pos0; pos0[0] = pos0_[0]; pos0[1] = pos0_[1]; pos0[2] = pos0_[2]; mitk::NavigationData::OrientationType orientation0; orientation0[0] = orientation0_[0]; orientation0[1] = orientation0_[1]; orientation0[2] = orientation0_[2]; orientation0[3] = orientation0_[3]; float pos3_[3]; float orientation3_[4]; igtlMsg3->GetPosition(pos3_); igtlMsg3->GetQuaternion(orientation3_); mitk::NavigationData::PositionType pos3; pos3[0] = pos3_[0]; pos3[1] = pos3_[1]; pos3[2] = pos3_[2]; mitk::NavigationData::OrientationType orientation3; orientation3[0] = orientation3_[0]; orientation3[1] = orientation3_[1]; orientation3[2] = orientation3_[2]; orientation3[3] = orientation3_[3]; MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to QTrans OpenIGTLink messages:"); MITK_TEST_CONDITION(mitk::Equal(pos0, m_NavigationDataToIGTLMessageFilter->GetInput(0)->GetPosition()), "Position0 correct?"); MITK_TEST_CONDITION(mitk::Equal(pos3, m_NavigationDataToIGTLMessageFilter->GetInput(3)->GetPosition()), "Position3 correct?"); MITK_TEST_CONDITION(mitk::Equal(orientation0, m_NavigationDataToIGTLMessageFilter->GetInput(0)->GetOrientation()), "Orientation0 correct?"); MITK_TEST_CONDITION(mitk::Equal(orientation3, m_NavigationDataToIGTLMessageFilter->GetInput(3)->GetOrientation()), "Orientation3 correct?"); } static void TestModeTransMsg() { Setup(); SetInputs(); m_NavigationDataToIGTLMessageFilter->SetOperationMode( mitk::NavigationDataToIGTLMessageFilter::ModeSendTransMsg); //Process mitk::IGTLMessage::Pointer msg0 = m_NavigationDataToIGTLMessageFilter->GetOutput(); mitk::IGTLMessage::Pointer msg1 = m_NavigationDataToIGTLMessageFilter->GetOutput(1); mitk::IGTLMessage::Pointer msg2 = m_NavigationDataToIGTLMessageFilter->GetOutput(2); mitk::IGTLMessage::Pointer msg3 = m_NavigationDataToIGTLMessageFilter->GetOutput(3); msg0->Update(); igtl::TransformMessage::Pointer igtlMsg0 = dynamic_cast(msg0->GetMessage().GetPointer()); igtl::TransformMessage::Pointer igtlMsg3 = dynamic_cast(msg3->GetMessage().GetPointer()); MITK_TEST_OUTPUT(<< "Testing the converted OpenIGTLink messages:"); MITK_TEST_CONDITION(igtlMsg0.IsNotNull(), "Message0 is not null?"); MITK_TEST_CONDITION(igtlMsg3.IsNotNull(), "Message3 is not null?"); //Convert the data from the igtl message back to mitk types mitk::AffineTransform3D::Pointer affineTransformation0 = mitk::AffineTransform3D::New(); igtl::Matrix4x4 transformation0_; mitk::Matrix3D transformation0; mitk::Vector3D offset0; igtlMsg0->GetMatrix(transformation0_); for ( unsigned int r = 0; r < 3; r++ ) { for ( unsigned int c = 0; c < 3; c++ ) { transformation0.GetVnlMatrix().set( r , c , transformation0_[r][c] ); } offset0.SetElement(r, transformation0_[r][3]); } //convert the igtl matrix here and set it in the affine transformation affineTransformation0->SetMatrix(transformation0); affineTransformation0->SetOffset(offset0); //the easiest way to convert the affine transform to position and quaternion mitk::NavigationData::Pointer nd0 = mitk::NavigationData::New(affineTransformation0, true); mitk::AffineTransform3D::Pointer affineTransformation3 = mitk::AffineTransform3D::New(); igtl::Matrix4x4 transformation3_; mitk::Matrix3D transformation3; mitk::Vector3D offset3; igtlMsg3->GetMatrix(transformation3_); for ( unsigned int r = 0; r < 3; r++ ) { for ( unsigned int c = 0; c < 3; c++ ) { transformation3.GetVnlMatrix().set( r , c , transformation3_[r][c] ); } offset3.SetElement(r, transformation3_[r][3]); } //convert the igtl matrix here and set it in the affine transformation affineTransformation3->SetMatrix(transformation3); affineTransformation3->SetOffset(offset3); //the easiest way to convert the affine transform to position and quaternion mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(affineTransformation3, true); MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to Trans OpenIGTLink messages:"); MITK_TEST_CONDITION(mitk::Equal(nd0->GetPosition(), m_NavigationDataToIGTLMessageFilter->GetInput(0)->GetPosition()), "Position0 correct?"); MITK_TEST_CONDITION(mitk::Equal(nd3->GetPosition(), m_NavigationDataToIGTLMessageFilter->GetInput(3)->GetPosition()), "Position3 correct?"); MITK_TEST_CONDITION(mitk::Equal(nd0->GetOrientation(), m_NavigationDataToIGTLMessageFilter->GetInput(0)->GetOrientation()), "Orientation0 correct?"); MITK_TEST_CONDITION(mitk::Equal(nd3->GetOrientation(), m_NavigationDataToIGTLMessageFilter->GetInput(3)->GetOrientation()), "Orientation3 correct?"); } static void NavigationDataToIGTLMessageFilterContructor_DefaultCall_IsNotEmpty() { Setup(); MITK_TEST_CONDITION_REQUIRED(m_NavigationDataToIGTLMessageFilter.IsNotNull(),"Testing instantiation"); //I think this test is meaningless, because it will never ever fail. I keep it for know just to be save. } int mitkNavigationDataToIGTLMessageFilterTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataToIGTLMessageFilter"); NavigationDataToIGTLMessageFilterContructor_DefaultCall_IsNotEmpty(); TestModeQTransMsg(); TestModeTransMsg(); MITK_TEST_END(); } diff --git a/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp b/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp index 8bb4d8d7a8..3985dcf531 100644 --- a/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp +++ b/Modules/IGT/Testing/mitkNavigationDataToPointSetFilterTest.cpp @@ -1,240 +1,239 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataToPointSetFilter.h" #include "mitkNavigationDataSequentialPlayer.h" -#include "mitkNavigationDataReaderXML.h" #include #include +#include #include /** * Simple example for a test for the (non-existent) class "NavigationDataToPointSetFilter". * * argc and argv are the command line parameters which were passed to * the ADD_TEST command in the CMakeLists.txt file. For the automatic * tests, argv is either empty for the simple tests or contains the filename * of a test image for the image tests (see CMakeLists.txt). */ mitk::NavigationDataToPointSetFilter::Pointer m_NavigationDataToPointSetFilter; static void Setup() { m_NavigationDataToPointSetFilter = mitk::NavigationDataToPointSetFilter::New(); } static void TestMode3D() { Setup(); m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3D); //Build up test data mitk::NavigationData::Pointer nd0 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd1 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); mitk::NavigationData::PositionType point0; point0[0] = 1.0; point0[1] = 2.0; point0[2] = 3.0; nd0->SetPosition(point0); nd0->SetDataValid(true); mitk::NavigationData::PositionType point1; point1[0] = 4.0; point1[1] = 5.0; point1[2] = 6.0; nd1->SetPosition(point1); nd1->SetDataValid(true); mitk::NavigationData::PositionType point2; point2[0] = 7.0; point2[1] = 8.0; point2[2] = 9.0; nd2->SetPosition(point2); nd2->SetDataValid(true); mitk::NavigationData::PositionType point3; point3[0] = 10.0; point3[1] = 11.0; point3[2] = 12.0; nd3->SetPosition(point3); nd3->SetDataValid(true); m_NavigationDataToPointSetFilter->SetInput(0, nd0); m_NavigationDataToPointSetFilter->SetInput(1, nd1); m_NavigationDataToPointSetFilter->SetInput(2, nd2); m_NavigationDataToPointSetFilter->SetInput(3, nd3); //Process mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput(); mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1); mitk::PointSet::Pointer pointSet2 = m_NavigationDataToPointSetFilter->GetOutput(2); mitk::PointSet::Pointer pointSet3 = m_NavigationDataToPointSetFilter->GetOutput(3); pointSet0->Update(); MITK_TEST_OUTPUT(<< "Testing the conversion of navigation data object to PointSets in Mode 3D:"); MITK_TEST_CONDITION(mitk::Equal(pointSet0->GetPoint(0), point0), "Pointset 0 correct?"); MITK_TEST_CONDITION(mitk::Equal(pointSet1->GetPoint(0), point1), "Pointset 1 correct?"); MITK_TEST_CONDITION(mitk::Equal(pointSet2->GetPoint(0), point2), "Pointset 2 correct?"); MITK_TEST_CONDITION(mitk::Equal(pointSet3->GetPoint(0), point3), "Pointset 3 correct?"); } static void TestMode4D() { Setup(); m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode4D); m_NavigationDataToPointSetFilter->SetRingBufferSize(2); //Build up test data mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd2 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd3 = mitk::NavigationData::New(); mitk::NavigationData::Pointer nd4 = mitk::NavigationData::New(); mitk::NavigationData::PositionType point; point[0] = 1.0; point[1] = 2.0; point[2] = 3.0; nd->SetPosition(point); point[0] = 4.0; point[1] = 5.0; point[2] = 6.0; nd2->SetPosition(point); point[0] = 7.0; point[1] = 8.0; point[2] = 9.0; nd3->SetPosition(point); point[0] = 10.0; point[1] = 11.0; point[2] = 12.0; nd4->SetPosition(point); m_NavigationDataToPointSetFilter->SetInput(0, nd); m_NavigationDataToPointSetFilter->SetInput(1, nd2); mitk::PointSet::Pointer pointSet = m_NavigationDataToPointSetFilter->GetOutput(); pointSet->Update(); MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 && pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 , "Testing the conversion of navigation data object to one point set in Mode 4D in first timestep" ); m_NavigationDataToPointSetFilter->SetInput(0, nd3); m_NavigationDataToPointSetFilter->SetInput(1, nd4); m_NavigationDataToPointSetFilter->Update(); pointSet = m_NavigationDataToPointSetFilter->GetOutput(); MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 1.0 && pointSet->GetPoint(0,0)[1] == 2.0 && pointSet->GetPoint(0,0)[2] == 3.0 && pointSet->GetPoint(1,0)[0] == 4.0 && pointSet->GetPoint(1,0)[1] == 5.0 && pointSet->GetPoint(1,0)[2] == 6.0 && pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 && pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0 , "Testing the conversion of navigation data object to one point set in Mode 4D in second timestep" ); m_NavigationDataToPointSetFilter->SetInput(0, nd3); m_NavigationDataToPointSetFilter->SetInput(1, nd4); pointSet = m_NavigationDataToPointSetFilter->GetOutput(); pointSet->Update(); MITK_TEST_CONDITION( pointSet->GetPoint(0,0)[0] == 7.0 && pointSet->GetPoint(0,0)[1] == 8.0 && pointSet->GetPoint(0,0)[2] == 9.0 && pointSet->GetPoint(1,0)[0] == 10.0 && pointSet->GetPoint(1,0)[1] == 11.0 && pointSet->GetPoint(1,0)[2] == 12.0 && pointSet->GetPoint(0,1)[0] == 7.0 && pointSet->GetPoint(0,1)[1] == 8.0 && pointSet->GetPoint(0,1)[2] == 9.0 && pointSet->GetPoint(1,1)[0] == 10.0 && pointSet->GetPoint(1,1)[1] == 11.0 && pointSet->GetPoint(1,1)[2] == 12.0 , "Testing the correct ring buffer behavior" ); } static void TestMode3DMean() { Setup(); m_NavigationDataToPointSetFilter->SetOperationMode(mitk::NavigationDataToPointSetFilter::Mode3DMean); int numberForMean = 5; m_NavigationDataToPointSetFilter->SetNumberForMean(numberForMean); MITK_TEST_CONDITION(mitk::Equal(m_NavigationDataToPointSetFilter->GetNumberForMean(), numberForMean), "Testing get/set for numberForMean"); mitk::NavigationDataSequentialPlayer::Pointer player = mitk::NavigationDataSequentialPlayer::New(); std::string file(MITK_IGT_DATA_DIR); file.append("/NavigationDataTestData_2Tools.xml"); - mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); - - player->SetNavigationDataSet( reader->Read(file) ); + mitk::NavigationDataSet::Pointer dataset = dynamic_cast (mitk::IOUtil::LoadBaseData(file).GetPointer()); + player->SetNavigationDataSet(dataset); for (unsigned int i = 0; i< player->GetNumberOfOutputs(); i++) { m_NavigationDataToPointSetFilter->SetInput(i, player->GetOutput(i)); } mitk::PointSet::Pointer pointSet0 = m_NavigationDataToPointSetFilter->GetOutput(); mitk::PointSet::Pointer pointSet1 = m_NavigationDataToPointSetFilter->GetOutput(1); m_NavigationDataToPointSetFilter->Update(); MITK_TEST_CONDITION(pointSet0->GetPoint(0)[0]==3.0 && pointSet0->GetPoint(0)[1]==2.0 && pointSet0->GetPoint(0)[2]==5.0, "Testing the average of first input"); MITK_TEST_CONDITION(pointSet1->GetPoint(0)[0]==30.0 && pointSet1->GetPoint(0)[1]==20.0 && pointSet1->GetPoint(0)[2]==50.0, "Testing the average of second input"); } static void NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty() { Setup(); MITK_TEST_CONDITION_REQUIRED(m_NavigationDataToPointSetFilter.IsNotNull(),"Testing instantiation"); //I think this test is meaningless, because it will never ever fail. I keep it for know just to be save. } static void NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth() { Setup(); mitk::NavigationData::Pointer nd_in = mitk::NavigationData::New(); const mitk::NavigationData* nd_out = mitk::NavigationData::New(); mitk::NavigationData::PositionType point; point[0] = 1.0; point[1] = 2.0; point[2] = 3.0; nd_in->SetPosition(point); m_NavigationDataToPointSetFilter->SetInput(nd_in); nd_out = m_NavigationDataToPointSetFilter->GetInput(); MITK_TEST_CONDITION( nd_out->GetPosition() == nd_in->GetPosition(), "Testing get/set input" ); } int mitkNavigationDataToPointSetFilterTest(int /* argc */, char* /*argv*/[]) { MITK_TEST_BEGIN("NavigationDataToPointSetFilter"); NavigationDataToPointSetFilterContructor_DefaultCall_IsNotEmpty(); NavigationDataToPointSetFilterSetInput_SimplePoint_EqualsGroundTruth(); TestMode3D(); TestMode4D(); // TestMode3DMean(); //infinite loop in debug mode, see bug 17763 MITK_TEST_END(); } diff --git a/Modules/IGT/Testing/mitkOpenIGTLinkTrackingDeviceTest.cpp b/Modules/IGT/Testing/mitkOpenIGTLinkTrackingDeviceTest.cpp new file mode 100644 index 0000000000..1c5f5a3247 --- /dev/null +++ b/Modules/IGT/Testing/mitkOpenIGTLinkTrackingDeviceTest.cpp @@ -0,0 +1,87 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +//testing headers +#include +#include + +//headers of IGT classes releated to the tested class +#include + +//sleep headers +#include +#include + +class mitkOpenIGTLinkTrackingDeviceTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkOpenIGTLinkTrackingDeviceTestSuite); + MITK_TEST(TestInstantiation); + MITK_TEST(TestSetConnectionParameters); + MITK_TEST(TestDiscoverToolMethod); + CPPUNIT_TEST_SUITE_END(); + +private: + /** Members used inside the different test methods. All members are initialized via setUp().*/ + mitk::OpenIGTLinkTrackingDevice::Pointer m_OpenIGTLinkTrackingDevice; + +public: + + /**@brief Setup Always call this method before each Test-case to ensure correct and new intialization of the used members for a new test case. (If the members are not used in a test, the method does not need to be called).*/ + void setUp() + { + m_OpenIGTLinkTrackingDevice = mitk::OpenIGTLinkTrackingDevice::New(); + } + + void tearDown() + { + } + + void TestInstantiation() + { + // let's create objects of our classes + mitk::OpenIGTLinkTrackingDevice::Pointer testDevice = mitk::OpenIGTLinkTrackingDevice::New(); + CPPUNIT_ASSERT_MESSAGE("Testing instantiation of OpenIGTLinkTrackingDevice",testDevice.IsNotNull()); + } + + void TestSetConnectionParameters() + { + m_OpenIGTLinkTrackingDevice->SetHostname("localhost"); + m_OpenIGTLinkTrackingDevice->SetPortNumber(10); + CPPUNIT_ASSERT_MESSAGE("Testing method SetHostname() ...", m_OpenIGTLinkTrackingDevice->GetHostname()=="localhost"); + CPPUNIT_ASSERT_MESSAGE("Testing method SetPort() ...", m_OpenIGTLinkTrackingDevice->GetPortNumber()==10); + } + + void TestDiscoverToolMethod() + { + CPPUNIT_ASSERT_MESSAGE("Testing DiscoverTools() without initialization. (Warnings are expected)", m_OpenIGTLinkTrackingDevice->DiscoverTools()==false); + m_OpenIGTLinkTrackingDevice->SetPortNumber(10); + CPPUNIT_ASSERT_MESSAGE("Testing DiscoverTools() with initialization, but without existing server. (Warnings are expected)", m_OpenIGTLinkTrackingDevice->DiscoverTools()==false); + + m_OpenIGTLinkTrackingDevice->SetHostname("193.174.50.103"); + m_OpenIGTLinkTrackingDevice->SetPortNumber(18944); + m_OpenIGTLinkTrackingDevice->DiscoverTools(20000); + m_OpenIGTLinkTrackingDevice->OpenConnection(); + m_OpenIGTLinkTrackingDevice->StartTracking(); + + std::this_thread::sleep_for(std::chrono::seconds(20)); + + m_OpenIGTLinkTrackingDevice->StopTracking(); + m_OpenIGTLinkTrackingDevice->CloseConnection(); + + } + +}; +MITK_TEST_SUITE_REGISTRATION(mitkOpenIGTLinkTrackingDevice) diff --git a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp new file mode 100644 index 0000000000..76449d504c --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp @@ -0,0 +1,341 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkOpenIGTLinkTrackingDevice.h" +#include "mitkOpenIGTLinkTrackingTool.h" +#include "mitkIGTConfig.h" +#include "mitkIGTTimeStamp.h" +#include "mitkIGTHardwareException.h" +#include "mitkTrackingTypes.h" +#include +#include +#include +#include +#include + +//sleep headers +#include +#include + +typedef itk::MutexLockHolder MutexLockHolder; + + +mitk::OpenIGTLinkTrackingDevice::OpenIGTLinkTrackingDevice(): mitk::TrackingDevice() +{ + //set the type of this tracking device + this->m_Data = mitk::DeviceDataOpenIGTLinkTrackingDeviceConnection; + + m_OpenIGTLinkClient = mitk::IGTLClient::New(); + m_OpenIGTLinkClient->EnableInfiniteBufferingMode(m_OpenIGTLinkClient->GetReceiveQueue(),false); + m_OpenIGTLinkClient->SetName("OpenIGTLink Tracking Device"); + + m_IGTLDeviceSource = mitk::IGTLDeviceSource::New(); + m_IGTLDeviceSource->SetIGTLDevice(m_OpenIGTLinkClient); +} + + +mitk::OpenIGTLinkTrackingDevice::~OpenIGTLinkTrackingDevice() +{ +} + +int mitk::OpenIGTLinkTrackingDevice::GetPortNumber() +{ + return m_OpenIGTLinkClient->GetPortNumber(); +} + +std::string mitk::OpenIGTLinkTrackingDevice::GetHostname() +{ + return m_OpenIGTLinkClient->GetHostname(); +} + + +void mitk::OpenIGTLinkTrackingDevice::SetPortNumber(int portNumber) +{ + m_OpenIGTLinkClient->SetPortNumber(portNumber); +} + +void mitk::OpenIGTLinkTrackingDevice::SetHostname(std::string hostname) +{ + m_OpenIGTLinkClient->SetHostname(hostname); +} + +bool mitk::OpenIGTLinkTrackingDevice::IsDeviceInstalled() +{ + return true; +} + +mitk::TrackingTool* mitk::OpenIGTLinkTrackingDevice::AddTool( const char* toolName, const char* fileName ) +{ + mitk::OpenIGTLinkTrackingTool::Pointer t;// = mitk::OpenIGTLinkTrackingTool::New(); + //TODO: Implement + if (this->InternalAddTool(t) == false) + return NULL; + return t.GetPointer(); +} + + +bool mitk::OpenIGTLinkTrackingDevice::InternalAddTool(OpenIGTLinkTrackingTool::Pointer tool) +{ + m_AllTools.push_back(tool); + return true; +} + + +bool mitk::OpenIGTLinkTrackingDevice::DiscoverTools(int WaitingTime) +{ + if (m_OpenIGTLinkClient->GetPortNumber() == -1) + { + MITK_WARN << "Connection not initialized, aborting (invalid port number)."; + return false; + } + + try + { + m_IGTLDeviceSource->Connect(); + m_IGTLDeviceSource->StartCommunication(); + } + catch(std::runtime_error &e) + { + MITK_WARN << "Open IGT Link device retruned an error while trying to connect: " << e.what(); + return false; + } + + //send a message to the server: start tracking stream + mitk::IGTLMessageFactory::Pointer msgFactory = m_OpenIGTLinkClient->GetMessageFactory(); + std::string message = "STT_TDATA"; + igtl::MessageBase::Pointer sttMsg = msgFactory->CreateInstance(message); + ((igtl::StartTrackingDataMessage*)sttMsg.GetPointer())->SetResolution(1); + m_OpenIGTLinkClient->SendMessage(sttMsg); + + std::this_thread::sleep_for(std::chrono::seconds(WaitingTime)); + //Sleep(WaitingTime); //wait for data to arrive + + m_IGTLDeviceSource->Update(); + + //check the tracking stream for the number and type of tools + //igtl::MessageBase::Pointer receivedMessage = m_OpenIGTLinkClient->GetNextMessage(); + mitk::IGTLMessage::Pointer receivedMessage = m_IGTLDeviceSource->GetOutput(); + if (receivedMessage.IsNull()) + { + MITK_WARN << "No message was received. Is there really a server?"; + return false; + } + else if (!receivedMessage->IsDataValid()) + { + MITK_WARN << "Received invalid message."; + return false; + } + + const char* msgType = receivedMessage->GetIGTLMessageType(); + + if( !(strcmp(msgType,"TDATA") == 0) ) + { + MITK_INFO << "Server does not send tracking data. Received data is not of the type TDATA. Received type: " << msgType; + return true; + } + + + igtl::TrackingDataMessage* tdMsg = (igtl::TrackingDataMessage*)(receivedMessage->GetMessage().GetPointer()); + + if(!tdMsg) + { + MITK_WARN << "Cannot cast message object as expected, aborting!"; + return false; + } + + int numberOfTools = tdMsg->GetNumberOfTrackingDataElements(); + MITK_INFO << "Found " << numberOfTools << " tools"; + for(int i=0; iGetTrackingDataElement(i,currentTrackingData); + std::string name = currentTrackingData->GetName(); + if (name == "") //if no name was given create a default name + { + std::stringstream defaultName; + defaultName << "OpenIGTLinkTool#" << i; + name = defaultName.str(); + } + MITK_INFO << "Added tool " << name << " to tracking device."; + newTool->SetToolName(name); + this->InternalAddTool(newTool); + } + + m_IGTLDeviceSource->StopCommunication(); + this->SetState(Ready); + return true; +} + +void mitk::OpenIGTLinkTrackingDevice::UpdateTools() +{ + if (this->GetState() != Tracking) + { + MITK_ERROR << "Method was called in the wrong state, something went wrong!"; + return; + } + + m_IGTLMsgToNavDataFilter->Update(); + for (int i=0; iGetToolCount(); i++) + { + mitk::NavigationData::Pointer currentNavData = m_IGTLMsgToNavDataFilter->GetOutput(i); + m_AllTools.at(i)->SetDataValid(currentNavData->IsDataValid()); + m_AllTools.at(i)->SetPosition(currentNavData->GetPosition()); + m_AllTools.at(i)->SetOrientation(currentNavData->GetOrientation()); + m_AllTools.at(i)->SetIGTTimeStamp(currentNavData->GetIGTTimeStamp()); + + + mitk::Point3D pos; + m_AllTools.at(i)->GetPosition(pos); + + //MITK_INFO << "Updated Tool " << i << " Pos: " << pos; + } + +} + + +bool mitk::OpenIGTLinkTrackingDevice::StartTracking() +{ + //check tracking state + if (this->GetState() != Ready) + { + MITK_WARN << "Cannot start tracking, device is not ready!"; + return false; + } + + try + { + m_IGTLDeviceSource->StartCommunication(); + + //send a message to the server: start tracking stream + mitk::IGTLMessageFactory::Pointer msgFactory = m_OpenIGTLinkClient->GetMessageFactory(); + std::string message = "STT_TDATA"; + //m_OpenIGTLinkClient->SendMessage(msgFactory->CreateInstance(message)); + } + catch(std::runtime_error &e) + { + MITK_WARN << "Open IGT Link device retruned an error while starting communication: " << e.what(); + return false; + } + + //create internal igtl pipeline + m_IGTLMsgToNavDataFilter = mitk::IGTLMessageToNavigationDataFilter::New(); + m_IGTLMsgToNavDataFilter->SetNumberOfExpectedOutputs(this->GetToolCount()); + m_IGTLMsgToNavDataFilter->ConnectTo(m_IGTLDeviceSource); + + + //connect itk events + typedef itk::SimpleMemberCommand< mitk::OpenIGTLinkTrackingDevice > CurCommandType; + CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); + messageReceivedCommand->SetCallbackFunction(this, &mitk::OpenIGTLinkTrackingDevice::UpdateTools); + m_MessageReceivedObserverTag = m_OpenIGTLinkClient->AddObserver(mitk::MessageReceivedEvent(),messageReceivedCommand); + + this->SetState(Tracking); + return true; +} + + +bool mitk::OpenIGTLinkTrackingDevice::StopTracking() +{ + //check tracking state + if (this->GetState() != Tracking) + { + MITK_WARN << "Cannot open connection, device is already connected!"; + return false; + } + + m_OpenIGTLinkClient->RemoveObserver(m_MessageReceivedObserverTag); //disconnect itk events + + try + { + m_IGTLDeviceSource->StopCommunication(); + } + catch(std::runtime_error &e) + { + MITK_WARN << "Open IGT Link device retruned an error while stopping communication: " << e.what(); + return false; + } + this->SetState(Ready); + return true; +} + + +unsigned int mitk::OpenIGTLinkTrackingDevice::GetToolCount() const +{ + return (unsigned int)this->m_AllTools.size(); +} + + +mitk::TrackingTool* mitk::OpenIGTLinkTrackingDevice::GetTool(unsigned int toolNumber) const +{ + if ( toolNumber >= this->GetToolCount()) + return NULL; + else + return this->m_AllTools[toolNumber]; +} + + +bool mitk::OpenIGTLinkTrackingDevice::OpenConnection() +{ + //check tracking state + if (this->GetState() != Setup) + { + MITK_WARN << "Cannot open connection, device is already connected!"; + return false; + } + + try + { + m_IGTLDeviceSource->Connect(); + } + catch(std::runtime_error &e) + { + MITK_WARN << "Open IGT Link device retruned an error while trying to connect: " << e.what(); + return false; + } + this->SetState(Ready); + return true; +} + + +bool mitk::OpenIGTLinkTrackingDevice::CloseConnection() +{ + //check tracking state + if (this->GetState() != Ready) + { + MITK_WARN << "Cannot close connection, device is in the wrong state!"; + return false; + } + + try + { + m_IGTLDeviceSource->Disconnect(); + } + catch(std::runtime_error &e) + { + MITK_WARN << "Open IGT Link device retruned an error while trying to disconnect: " << e.what(); + return false; + } + + this->SetState(Setup); + + return true; +} + +std::vector mitk::OpenIGTLinkTrackingDevice::GetAllTools() +{ + return this->m_AllTools; +} diff --git a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.h b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.h new file mode 100644 index 0000000000..710f00baf1 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.h @@ -0,0 +1,145 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKOPENIGTLINKTRACKINGDEVICE_H_HEADER_INCLUDED_ +#define MITKOPENIGTLINKTRACKINGDEVICE_H_HEADER_INCLUDED_ + + +#include +#include +#include +#include +#include +#include +#include + + +namespace mitk +{ + /** Documentation: + * \brief An object of this class represents the MicronTracker device. You can add tools to this + * device, then open the connection and start tracking. The tracking device will then + * continuously update the tool coordinates. + * \ingroup IGT + */ + class MITKIGT_EXPORT OpenIGTLinkTrackingDevice : public TrackingDevice + { + public: + mitkClassMacro(OpenIGTLinkTrackingDevice, TrackingDevice); + itkFactorylessNewMacro(Self) + itkCloneMacro(Self) + + /** Sets the port number for the Open IGT Link connection. Default value is -1 (invalid). */ + void SetPortNumber(int portNumber); + + /** Sets the hostname for the Open IGT Link connection. Default value is 127.0.0.1 (localhost). */ + void SetHostname(std::string hostname); + + int GetPortNumber(); + + std::string GetHostname(); + + /** + * \brief Starts the tracking. + * \return Returns true if the tracking is started. Throws an exception if an error occures. + * @throw mitk::IGTHardwareException Throws an exception if there is an error during start tracking. + */ + virtual bool StartTracking(); + + /** + * \brief Stops the tracking. + * \return Returns true if the tracking is stopped. + */ + virtual bool StopTracking(); + + /** + * \brief Opens the connection to the device. This have to be done before the tracking is started. + * @throw mitk::IGTHardwareException Throws an exception if there is an error during open connection. + */ + virtual bool OpenConnection(); + + /** + * \brief Closes the connection and clears all resources. + */ + virtual bool CloseConnection(); + + /** + * \return Returns the number of tools which have been added to the device. + */ + virtual unsigned int GetToolCount() const; + + /** + * \param toolNumber The number of the tool which should be given back. + * \return Returns the tool which the number "toolNumber". Returns NULL, if there is + * no tool with this number. + */ + TrackingTool* GetTool(unsigned int toolNumber) const; + + /** + * \brief Discover the tools available from the connected OpenIGTLink device and adds these tools to this tracking device. Therefore, a connection + * is opened, the tools are discovered and added. + * \param WaitingTime Defines how long the method waits for an answer from the server (in milliseconds). Default value is 10000 (10 seconds). + * \return Returns true if the connection was established and the tools were discovered successfully and - if at least one tool was found - were added to this device. + * Retruns false if no valid connection is available. + */ + bool DiscoverTools(int WaitingTime = 10000); + + + /** + * \brief Create a new OpenIGTLink tool with toolName and fileName and add it to the list of tools + * + * Note that tools are usually provided by the OpenIGTLink connection. In most cases, the method DiscoverTools() should be used + * instead which automatically finds the provided tools. If you use this method to manually add tools be sure that you add the + * same number and type of tools that are provided by the connected device. Otherwise problems might occur when you try to start + * tracking. + */ + mitk::TrackingTool* AddTool(const char* toolName, const char* fileName); + + bool IsDeviceInstalled(); + + protected: + OpenIGTLinkTrackingDevice(); + ~OpenIGTLinkTrackingDevice(); + + /** + * \brief Adds a tool to the tracking device. + * + * \param tool The tool which will be added. + * \return Returns true if the tool has been added, false otherwise. + */ + bool InternalAddTool(OpenIGTLinkTrackingTool::Pointer tool); + + + /** Updates the tools from the open IGT link connection. Is called every time a message received event is invoked.*/ + void UpdateTools(); + unsigned long m_MessageReceivedObserverTag; + + /** + * \return Returns all tools of the tracking device. + */ + std::vector GetAllTools(); + + //OpenIGTLink connection class + mitk::IGTLClient::Pointer m_OpenIGTLinkClient; + + //OpenIGTLink pipeline + mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource; + mitk::IGTLMessageToNavigationDataFilter::Pointer m_IGTLMsgToNavDataFilter; + + std::vector m_AllTools; ///< vector holding all tools + }; +}//mitk +#endif /* MITKOpenIGTLinkTRACKINGDEVICE_H_HEADER_INCLUDED_ */ diff --git a/Modules/RDF/mitkRdfNode.h b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.cpp similarity index 67% copy from Modules/RDF/mitkRdfNode.h copy to Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.cpp index 9ade7dee04..13f9ae4d24 100644 --- a/Modules/RDF/mitkRdfNode.h +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.cpp @@ -1,39 +1,28 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +#include "mitkOpenIGTLinkTrackingTool.h" +#include +#include +#include -#ifndef MITKRDFNODE_H -#define MITKRDFNODE_H - -#include - -namespace mitk { - -/** - * \ingroup MitkRDFModule - */ -class MITKRDF_EXPORT RdfNode +mitk::OpenIGTLinkTrackingTool::OpenIGTLinkTrackingTool() :InternalTrackingTool() { - -public: - - bool dummy(); - -}; - } -#endif +mitk::OpenIGTLinkTrackingTool::~OpenIGTLinkTrackingTool(void) +{ +} diff --git a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.h b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.h new file mode 100644 index 0000000000..67f761eadb --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.h @@ -0,0 +1,46 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKOpenIGTLinkTrackingTOOL_H_HEADER_INCLUDED_ +#define MITKOpenIGTLinkTrackingTOOL_H_HEADER_INCLUDED_ + +#include +#include + +namespace mitk +{ + class OpenIGTLinkTrackingDevice; + /** Documentation: + * \brief An object of this class represents a OpenIGTLink tracking tool. + * A tool has to be added to a tracking device which will then + * continuously update the tool coordinates. + * \ingroup IGT + */ + class MITKIGT_EXPORT OpenIGTLinkTrackingTool : public InternalTrackingTool + { + public: + friend class OpenIGTLinkTrackingTrackingDevice; + mitkClassMacro(OpenIGTLinkTrackingTool, InternalTrackingTool); + + itkFactorylessNewMacro(Self) + protected: + + itkCloneMacro(Self) + OpenIGTLinkTrackingTool(); + virtual ~OpenIGTLinkTrackingTool(); + }; +}//mitk +#endif // MITKOpenIGTLinkTrackingTOOL_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp b/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp index fa652ce6ce..09cbd8c4c4 100644 --- a/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp +++ b/Modules/IGT/Tutorial/mitkIGTTutorialStep1.cpp @@ -1,194 +1,190 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include #include +#include #include #include #include "mitkNavigationDataDisplacementFilter.h" #include #include -#include -#include #include //##Documentation //## \brief A small console tutorial about MITK-IGT int main(int /*argc*/, char* /*argv*/[]) { //************************************************************************* // What we will do... //************************************************************************* //In this tutorial we build up a small navigation pipeline with a virtual tracking device //which produce random positions and orientation so no additional hardware is required. //The source of the pipeline is a TrackingDeviceSource object. This we connect to a simple //filter which just displaces the positions with an offset. After that we use a recorder //to store this new positions and other information to disc in a XML file. After that we use //another source (NavigationDataPlayer) to replay the recorded data. //************************************************************************* // Part I: Basic initialization of the source and tracking device //************************************************************************* //First of all create a tracking device object and two tools for this "device". //Here we take the VirtualTrackingDevice. This is not a real tracking device it just delivers random //positions and orientations. You can use other/real tracking devices if you replace the following //code with different tracking devices, e.g. mitk::NDITrackingDevice. The tools represent the //sensors of the tracking device. The TrackingDevice fills the tools with data. std::cout << "Generating TrackingDevice ..." << std::endl; mitk::VirtualTrackingDevice::Pointer tracker = mitk::VirtualTrackingDevice::New(); tracker->AddTool("tool1"); tracker->AddTool("tool2"); //The tracking device object is used for the physical connection to the device. To use the //data inside of our tracking pipeline we need a source. This source encapsulate the tracking device //and provides objects of the type mitk::NavigationData as output. The NavigationData objects stores //position, orientation, if the data is valid or not and special error informations in a covariance //matrix. // //Typically the start of our pipeline is a TrackingDeviceSource. To work correct we have to set a //TrackingDevice object. Attention you have to set the tools before you set the whole TrackingDevice //object to the TrackingDeviceSource because the source need to know how many outputs should be //generated. std::cout << "Generating Source ..." << std::endl; mitk::TrackingDeviceSource::Pointer source = mitk::TrackingDeviceSource::New(); source->SetTrackingDevice(tracker); //here we set the device for the pipeline source source->Connect(); //here we connect to the tracking system //Note we do not call this on the TrackingDevice object source->StartTracking(); //start the tracking //Now the source generates outputs. //************************************************************************* // Part II: Create a NavigationDataToNavigationDataFilter //************************************************************************* //The next thing we do is using a NavigationDataToNavigationDataFilter. One of these filter is the //very simple NavigationDataDisplacementFilter. This filter just changes the positions of the input //NavigationData objects with an offset for each direction (X,Y,Z). The input of this filter is the //source and the output of this filter is the "displaced" input. std::cout << "Generating DisplacementFilter ..." << std::endl; mitk::NavigationDataDisplacementFilter::Pointer displacer = mitk::NavigationDataDisplacementFilter::New(); mitk::Vector3D offset; mitk::FillVector3D(offset, 10.0, 100.0, 1.0); //initialize the offset displacer->SetOffset(offset); //now set the offset in the NavigationDataDisplacementFilter object //Connect the two filters. You can use the ConnectTo method to automatically connect all outputs from one filter // to inputs from another filter. displacer->ConnectTo(source.GetPointer()); // Alternatively, you can manually connect inputs and outputs. // The code below shows what the ConnectTo Methods does internally: // //for (unsigned int i = 0; i < source->GetNumberOfOutputs(); i++) //{ // displacer->SetInput(i, source->GetOutput(i)); //here we connect to the displacement filter //} //************************************************************************* // Part III: Record the data with the NavigationDataRecorder //************************************************************************* //The next part of our pipeline is the recorder. The input of the recorder is the output of the displacement filter //and the output is a XML file with the name "Test Output-0.xml", which is written with a NavigationDataSetWriter. std::cout << "Start Recording ..." << std::endl; //we need the stringstream for building up our filename std::stringstream filename; //the .xml extension and an counter is NOT added automatically anymore -- that was the case in an earlier version filename << itksys::SystemTools::GetCurrentWorkingDirectory() << "/Test Output-0.xml"; std::cout << "Record to file: " << filename.str() << " ..." << std::endl; mitk::NavigationDataRecorder::Pointer recorder = mitk::NavigationDataRecorder::New(); //now the output of the displacer object is connected to the recorder object recorder->ConnectTo(displacer); recorder->StartRecording(); //after finishing the settings you can start the recording mechanism //now every update of the recorder stores one line into the file for //each added NavigationData for (unsigned int x = 0; x < 100; x++) //write 100 datasets { recorder->Update(); //the update causes one line in the XML file for every tool //in this case two lines itksys::SystemTools::Delay(100); //sleep a little } recorder->StopRecording(); //to get proper XML files you should stop recording //if your application crashes during recording no data //will be lost it is all stored to disc - //The writer needs a filename. Otherwise the output - //is redirected to the console. - mitk::NavigationDataSetWriterXML writer; - writer.Write(filename.str(),recorder->GetNavigationDataSet()); - + //The IO-System needs a filename. Otherwise the output + //is redirected to the console. See MITK-Concepts page for more details on IO in MITK + mitk::IOUtil::SaveBaseData(recorder->GetNavigationDataSet(), filename.str()); //************************************************************************* // Part IV: Play the data with the NavigationDataPlayer //************************************************************************* //The recording is finished now so now we can play the data. The NavigationDataPlayer is similar //to the TrackingDevice source. It also derives from NavigationDataSource. So you can use a player //instead of a TrackingDeviceSource. The input of this player is a NavigationDataSet, which we //read with a NavigationDataReader. std::cout << "Start playing from file: " << filename.str() << " ..." << std::endl; mitk::NavigationDataPlayer::Pointer player = mitk::NavigationDataPlayer::New(); - mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); - mitk::NavigationDataSet::Pointer naviDataSet = reader->Read(filename.str()); + mitk::NavigationDataSet::Pointer naviDataSet = dynamic_cast (mitk::IOUtil::LoadBaseData(filename.str()).GetPointer()); player->SetNavigationDataSet(naviDataSet); player->StartPlaying(); //this starts the player //From now on the player provides NavigationDatas in the order and //correct time as they were recorded //this connects the outputs of the player to the NavigationData objects mitk::NavigationData::Pointer nd = player->GetOutput(); mitk::NavigationData::Pointer nd2 = player->GetOutput(1); for (unsigned int x=0; x<100; x++) { if (nd.IsNotNull()) //check if the output is not null { //With this update the NavigationData object propagates through the pipeline to get a new value. //In this case we only have a source (NavigationDataPlayer). nd->Update(); std::cout << x << ": 1:" << nd->GetPosition() << std::endl; std::cout << x << ": 2:" << nd2->GetPosition() << std::endl; std::cout << x << ": 1:" << nd->GetOrientation() << std::endl; std::cout << x << ": 2:" << nd2->GetOrientation() << std::endl; itksys::SystemTools::Delay(100); //sleep a little like in the recorder part } } player->StopPlaying(); //This stops the player //With another call of StartPlaying the player will start again at the beginning of the file itksys::SystemTools::Delay(2000); std::cout << "finished" << std::endl; } diff --git a/Modules/IGT/files.cmake b/Modules/IGT/files.cmake index aef21bf3f1..483841a8e7 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,92 +1,88 @@ set(CPP_FILES TestingHelper/mitkNavigationToolStorageTestHelper.cpp Algorithms/mitkNavigationDataDelayFilter.cpp Algorithms/mitkNavigationDataDisplacementFilter.cpp Algorithms/mitkNavigationDataEvaluationFilter.cpp Algorithms/mitkNavigationDataLandmarkTransformFilter.cpp Algorithms/mitkNavigationDataReferenceTransformFilter.cpp Algorithms/mitkNavigationDataSmoothingFilter.cpp Algorithms/mitkNavigationDataToMessageFilter.cpp Algorithms/mitkNavigationDataToNavigationDataFilter.cpp Algorithms/mitkNavigationDataToPointSetFilter.cpp Algorithms/mitkNavigationDataTransformFilter.cpp Algorithms/mitkIGTLMessageToNavigationDataFilter.cpp Algorithms/mitkNavigationDataToIGTLMessageFilter.cpp Common/mitkIGTTimeStamp.cpp Common/mitkSerialCommunication.cpp Common/mitkTrackingTypes.cpp - DataManagement/mitkNavigationData.cpp - DataManagement/mitkNavigationDataSet.cpp DataManagement/mitkNavigationDataSource.cpp DataManagement/mitkNavigationTool.cpp DataManagement/mitkNavigationToolStorage.cpp DataManagement/mitkTrackingDeviceSourceConfigurator.cpp DataManagement/mitkTrackingDeviceSource.cpp ExceptionHandling/mitkIGTException.cpp ExceptionHandling/mitkIGTHardwareException.cpp ExceptionHandling/mitkIGTIOException.cpp IO/mitkNavigationDataPlayer.cpp IO/mitkNavigationDataPlayerBase.cpp IO/mitkNavigationDataRecorder.cpp IO/mitkNavigationDataRecorderDeprecated.cpp IO/mitkNavigationDataSequentialPlayer.cpp IO/mitkNavigationToolReader.cpp IO/mitkNavigationToolStorageSerializer.cpp IO/mitkNavigationToolStorageDeserializer.cpp IO/mitkNavigationToolWriter.cpp IO/mitkNavigationDataReaderInterface.cpp - IO/mitkNavigationDataReaderXML.cpp - IO/mitkNavigationDataReaderCSV.cpp - IO/mitkNavigationDataSetWriterXML.cpp - IO/mitkNavigationDataSetWriterCSV.cpp Rendering/mitkCameraVisualization.cpp Rendering/mitkNavigationDataObjectVisualizationFilter.cpp TrackingDevices/mitkClaronTool.cpp TrackingDevices/mitkClaronTrackingDevice.cpp TrackingDevices/mitkInternalTrackingTool.cpp TrackingDevices/mitkNDIPassiveTool.cpp TrackingDevices/mitkNDIProtocol.cpp TrackingDevices/mitkNDITrackingDevice.cpp TrackingDevices/mitkTrackingDevice.cpp TrackingDevices/mitkTrackingTool.cpp TrackingDevices/mitkTrackingVolumeGenerator.cpp TrackingDevices/mitkVirtualTrackingDevice.cpp TrackingDevices/mitkVirtualTrackingTool.cpp TrackingDevices/mitkOptitrackErrorMessages.cpp TrackingDevices/mitkOptitrackTrackingDevice.cpp TrackingDevices/mitkOptitrackTrackingTool.cpp + TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp + TrackingDevices/mitkOpenIGTLinkTrackingTool.cpp ) set(RESOURCE_FILES ClaronMicron.stl IntuitiveDaVinci.stl NDIAurora.stl NDIAurora_Dome.stl NDIAuroraCompactFG_Dome.stl NDIAuroraPlanarFG_Dome.stl NDIAuroraTabletopFG_Dome.stl NDIAuroraTabletopFG_Prototype_Dome.stl NDIPolarisOldModel.stl NDIPolarisSpectra.stl NDIPolarisSpectraExtendedPyramid.stl NDIPolarisVicra.stl ) if(MITK_USE_MICRON_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterface.cpp) else() set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkClaronInterfaceStub.cpp) endif(MITK_USE_MICRON_TRACKER) if(MITK_USE_MICROBIRD_TRACKER) set(CPP_FILES ${CPP_FILES} TrackingDevices/mitkMicroBirdTrackingDevice.cpp) endif(MITK_USE_MICROBIRD_TRACKER) diff --git a/Modules/IGTBase/CMakeLists.txt b/Modules/IGTBase/CMakeLists.txt index f2d0202473..abb7877502 100644 --- a/Modules/IGTBase/CMakeLists.txt +++ b/Modules/IGTBase/CMakeLists.txt @@ -1,4 +1,4 @@ -MITK_CREATE_MODULE( - DEPENDS MitkCore - WARNINGS_AS_ERRORS -) +MITK_CREATE_MODULE(DEPENDS MitkCore + ) + +add_subdirectory(autoload) diff --git a/Modules/IGTBase/autoload/CMakeLists.txt b/Modules/IGTBase/autoload/CMakeLists.txt new file mode 100644 index 0000000000..e2cfc34638 --- /dev/null +++ b/Modules/IGTBase/autoload/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(IO) diff --git a/Modules/IGTBase/autoload/IO/CMakeLists.txt b/Modules/IGTBase/autoload/IO/CMakeLists.txt new file mode 100644 index 0000000000..0684437037 --- /dev/null +++ b/Modules/IGTBase/autoload/IO/CMakeLists.txt @@ -0,0 +1,6 @@ +MITK_CREATE_MODULE(IGTIO + DEPENDS MitkIGTBase + PACKAGE_DEPENDS tinyxml + WARNINGS_AS_ERRORS + AUTOLOAD_WITH MitkCore + ) diff --git a/Modules/IGTBase/autoload/IO/files.cmake b/Modules/IGTBase/autoload/IO/files.cmake new file mode 100644 index 0000000000..8e6176b939 --- /dev/null +++ b/Modules/IGTBase/autoload/IO/files.cmake @@ -0,0 +1,7 @@ +set(CPP_FILES + mitkIGTBaseActivator.cpp + mitkNavigationDataSetWriterXML.cpp + mitkNavigationDataSetWriterCSV.cpp + mitkNavigationDataReaderXML.cpp + mitkNavigationDataReaderCSV.cpp +) diff --git a/Modules/IGTBase/autoload/IO/mitkIGTBaseActivator.cpp b/Modules/IGTBase/autoload/IO/mitkIGTBaseActivator.cpp new file mode 100644 index 0000000000..282880795b --- /dev/null +++ b/Modules/IGTBase/autoload/IO/mitkIGTBaseActivator.cpp @@ -0,0 +1,41 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkIGTBaseActivator.h" + +#include +#include +#include +#include + +namespace mitk { + +void IOExtActivator::Load(us::ModuleContext*) +{ + m_NavigationDataSetWriterXML.reset(new NavigationDataSetWriterXML()); + m_NavigationDataSetWriterCSV.reset(new NavigationDataSetWriterCSV()); + m_NavigationDataReaderCSV.reset(new NavigationDataReaderCSV()); + m_NavigationDataReaderXML.reset(new NavigationDataReaderXML()); + +} + +void IOExtActivator::Unload(us::ModuleContext*) +{ +} + +} + +US_EXPORT_MODULE_ACTIVATOR(mitk::IOExtActivator) diff --git a/Modules/IGTBase/autoload/IO/mitkIGTBaseActivator.h b/Modules/IGTBase/autoload/IO/mitkIGTBaseActivator.h new file mode 100644 index 0000000000..23dce5863e --- /dev/null +++ b/Modules/IGTBase/autoload/IO/mitkIGTBaseActivator.h @@ -0,0 +1,46 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKIGTBASEACTIVATOR_H +#define MITKIGTBASEACTIVATOR_H + +#include + +#include + +namespace mitk { + +struct IFileReader; +struct IFileWriter; + +class IOExtActivator : public us::ModuleActivator +{ +public: + + void Load(us::ModuleContext*context) override; + void Unload(us::ModuleContext* context) override; + +private: + + std::unique_ptr m_NavigationDataSetWriterXML; + std::unique_ptr m_NavigationDataSetWriterCSV; + std::unique_ptr m_NavigationDataReaderXML; + std::unique_ptr m_NavigationDataReaderCSV; +}; + +} + +#endif // MITKIGTBASEACTIVATOR_H diff --git a/Modules/IGT/IO/mitkNavigationDataReaderCSV.cpp b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderCSV.cpp similarity index 82% rename from Modules/IGT/IO/mitkNavigationDataReaderCSV.cpp rename to Modules/IGTBase/autoload/IO/mitkNavigationDataReaderCSV.cpp index afd0c8e67c..c3983e5120 100644 --- a/Modules/IGT/IO/mitkNavigationDataReaderCSV.cpp +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderCSV.cpp @@ -1,164 +1,180 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +// MITK #include "mitkNavigationDataReaderCSV.h" +#include + +// STL #include -mitk::NavigationDataReaderCSV::NavigationDataReaderCSV() + +mitk::NavigationDataReaderCSV::NavigationDataReaderCSV() : AbstractFileReader( + mitk::IGTMimeTypes::NAVIGATIONDATASETCSV_MIMETYPE(), + "MITK NavigationData Reader (CSV)") { + RegisterService(); +} +mitk::NavigationDataReaderCSV::NavigationDataReaderCSV(const mitk::NavigationDataReaderCSV& other) : AbstractFileReader(other) +{ } mitk::NavigationDataReaderCSV::~NavigationDataReaderCSV() { +} + +mitk::NavigationDataReaderCSV* mitk::NavigationDataReaderCSV::Clone() const +{ + return new NavigationDataReaderCSV(*this); +} + +std::vector> mitk::NavigationDataReaderCSV::Read() +{ + std::vector fileContent = GetFileContentLineByLine(GetInputLocation()); + int NumOfTools = getNumberOfToolsInLine(fileContent[0]); + + mitk::NavigationDataSet::Pointer returnValue = mitk::NavigationDataSet::New(NumOfTools); + std::vector result; + result.push_back(returnValue.GetPointer()); + + // start from line 1 to leave out header + for (unsigned int i = 1; iAddNavigationDatas(parseLine(fileContent[i], NumOfTools)); + } + return result; } + int mitk::NavigationDataReaderCSV::getNumberOfToolsInLine(std::string line) { std::vector tokens=splitLine(line); int size = tokens.size(); int NumOfTools = (size-1)/8; if ( (size-1)%8 != 0 ) { MITK_ERROR("mitkNavigationDataReader") << "Illegal csv-file! Unexpected number of columns found! Assuming " << NumOfTools << " tools!"; } return NumOfTools ; } std::vector mitk::NavigationDataReaderCSV::splitLine(std::string line) { std::vector elems; std::stringstream ss(line); std::string item; while (std::getline(ss, item, ';')) { elems.push_back(item); } return elems; } mitk::NavigationData::Pointer mitk::NavigationDataReaderCSV::CreateNd(std::string timestamp, std::string valid, std::string X, std::string Y, std::string Z, std::string QX, std::string QY, std::string QZ, std::string QR) { mitk::NavigationData::Pointer result= mitk::NavigationData::New(); mitk::Point3D position; mitk::Quaternion orientation; bool isValid = false; double time; time = StringToDouble(timestamp); if (valid == "1") isValid = true; else isValid = false; position[0] = StringToDouble(X); position[1] = StringToDouble(Y); position[2] = StringToDouble(Z); orientation[0] = StringToDouble(QX); orientation[1] = StringToDouble(QY); orientation[2] = StringToDouble(QZ); orientation[3] = StringToDouble(QR); result->SetIGTTimeStamp(time); result->SetDataValid(isValid); result->SetPosition(position); result->SetOrientation(orientation); return result; } double mitk::NavigationDataReaderCSV::StringToDouble( const std::string& s ) { std::istringstream i(s); double x; if (!(i >> x)) return 0; return x; } std::vector mitk::NavigationDataReaderCSV::parseLine(std::string line, int NumOfTools) { std::vector parts = splitLine(line); std::vector result; for (int n = 0; n < NumOfTools; n++) { mitk::NavigationData::Pointer nd; int offset = n * 8; nd = CreateNd(parts[0], parts[offset + 1], parts[offset + 2], parts[offset + 3], parts[offset + 4], parts[offset + 5], parts[offset + 6], parts[offset + 7], parts[offset + 8]); result.push_back(nd); } return result; } -mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderCSV::Read(std::string fileName) -{ - std::vector fileContent = GetFileContentLineByLine(fileName); - int NumOfTools = getNumberOfToolsInLine(fileContent[0]); - - mitk::NavigationDataSet::Pointer returnValue = mitk::NavigationDataSet::New(NumOfTools); - - // start from line 1 to leave out header - for (int i = 1; iAddNavigationDatas( parseLine( fileContent[i], NumOfTools) ); - } - - - return returnValue; -} - - std::vector mitk::NavigationDataReaderCSV::GetFileContentLineByLine(std::string filename) { std::vector readData = std::vector(); //save old locale char * oldLocale; oldLocale = setlocale( LC_ALL, nullptr ); //define own locale std::locale C("C"); setlocale( LC_ALL, "C" ); //read file std::ifstream file; file.open(filename.c_str(), std::ios::in); if (file.good()) { //read out file file.seekg(0L, std::ios::beg); // move to begin of file while (! file.eof()) { std::string buffer; std::getline(file,buffer); // read out file line by line if (buffer.size() > 0) readData.push_back(buffer); } } file.close(); //switch back to old locale setlocale( LC_ALL, oldLocale ); return readData; } diff --git a/Modules/IGT/IO/mitkNavigationDataReaderCSV.h b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderCSV.h similarity index 85% rename from Modules/IGT/IO/mitkNavigationDataReaderCSV.h rename to Modules/IGTBase/autoload/IO/mitkNavigationDataReaderCSV.h index f709981bf5..06e02b54b1 100644 --- a/Modules/IGT/IO/mitkNavigationDataReaderCSV.h +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderCSV.h @@ -1,78 +1,82 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - #ifndef MITKNavigationDataReaderCSV_H_HEADER_INCLUDED_ #define MITKNavigationDataReaderCSV_H_HEADER_INCLUDED_ -#include "mitkNavigationDataReaderInterface.h" +#include +#include namespace mitk { /** This class reads csv logged navigation datas from the hard disc and returns * the navigation data set. * * Caution: at the moment only one navigation data is supported which means that only * the data of the first navigation tool in the file is read! */ - class MITKIGT_EXPORT NavigationDataReaderCSV : public NavigationDataReaderInterface + class NavigationDataReaderCSV : public AbstractFileReader { public: - mitkClassMacro(NavigationDataReaderCSV, NavigationDataReaderInterface); - itkNewMacro(Self); + NavigationDataReaderCSV(); + virtual ~NavigationDataReaderCSV(); /** @return Returns the NavigationDataSet of the first tool in the given file. * Returns an empty NavigationDataSet if the file could not be read. */ - virtual mitk::NavigationDataSet::Pointer Read(std::string fileName) override; + using AbstractFileReader::Read; + virtual std::vector> Read() override; protected: - NavigationDataReaderCSV(); - virtual ~NavigationDataReaderCSV(); /** * /brief Creates a NavigationData Pointer based on the given Input. */ mitk::NavigationData::Pointer CreateNd(std::string timestamp, std::string valid, std::string X, std::string Y, std::string Z, std::string QX, std::string QY, std::string QZ, std::string QR); /** * /brief Presents File Content line by line */ std::vector GetFileContentLineByLine(std::string filename); /** * /brief Calculates the Number of Tools based on the number of colums per line. */ int getNumberOfToolsInLine(std::string line); /** * /brief Converts string to double returns zero if failing */ std::vector parseLine(std::string line, int NumOfTools); /** * /brief Converts string to double returns zero if failing */ double StringToDouble( const std::string& s ); /** * /brief Split line in elemens based on a given delim */ std::vector splitLine(std::string line); + + NavigationDataReaderCSV(const NavigationDataReaderCSV& other); + + virtual mitk::NavigationDataReaderCSV* Clone() const override; + }; } #endif // MITKNavigationDataReaderCSV_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataReaderXML.cpp b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.cpp similarity index 85% rename from Modules/IGT/IO/mitkNavigationDataReaderXML.cpp rename to Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.cpp index c56319118f..e88cca719d 100644 --- a/Modules/IGT/IO/mitkNavigationDataReaderXML.cpp +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.cpp @@ -1,355 +1,383 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +// MITK #include "mitkNavigationDataReaderXML.h" +#include + +// Third Party #include #include -#include "tinyxml.h" +#include -//includes for exceptions -#include "mitkIGTException.h" -#include "mitkIGTIOException.h" -mitk::NavigationDataReaderXML::NavigationDataReaderXML() - : m_parentElement(nullptr), m_currentNode(nullptr) +mitk::NavigationDataReaderXML::NavigationDataReaderXML() : AbstractFileReader( + mitk::IGTMimeTypes::NAVIGATIONDATASETXML_MIMETYPE(), + "MITK NavigationData Reader (XML)"), m_parentElement(nullptr), m_currentNode(nullptr) { + RegisterService(); } mitk::NavigationDataReaderXML::~NavigationDataReaderXML() { +} + +mitk::NavigationDataReaderXML::NavigationDataReaderXML(const mitk::NavigationDataReaderXML& other) : AbstractFileReader(other), m_parentElement(nullptr), m_currentNode(nullptr) +{ +} + +mitk::NavigationDataReaderXML* mitk::NavigationDataReaderXML::Clone() const +{ + return new NavigationDataReaderXML(*this); +} + +std::vector> mitk::NavigationDataReaderXML::Read() +{ + mitk::NavigationDataSet::Pointer dataset; + std::istream* in = GetInputStream(); + if (in == nullptr) + { + dataset = Read(GetInputLocation()); + } else { + dataset = Read(in); + } + std::vector result; + mitk::BaseData::Pointer base = dataset.GetPointer(); + result.push_back(base); + return result; } + + mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(std::string fileName) { //save old locale char * oldLocale; - oldLocale = setlocale( LC_ALL, nullptr ); + oldLocale = setlocale(LC_ALL, 0); //define own locale std::locale C("C"); - setlocale( LC_ALL, "C" ); + setlocale(LC_ALL, "C"); m_FileName = fileName; TiXmlDocument document; - if ( !document.LoadFile(fileName)) + if (!document.LoadFile(fileName)) { - mitkThrowException(mitk::IGTIOException) << "File '"<QueryIntAttribute("Ver", &m_FileVersion) != TIXML_SUCCESS) { if (m_DataElem->QueryIntAttribute("version", &m_FileVersion) != TIXML_SUCCESS) { mitkThrowException(mitk::IGTIOException) << "Version not specified in XML file."; } } if (m_FileVersion != 1) { - mitkThrowException(mitk::IGTIOException) << "File format version "<QueryIntAttribute("ToolCount", &m_NumberOfOutputs); mitk::NavigationDataSet::Pointer navigationDataSet = this->ReadNavigationDataSet(); //switch back to old locale - setlocale( LC_ALL, oldLocale ); + setlocale(LC_ALL, oldLocale); return navigationDataSet; } mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::Read(std::istream* stream) { //save old locale char * oldLocale; oldLocale = setlocale( LC_ALL, nullptr ); //define own locale std::locale C("C"); setlocale( LC_ALL, "C" ); // first get the file version m_FileVersion = this->GetFileVersion(stream); // check if we have a valid version: m_FileVersion has to be always bigger than 1 for playing if (m_FileVersion < 1) { StreamInvalid("Playing not possible. Invalid file version!"); return nullptr; } m_NumberOfOutputs = this->GetNumberOfNavigationDatas(stream); if (m_NumberOfOutputs == 0) { return nullptr; } mitk::NavigationDataSet::Pointer dataSet = this->ReadNavigationDataSet(); //switch back to old locale setlocale( LC_ALL, oldLocale ); return dataSet; } mitk::NavigationDataSet::Pointer mitk::NavigationDataReaderXML::ReadNavigationDataSet() { mitk::NavigationDataSet::Pointer navigationDataSet = mitk::NavigationDataSet::New(m_NumberOfOutputs); mitk::NavigationData::Pointer curNavigationData; do { std::vector navDatas(m_NumberOfOutputs); - for (unsigned int n = 0; n < m_NumberOfOutputs; ++n) + for (int n = 0; n < m_NumberOfOutputs; ++n) { curNavigationData = this->ReadVersion1(); if (curNavigationData.IsNull()) { if (n != 0) { MITK_WARN("mitkNavigationDataReaderXML") << "Different number of NavigationData objects for different tools. Ignoring last ones."; } break; } navDatas.at(n) = curNavigationData; } if (curNavigationData.IsNotNull()) { navigationDataSet->AddNavigationDatas(navDatas); } } while (curNavigationData.IsNotNull()); return navigationDataSet; } mitk::NavigationData::Pointer mitk::NavigationDataReaderXML::ReadVersion1() { if ( !m_parentElement ) { - mitkThrowException(mitk::IGTIOException) - << "Reading XML is not possible. Parent element is not set."; + mitkThrowException(mitk::IGTIOException) << "Reading XML is not possible. Parent element is not set."; } TiXmlElement* elem; m_currentNode = m_parentElement->IterateChildren(m_currentNode); bool delElem; if(m_currentNode) { elem = m_currentNode->ToElement(); if(elem==nullptr) { mitkThrowException(mitk::IGTException) << "Cannot find element: Is this file damaged?"; } delElem = false; } else { elem = new TiXmlElement(""); delElem = true; } mitk::NavigationData::Pointer nd = this->ReadNavigationData(elem); if(delElem) { delete elem; } return nd; } mitk::NavigationData::Pointer mitk::NavigationDataReaderXML::ReadNavigationData(TiXmlElement* elem) { if (elem == nullptr) {mitkThrow() << "Error: Element is NULL!";} mitk::NavigationData::Pointer nd = mitk::NavigationData::New(); mitk::NavigationData::PositionType position; mitk::NavigationData::OrientationType orientation(0.0,0.0,0.0,0.0); mitk::NavigationData::TimeStampType timestamp = -1; mitk::NavigationData::CovarianceMatrixType matrix; bool hasPosition = true; bool hasOrientation = true; bool dataValid = false; position.Fill(0.0); matrix.SetIdentity(); elem->QueryDoubleAttribute("Time",×tamp); if (timestamp == -1) { return nullptr; //the calling method should check the return value if it is valid/not NULL } elem->QueryDoubleAttribute("X", &position[0]); elem->QueryDoubleAttribute("Y", &position[1]); elem->QueryDoubleAttribute("Z", &position[2]); elem->QueryDoubleAttribute("QX", &orientation[0]); elem->QueryDoubleAttribute("QY", &orientation[1]); elem->QueryDoubleAttribute("QZ", &orientation[2]); elem->QueryDoubleAttribute("QR", &orientation[3]); elem->QueryDoubleAttribute("C00", &matrix[0][0]); elem->QueryDoubleAttribute("C01", &matrix[0][1]); elem->QueryDoubleAttribute("C02", &matrix[0][2]); elem->QueryDoubleAttribute("C03", &matrix[0][3]); elem->QueryDoubleAttribute("C04", &matrix[0][4]); elem->QueryDoubleAttribute("C05", &matrix[0][5]); elem->QueryDoubleAttribute("C10", &matrix[1][0]); elem->QueryDoubleAttribute("C11", &matrix[1][1]); elem->QueryDoubleAttribute("C12", &matrix[1][2]); elem->QueryDoubleAttribute("C13", &matrix[1][3]); elem->QueryDoubleAttribute("C14", &matrix[1][4]); elem->QueryDoubleAttribute("C15", &matrix[1][5]); int tmpval = 0; elem->QueryIntAttribute("Valid", &tmpval); if (tmpval == 0) dataValid = false; else dataValid = true; tmpval = 0; elem->QueryIntAttribute("hO", &tmpval); if (tmpval == 0) hasOrientation = false; else hasOrientation = true; tmpval = 0; elem->QueryIntAttribute("hP", &tmpval); if (tmpval == 0) hasPosition = false; else hasPosition = true; nd->SetIGTTimeStamp(timestamp); nd->SetPosition(position); nd->SetOrientation(orientation); nd->SetCovErrorMatrix(matrix); nd->SetDataValid(dataValid); nd->SetHasOrientation(hasOrientation); nd->SetHasPosition(hasPosition); return nd; } // -- deprecated | begin unsigned int mitk::NavigationDataReaderXML::GetFileVersion(std::istream* stream) { if (stream==nullptr) { MITK_ERROR << "No input stream set!"; mitkThrowException(mitk::IGTIOException)<<"No input stream set!"; } if (!stream->good()) { MITK_ERROR << "Stream is not good!"; mitkThrowException(mitk::IGTIOException)<<"Stream is not good!"; } int version = 1; auto dec = new TiXmlDeclaration(); *stream >> *dec; if(strcmp(dec->Version(),"") == 0) { MITK_ERROR << "The input stream seems to have XML incompatible format"; mitkThrowException(mitk::IGTIOException) << "The input stream seems to have XML incompatible format"; } m_parentElement = new TiXmlElement(""); *stream >> *m_parentElement; //2nd line this is the file version std::string tempValue = m_parentElement->Value(); if(tempValue != "Version") { if(tempValue == "Data"){ m_parentElement->QueryIntAttribute("version",&version); } } else { m_parentElement->QueryIntAttribute("Ver",&version); } if (version > 0) { return version; } else { return 0; } } unsigned int mitk::NavigationDataReaderXML::GetNumberOfNavigationDatas(std::istream* stream) { if (stream == nullptr) { MITK_ERROR << "No input stream set!"; mitkThrowException(mitk::IGTException)<<"No input stream set!"; } if (!stream->good()) { MITK_ERROR << "Stream not good!"; mitkThrowException(mitk::IGTException)<<"Stream not good!"; } //If something has changed in a future version of the XML definition e.g. navigationcount or addional parameters //catch this here with a select case block (see GenerateData() method) int numberOfTools = 0; std::string tempValue = m_parentElement->Value(); if(tempValue == "Version"){ *stream >> *m_parentElement; } m_parentElement->QueryIntAttribute("ToolCount",&numberOfTools); if (numberOfTools > 0) { return numberOfTools; } return 0; } void mitk::NavigationDataReaderXML::StreamInvalid(std::string message) { m_StreamEnd = true; m_ErrorMessage = message; m_StreamValid = false; mitkThrowException(mitk::IGTIOException) << "Invalid stream!"; } // -- deprecated | end - diff --git a/Modules/IGT/IO/mitkNavigationDataReaderXML.h b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.h similarity index 82% rename from Modules/IGT/IO/mitkNavigationDataReaderXML.h rename to Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.h index a99bd98eb8..3d34a5150b 100644 --- a/Modules/IGT/IO/mitkNavigationDataReaderXML.h +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataReaderXML.h @@ -1,109 +1,108 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ #define MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ -#include "mitkNavigationDataReaderInterface.h" +#include +#include +// includes for exceptions +#include +#include class TiXmlElement; class TiXmlNode; namespace mitk { - class MITKIGT_EXPORT NavigationDataReaderXML : public NavigationDataReaderInterface + class NavigationDataReaderXML : public AbstractFileReader { public: - mitkClassMacro(NavigationDataReaderXML, NavigationDataReaderInterface); - itkNewMacro(Self); - - virtual mitk::NavigationDataSet::Pointer Read(std::string fileName) override; - virtual mitk::NavigationDataSet::Pointer Read(std::istream* stream); + NavigationDataReaderXML(); + virtual ~NavigationDataReaderXML(); - // -- deprecated | begin - /** - * \brief Sets the stream of this player. - * @throw mitk::IGTException Throws an exception if stream is NULL or if it is not good. - * \deprecated Will be removed in one of the next releases. Use SetFileName() instead. - */ - //void SetStream(std::istream* stream); - // -- deprecated | end + using AbstractFileReader::Read; + virtual std::vector> Read() override; protected: - NavigationDataReaderXML(); - virtual ~NavigationDataReaderXML(); + + NavigationDataReaderXML(const NavigationDataReaderXML& other); + virtual mitk::NavigationDataReaderXML* Clone() const override; NavigationDataSet::Pointer ReadNavigationDataSet(); /** * \brief This method reads one line of the XML document and returns the data as a NavigationData object * If there is a new file version another method must be added which reads this data. * @throw mitk::IGTException Throws an exceptions if file is damaged. */ mitk::NavigationData::Pointer ReadVersion1(); mitk::NavigationData::Pointer ReadNavigationData(TiXmlElement* elem); std::string m_FileName; TiXmlElement* m_parentElement; TiXmlNode* m_currentNode; int m_FileVersion; ///< indicates which XML encoding is used int m_NumberOfOutputs; ///< stores the number of outputs known from the XML document // -- deprecated | begin //std::istream* m_Stream; ///< stores a pointer to the input stream bool m_StreamEnd; ///< stores if the input stream arrived at end bool m_StreamValid; ///< stores if the input stream is valid or not std::string m_ErrorMessage; ///< stores the error message if the stream is invalid /** * \brief Creates a stream out of the filename given by the variable m_FileName. * The stream is then set to m_Stream. * * @throw mitk::IGTIOException Throws an exception if file does not exist * @throw mitk::IGTException Throws an exception if the stream is NULL */ //void CreateStreamFromFilename(); /** * \brief Returns the file version out of the XML document. * @throw mitk::IGTException Throws an mitk::IGTException an exception if stream is NULL or not good. * @throw mitk::IGTIOException Throws an mitk::IGTIOException if the stream has an incompatible XML format. */ unsigned int GetFileVersion(std::istream* stream); /** * \brief Returns the number of tracked tools out of the XML document. * @throw Throws an exception if stream is NULL. * @throw Throws an exception if the input stream has an XML incompatible format. */ unsigned int GetNumberOfNavigationDatas(std::istream* stream); /** * @brief This is a helping method which gives an error message and throws an exception with the given message. * It can be used if a stream is found to be invalid. * * @throw mitk::IGTIOException Always throws an exception. */ void StreamInvalid(std::string message); ///< help method which sets the stream invalid and displays an error // -- deprecated | end + private: + NavigationDataSet::Pointer Read(std::istream* stream); + NavigationDataSet::Pointer Read(std::string fileName); }; } // namespace mitk #endif // MITKNavigationDataReaderXML_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.cpp b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterCSV.cpp similarity index 70% rename from Modules/IGT/IO/mitkNavigationDataSetWriterCSV.cpp rename to Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterCSV.cpp index c8f3f1ae95..60429db6ea 100644 --- a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.cpp +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterCSV.cpp @@ -1,85 +1,97 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataSetWriterCSV.h" #include +#include -void mitk::NavigationDataSetWriterCSV::Write (std::string path, mitk::NavigationDataSet::Pointer data) +mitk::NavigationDataSetWriterCSV::NavigationDataSetWriterCSV() : AbstractFileWriter(NavigationDataSet::GetStaticNameOfClass(), + mitk::IGTMimeTypes::NAVIGATIONDATASETCSV_MIMETYPE(), + "MITK NavigationDataSet Reader (CSV)") { - MITK_INFO << "Writing navigation data set to file: " << path; - std::ofstream stream; - stream.open (path.c_str(), std::ios_base::trunc); + RegisterService(); +} + +mitk::NavigationDataSetWriterCSV::~NavigationDataSetWriterCSV() +{} - // Pass to Stream Handler - Write(&stream, data); - stream.close(); +mitk::NavigationDataSetWriterCSV::NavigationDataSetWriterCSV(const mitk::NavigationDataSetWriterCSV& other) : AbstractFileWriter(other) +{ +} + +mitk::NavigationDataSetWriterCSV* mitk::NavigationDataSetWriterCSV::Clone() const +{ + return new NavigationDataSetWriterCSV(*this); } -void mitk::NavigationDataSetWriterCSV::Write (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +void mitk::NavigationDataSetWriterCSV::Write() { - //save old locale + std::ostream* out = GetOutputStream(); + if (out == nullptr) + { + out = new std::ofstream(GetOutputLocation().c_str()); + } + mitk::NavigationDataSet::ConstPointer data = dynamic_cast (this->GetInput()); + + //save old locale char * oldLocale; oldLocale = setlocale( LC_ALL, nullptr ); //define own locale std::locale C("C"); setlocale( LC_ALL, "C" ); //write header unsigned int numberOfTools = data->GetNumberOfTools(); - for (unsigned int index = 0; index < numberOfTools; index++){ *stream << "TimeStamp_Tool" << index << + for (unsigned int index = 0; index < numberOfTools; index++){ *out << "TimeStamp_Tool" << index << ";Valid_Tool" << index << ";X_Tool" << index << ";Y_Tool" << index << ";Z_Tool" << index << ";QX_Tool" << index << ";QY_Tool" << index << ";QZ_Tool" << index << ";QR_Tool" << index << ";";} - *stream << "\n"; + *out << "\n"; - stream->precision(15); // rounding precision because we don't want to loose data. + out->precision(15); // rounding precision because we don't want to loose data. //write data MITK_INFO << "Number of timesteps: " << data->Size(); for (unsigned int i=0; iSize(); i++) { std::vector< mitk::NavigationData::Pointer > NavigationDatasOfCurrentStep = data->GetTimeStep(i); for (unsigned int toolIndex = 0; toolIndex < numberOfTools; toolIndex++) { mitk::NavigationData::Pointer nd = NavigationDatasOfCurrentStep.at(toolIndex); - *stream << nd->GetTimeStamp() << ";" + *out << nd->GetTimeStamp() << ";" << nd->IsDataValid() << ";" << nd->GetPosition()[0] << ";" << nd->GetPosition()[1] << ";" << nd->GetPosition()[2] << ";" << nd->GetOrientation()[0] << ";" << nd->GetOrientation()[1] << ";" << nd->GetOrientation()[2] << ";" << nd->GetOrientation()[3] << ";"; } - *stream << "\n"; + *out << "\n"; } + out->flush(); + delete out; //switch back to old locale setlocale( LC_ALL, oldLocale ); } - -mitk::NavigationDataSetWriterCSV::NavigationDataSetWriterCSV() -{} - -mitk::NavigationDataSetWriterCSV::~NavigationDataSetWriterCSV() -{} diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterCSV.h similarity index 71% copy from Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h copy to Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterCSV.h index bf51ddd5f9..c3c4092c87 100644 --- a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterCSV.h @@ -1,35 +1,41 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ #define MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ #include +#include namespace mitk { - class MITKIGT_EXPORT NavigationDataSetWriterCSV + class NavigationDataSetWriterCSV : public AbstractFileWriter { public: NavigationDataSetWriterCSV(); virtual~NavigationDataSetWriterCSV(); - virtual void Write (std::string path, mitk::NavigationDataSet::Pointer ); - virtual void Write (std::ostream* stream, mitk::NavigationDataSet::Pointer); + using AbstractFileWriter::Write; + virtual void Write() override; + + protected: + NavigationDataSetWriterCSV(const NavigationDataSetWriterCSV& other); + + virtual mitk::NavigationDataSetWriterCSV* Clone() const override; }; } #endif // MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterXML.cpp b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.cpp similarity index 78% rename from Modules/IGT/IO/mitkNavigationDataSetWriterXML.cpp rename to Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.cpp index 9f839956a1..b98061ec61 100644 --- a/Modules/IGT/IO/mitkNavigationDataSetWriterXML.cpp +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.cpp @@ -1,137 +1,147 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // MITK #include "mitkNavigationDataSetWriterXML.h" +#include // Third Party #include #include #include #include -mitk::NavigationDataSetWriterXML::NavigationDataSetWriterXML() +mitk::NavigationDataSetWriterXML::NavigationDataSetWriterXML() : AbstractFileWriter(NavigationDataSet::GetStaticNameOfClass(), + mitk::IGTMimeTypes::NAVIGATIONDATASETXML_MIMETYPE(), + "MITK NavigationDataSet Writer (XML)") { + RegisterService(); } -mitk::NavigationDataSetWriterXML::~NavigationDataSetWriterXML() +mitk::NavigationDataSetWriterXML::NavigationDataSetWriterXML(const mitk::NavigationDataSetWriterXML& other) : AbstractFileWriter(other) { } -void mitk::NavigationDataSetWriterXML::Write (std::string path, mitk::NavigationDataSet::Pointer data) +mitk::NavigationDataSetWriterXML::~NavigationDataSetWriterXML() { - std::ofstream stream; - stream.open (path.c_str(), std::ios_base::trunc); +} - // Pass to Stream Handler - Write(&stream, data); - stream.close(); +mitk::NavigationDataSetWriterXML* mitk::NavigationDataSetWriterXML::Clone() const +{ + return new NavigationDataSetWriterXML(*this); } -void mitk::NavigationDataSetWriterXML::Write (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +void mitk::NavigationDataSetWriterXML::Write() { + std::ostream* out = GetOutputStream(); + if (out == nullptr) + { + out = new std::ofstream( GetOutputLocation().c_str() ); + } + mitk::NavigationDataSet::ConstPointer data = dynamic_cast (this->GetInput()); + //save old locale char * oldLocale; oldLocale = setlocale( LC_ALL, nullptr ); - StreamHeader(stream, data); - StreamData(stream, data); - StreamFooter(stream); + StreamHeader(out, data); + StreamData(out, data); + StreamFooter(out); // Cleanup - - stream->flush(); + out->flush(); + delete out; //switch back to old locale setlocale( LC_ALL, oldLocale ); } -void mitk::NavigationDataSetWriterXML::StreamHeader (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +void mitk::NavigationDataSetWriterXML::StreamHeader (std::ostream* stream, mitk::NavigationDataSet::ConstPointer data) { stream->precision(10); //TODO store date and GMT time //checking if the stream is good if (stream->good()) { *stream << "" << std::endl; /**m_Stream << "" << std::endl;*/ // should be a generic version, meaning a member variable, which has the actual version *stream << " " << "GetNumberOfTools() << "\" version=\"1.0\">" << std::endl; } } -void mitk::NavigationDataSetWriterXML::StreamData (std::ostream* stream, mitk::NavigationDataSet::Pointer data) +void mitk::NavigationDataSetWriterXML::StreamData (std::ostream* stream, mitk::NavigationDataSet::ConstPointer data) { // For each time step in the Dataset for (auto it = data->Begin(); it != data->End(); it++) { for (std::size_t toolIndex = 0; toolIndex < it->size(); toolIndex++) { mitk::NavigationData::Pointer nd = it->at(toolIndex); auto elem = new TiXmlElement("ND"); elem->SetDoubleAttribute("Time", nd->GetIGTTimeStamp()); // elem->SetAttribute("SystemTime", sysTimeStr); // tag for system time elem->SetDoubleAttribute("Tool", toolIndex); elem->SetDoubleAttribute("X", nd->GetPosition()[0]); elem->SetDoubleAttribute("Y", nd->GetPosition()[1]); elem->SetDoubleAttribute("Z", nd->GetPosition()[2]); elem->SetDoubleAttribute("QX", nd->GetOrientation()[0]); elem->SetDoubleAttribute("QY", nd->GetOrientation()[1]); elem->SetDoubleAttribute("QZ", nd->GetOrientation()[2]); elem->SetDoubleAttribute("QR", nd->GetOrientation()[3]); elem->SetDoubleAttribute("C00", nd->GetCovErrorMatrix()[0][0]); elem->SetDoubleAttribute("C01", nd->GetCovErrorMatrix()[0][1]); elem->SetDoubleAttribute("C02", nd->GetCovErrorMatrix()[0][2]); elem->SetDoubleAttribute("C03", nd->GetCovErrorMatrix()[0][3]); elem->SetDoubleAttribute("C04", nd->GetCovErrorMatrix()[0][4]); elem->SetDoubleAttribute("C05", nd->GetCovErrorMatrix()[0][5]); elem->SetDoubleAttribute("C10", nd->GetCovErrorMatrix()[1][0]); elem->SetDoubleAttribute("C11", nd->GetCovErrorMatrix()[1][1]); elem->SetDoubleAttribute("C12", nd->GetCovErrorMatrix()[1][2]); elem->SetDoubleAttribute("C13", nd->GetCovErrorMatrix()[1][3]); elem->SetDoubleAttribute("C14", nd->GetCovErrorMatrix()[1][4]); elem->SetDoubleAttribute("C15", nd->GetCovErrorMatrix()[1][5]); if (nd->IsDataValid()) elem->SetAttribute("Valid",1); else elem->SetAttribute("Valid",0); if (nd->GetHasOrientation()) elem->SetAttribute("hO",1); else elem->SetAttribute("hO",0); if (nd->GetHasPosition()) elem->SetAttribute("hP",1); else elem->SetAttribute("hP",0); *stream << " " << *elem << std::endl; delete elem; } } } void mitk::NavigationDataSetWriterXML::StreamFooter (std::ostream* stream) { *stream << "" << std::endl; } diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterXML.h b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.h similarity index 72% rename from Modules/IGT/IO/mitkNavigationDataSetWriterXML.h rename to Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.h index 8d0e48b64b..a4360a2250 100644 --- a/Modules/IGT/IO/mitkNavigationDataSetWriterXML.h +++ b/Modules/IGTBase/autoload/IO/mitkNavigationDataSetWriterXML.h @@ -1,41 +1,47 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNavigationDataSetWriterXML_H_HEADER_INCLUDED_ #define MITKNavigationDataSetWriterXML_H_HEADER_INCLUDED_ #include +#include namespace mitk { - class MITKIGT_EXPORT NavigationDataSetWriterXML + class NavigationDataSetWriterXML : public AbstractFileWriter { public: NavigationDataSetWriterXML(); virtual ~NavigationDataSetWriterXML(); - virtual void Write (std::string path, mitk::NavigationDataSet::Pointer ); - virtual void Write (std::ostream* stream, mitk::NavigationDataSet::Pointer); + + using AbstractFileWriter::Write; + virtual void Write() override; protected: - virtual void StreamHeader (std::ostream* stream, mitk::NavigationDataSet::Pointer data); - virtual void StreamData (std::ostream* stream, mitk::NavigationDataSet::Pointer data); + NavigationDataSetWriterXML(const NavigationDataSetWriterXML& other); + + virtual mitk::NavigationDataSetWriterXML* Clone() const override; + + virtual void StreamHeader (std::ostream* stream, mitk::NavigationDataSet::ConstPointer data); + virtual void StreamData (std::ostream* stream, mitk::NavigationDataSet::ConstPointer data); virtual void StreamFooter (std::ostream* stream); }; } #endif // MITKNavigationDataSetWriterXML_H_HEADER_INCLUDED_ diff --git a/Modules/IGTBase/files.cmake b/Modules/IGTBase/files.cmake index 9acce817e6..4d4a6ac3f2 100644 --- a/Modules/IGTBase/files.cmake +++ b/Modules/IGTBase/files.cmake @@ -1,9 +1,19 @@ +file(GLOB_RECURSE H_FILES RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" "${CMAKE_CURRENT_SOURCE_DIR}/include/*") + set(CPP_FILES - mitkRealTimeClock.cpp + mitkRealTimeClock.cpp + mitkNavigationData.cpp + mitkNavigationDataSet.cpp + mitkStaticIGTHelperFunctions.cpp + mitkQuaternionAveraging.cpp + mitkIGTMimeTypes.cpp + mitkIGTException.cpp + mitkIGTIOException.cpp + mitkIGTHardwareException.cpp ) if(WIN32) set(CPP_FILES ${CPP_FILES} mitkWindowsRealTimeClock.cpp) else() set(CPP_FILES ${CPP_FILES} mitkLinuxRealTimeClock.cpp) endif(WIN32) diff --git a/Modules/RDF/mitkRdfNode.h b/Modules/IGTBase/include/mitkIGTException.h similarity index 55% copy from Modules/RDF/mitkRdfNode.h copy to Modules/IGTBase/include/mitkIGTException.h index 9ade7dee04..593cf4b3a2 100644 --- a/Modules/RDF/mitkRdfNode.h +++ b/Modules/IGTBase/include/mitkIGTException.h @@ -1,39 +1,35 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +#ifndef IGTEXCEPTION_H_INCLUDED +#define IGTEXCEPTION_H_INCLUDED -#ifndef MITKRDFNODE_H -#define MITKRDFNODE_H - -#include +#include +#include +#include "mitkExceptionMacro.h" namespace mitk { - -/** - * \ingroup MitkRDFModule - */ -class MITKRDF_EXPORT RdfNode +/**Documentation +* \brief An object of this class represents an exception of the MITK-IGT module. +* +* \ingroup IGT +*/ class MITKIGTBASE_EXPORT IGTException : public mitk::Exception { - -public: - - bool dummy(); - -}; - -} - + public: + mitkExceptionClassMacro(IGTException,mitk::Exception); + }; +} // namespace mitk #endif diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h b/Modules/IGTBase/include/mitkIGTHardwareException.h similarity index 51% copy from Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h copy to Modules/IGTBase/include/mitkIGTHardwareException.h index bf51ddd5f9..6b047eac58 100644 --- a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h +++ b/Modules/IGTBase/include/mitkIGTHardwareException.h @@ -1,35 +1,34 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +#ifndef IGTHARDWAREEXCEPTION_H_INCLUDED +#define IGTHARDWAREEXCEPTION_H_INCLUDED -#ifndef MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ -#define MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ - -#include +#include "mitkIGTException.h" +#include "mitkExceptionMacro.h" namespace mitk { - class MITKIGT_EXPORT NavigationDataSetWriterCSV + /**Documentation + * \brief An object of this class represents an exception of the MITK-IGT module which are releated to the hardware (e.g. connection problems, etc.). + * + * \ingroup IGT + */ class MITKIGTBASE_EXPORT IGTHardwareException : public mitk::IGTException { public: - NavigationDataSetWriterCSV(); - virtual~NavigationDataSetWriterCSV(); - - virtual void Write (std::string path, mitk::NavigationDataSet::Pointer ); - virtual void Write (std::ostream* stream, mitk::NavigationDataSet::Pointer); + mitkExceptionClassMacro(IGTHardwareException,mitk::IGTException); }; -} - -#endif // MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ +} // namespace mitk +#endif diff --git a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h b/Modules/IGTBase/include/mitkIGTIOException.h similarity index 51% rename from Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h rename to Modules/IGTBase/include/mitkIGTIOException.h index bf51ddd5f9..e2f8a176c4 100644 --- a/Modules/IGT/IO/mitkNavigationDataSetWriterCSV.h +++ b/Modules/IGTBase/include/mitkIGTIOException.h @@ -1,35 +1,34 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +#ifndef IGTIOEXCEPTION_H_INCLUDED +#define IGTIOEXCEPTION_H_INCLUDED -#ifndef MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ -#define MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ - -#include +#include +#include "mitkExceptionMacro.h" namespace mitk { - class MITKIGT_EXPORT NavigationDataSetWriterCSV + /**Documentation + * \brief An object of this class represents an exception of the MITK-IGT module which are releated to the input/output problems (e.g. reading writing files, etc.). + * + * \ingroup IGT + */ class MITKIGTBASE_EXPORT IGTIOException : public mitk::IGTException { public: - NavigationDataSetWriterCSV(); - virtual~NavigationDataSetWriterCSV(); - - virtual void Write (std::string path, mitk::NavigationDataSet::Pointer ); - virtual void Write (std::ostream* stream, mitk::NavigationDataSet::Pointer); + mitkExceptionClassMacro(IGTIOException,mitk::IGTException); }; -} - -#endif // MITKNavigationDataSetWriterCSV_H_HEADER_INCLUDED_ +} // namespace mitk +#endif diff --git a/Modules/RDF/mitkRdfNode.h b/Modules/IGTBase/include/mitkIGTMimeTypes.h similarity index 56% copy from Modules/RDF/mitkRdfNode.h copy to Modules/IGTBase/include/mitkIGTMimeTypes.h index 9ade7dee04..cef22a1141 100644 --- a/Modules/RDF/mitkRdfNode.h +++ b/Modules/IGTBase/include/mitkIGTMimeTypes.h @@ -1,39 +1,34 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ +#ifndef MITKIOMIMETYPE_H_HEADER_INCLUDED_ +#define MITKIOMIMETYPE_H_HEADER_INCLUDED_ -#ifndef MITKRDFNODE_H -#define MITKRDFNODE_H - -#include +#include +#include +#include namespace mitk { - -/** - * \ingroup MitkRDFModule - */ -class MITKRDF_EXPORT RdfNode -{ - -public: - - bool dummy(); - -}; - + class MITKIGTBASE_EXPORT IGTMimeTypes + { + public: + static CustomMimeType NAVIGATIONDATASETXML_MIMETYPE(); + static CustomMimeType NAVIGATIONDATASETCSV_MIMETYPE(); + }; } -#endif + +#endif // MITKIOMIMETYPE_H_HEADER_INCLUDED_ \ No newline at end of file diff --git a/Modules/IGTBase/mitkLinuxRealTimeClock.h b/Modules/IGTBase/include/mitkLinuxRealTimeClock.h similarity index 100% rename from Modules/IGTBase/mitkLinuxRealTimeClock.h rename to Modules/IGTBase/include/mitkLinuxRealTimeClock.h diff --git a/Modules/IGT/DataManagement/mitkNavigationData.h b/Modules/IGTBase/include/mitkNavigationData.h similarity index 97% rename from Modules/IGT/DataManagement/mitkNavigationData.h rename to Modules/IGTBase/include/mitkNavigationData.h index 801bd2a2c0..34044b3d9e 100644 --- a/Modules/IGT/DataManagement/mitkNavigationData.h +++ b/Modules/IGTBase/include/mitkNavigationData.h @@ -1,297 +1,297 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNAVIGATIONDATA_H_HEADER_INCLUDED_ #define MITKNAVIGATIONDATA_H_HEADER_INCLUDED_ #include -#include +#include #include #include namespace mitk { /**Documentation * \brief Navigation Data * * This class represents the data object that is passed through the MITK-IGT navigation filter * pipeline. It encapsulates position and orientation of a tracked tool/sensor. Additionally, * it contains a data structure that contains error/plausibility information * * It provides methods to work with the affine transformation represented by its orientation and position. * Additionally, it provides a constructor to construct a NavigationData object from an AffineTransform3D and * a getter to create an AffineTransform3D from a NavigationData object. * * \ingroup IGT */ - class MITKIGT_EXPORT NavigationData : public itk::DataObject + class MITKIGTBASE_EXPORT NavigationData : public itk::DataObject { public: mitkClassMacroItkParent(NavigationData, itk::DataObject); itkFactorylessNewMacro(Self); itkCloneMacro(Self); mitkNewMacro2Param(Self, mitk::AffineTransform3D::Pointer, const bool); mitkNewMacro1Param(Self, mitk::AffineTransform3D::Pointer); /** * \brief Type that holds the position part of the tracking data */ typedef mitk::Point3D PositionType; /** * \brief Type that holds the orientation part of the tracking data */ typedef mitk::Quaternion OrientationType; /** * \brief type that holds the error characterization of the position and orientation measurements */ typedef itk::Matrix CovarianceMatrixType; /** * \brief type that holds the time at which the data was recorded */ typedef double TimeStampType; /** * \brief sets the position of the NavigationData object */ itkSetMacro(Position, PositionType); /** * \brief returns position of the NavigationData object */ itkGetConstMacro(Position, PositionType); /** * \brief sets the orientation of the NavigationData object */ itkSetMacro(Orientation, OrientationType); /** * \brief returns the orientation of the NavigationData object */ itkGetConstMacro(Orientation, OrientationType); /** * \brief returns true if the object contains valid data */ virtual bool IsDataValid() const; /** * \brief sets the dataValid flag of the NavigationData object indicating if the object contains valid data */ itkSetMacro(DataValid, bool); /** * \brief sets the IGT timestamp of the NavigationData object */ itkSetMacro(IGTTimeStamp, TimeStampType); /** * \brief gets the IGT timestamp of the NavigationData object */ itkGetConstMacro(IGTTimeStamp, TimeStampType); /** * \brief sets the HasPosition flag of the NavigationData object */ itkSetMacro(HasPosition, bool); /** * \brief gets the HasPosition flag of the NavigationData object */ itkGetConstMacro(HasPosition, bool); /** * \brief sets the HasOrientation flag of the NavigationData object */ itkSetMacro(HasOrientation, bool); /** * \brief gets the HasOrientation flag of the NavigationData object */ itkGetConstMacro(HasOrientation, bool); /** * \brief sets the 6x6 Error Covariance Matrix of the NavigationData object */ itkSetMacro(CovErrorMatrix, CovarianceMatrixType); /** * \brief gets the 6x6 Error Covariance Matrix of the NavigationData object */ itkGetConstMacro(CovErrorMatrix, CovarianceMatrixType); /** * \brief set the name of the NavigationData object */ itkSetStringMacro(Name); /** * \brief returns the name of the NavigationData object */ itkGetStringMacro(Name); /** * \brief Graft the data and information from one NavigationData to another. * * Copies the content of data into this object. * This is a convenience method to setup a second NavigationData object with all the meta * information of another NavigationData object. * Note that this method is different than just using two * SmartPointers to the same NavigationData object since separate DataObjects are * still maintained. */ virtual void Graft(const DataObject *data) override; /** * \brief copy meta data of a NavigationData object * * copies all meta data from NavigationData data to this object */ virtual void CopyInformation(const DataObject* data) override; /** * \brief Prints the object information to the given stream os. * \param os The stream which is used to print the output. * \param indent Defines the indentation of the output. */ void PrintSelf(std::ostream& os, itk::Indent indent) const override; /** * Set the position part of m_CovErrorMatrix to I*error^2 * This means that all position variables are assumed to be independent */ void SetPositionAccuracy(mitk::ScalarType error); /** * Set the orientation part of m_CovErrorMatrix to I*error^2 * This means that all orientation variables are assumed to be independent */ void SetOrientationAccuracy(mitk::ScalarType error); /** * \brief Calculate AffineTransform3D from the transformation held by this NavigationData. * TODO: should throw an error if transformation is invalid. */ mitk::AffineTransform3D::Pointer GetAffineTransform3D() const; /** * \brief Calculate the RotationMatrix of this transformation. */ mitk::Matrix3D GetRotationMatrix() const; /** * \brief Transform by an affine transformation * * This method applies the affine transform given by self to a * given point, returning the transformed point. */ mitk::Point3D TransformPoint(const mitk::Point3D point) const; /** * Get inverse of the Transformation represented by this NavigationData. * @throws mitk::Exception in case the transformation is invalid (only case: quaternion is zero) */ mitk::NavigationData::Pointer GetInverse() const; /** Compose with another NavigationData * * This method composes self with another NavigationData of the * same dimension, modifying self to be the composition of self * and other. If the argument pre is true, then other is * precomposed with self; that is, the resulting transformation * consists of first applying other to the source, followed by * self. If pre is false or omitted, then other is post-composed * with self; that is the resulting transformation consists of * first applying self to the source, followed by other. */ void Compose(const mitk::NavigationData::Pointer n, const bool pre = false); protected: mitkCloneMacro(Self); NavigationData(); /* * Copy constructor internally used. */ NavigationData(const mitk::NavigationData& toCopy); /** * Creates a NavigationData object from an affineTransform3D. * Caution: NavigationData doesn't support spacing, only translation and rotation. If the affine * transform includes spacing it cannot be converted to a NavigationData and an exception is thrown. * @param checkForRotationMatrix if this is true, the rotation matrix coming from the affineTransform is checked * for being a rotation matrix. If it isn't, an exception is thrown. Disable this check by * setting checkForRotationMatrix to false. * * @throws mitkException if checkForRotationMatrix is true and a non rotation matrix was introduced by * AffineTransform. */ NavigationData(mitk::AffineTransform3D::Pointer affineTransform3D, const bool checkForRotationMatrix = true); virtual ~NavigationData(); /** * \brief holds the position part of the tracking data */ PositionType m_Position; /** * \brief holds the orientation part of the tracking data */ OrientationType m_Orientation; /** * \brief A 6x6 covariance matrix parameterizing the Gaussian error * distribution of the measured position and orientation. * * The hasPosition/hasOrientation fields define which entries * are valid. */ CovarianceMatrixType m_CovErrorMatrix; ///< holds the error characterization of the position and orientation /** * \brief defines if position part of m_CovErrorMatrix is valid */ bool m_HasPosition; /** * \brief defines if orientation part of m_CovErrorMatrix is valid */ bool m_HasOrientation; /** * \brief defines if the object contains valid values */ bool m_DataValid; /** * \brief contains the time at which the tracking data was recorded */ TimeStampType m_IGTTimeStamp; /** * \brief name of the navigation data */ std::string m_Name; private: void ResetCovarianceValidity(); // pre = false static mitk::NavigationData::Pointer getComposition(const mitk::NavigationData::Pointer nd1, const mitk::NavigationData::Pointer nd2); }; /** * @brief Equal A function comparing two navigation data objects for beeing equal in meta- and imagedata * * @ingroup MITKTestingAPI * * Following aspects are tested for equality: * - position * - orientation * - other members and flags of the class * * @param rightHandSide An NavigationData to be compared * @param leftHandSide An NavigationData to be compared * @param eps Tolarence for comparison. You can use mitk::eps in most cases. * @param verbose Flag indicating if the user wants detailed console output or not. * @return true, if all subsequent comparisons are true, false otherwise */ - MITKIGT_EXPORT bool Equal( const mitk::NavigationData& leftHandSide, const mitk::NavigationData& rightHandSide, ScalarType eps = mitk::eps, bool verbose = false ); + MITKIGTBASE_EXPORT bool Equal( const mitk::NavigationData& leftHandSide, const mitk::NavigationData& rightHandSide, ScalarType eps = mitk::eps, bool verbose = false ); } // namespace mitk #endif /* MITKNAVIGATIONDATA_H_HEADER_INCLUDED_ */ diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSet.h b/Modules/IGTBase/include/mitkNavigationDataSet.h similarity index 88% rename from Modules/IGT/DataManagement/mitkNavigationDataSet.h rename to Modules/IGTBase/include/mitkNavigationDataSet.h index cd9a6a5675..2c987eb012 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSet.h +++ b/Modules/IGTBase/include/mitkNavigationDataSet.h @@ -1,158 +1,171 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKNAVIGATIONDATASET_H_HEADER_INCLUDED_ #define MITKNAVIGATIONDATASET_H_HEADER_INCLUDED_ -#include +#include #include "mitkBaseData.h" #include "mitkNavigationData.h" namespace mitk { /** * \brief Data structure which stores streams of mitk::NavigationData for * multiple tools. * * Use mitk::NavigationDataRecorder to create these sets easily from pipelines. * Use mitk::NavigationDataPlayer to stream from these sets easily. * */ - class MITKIGT_EXPORT NavigationDataSet : public BaseData + class MITKIGTBASE_EXPORT NavigationDataSet : public BaseData { public: /** * \brief This iterator iterates over the distinct time steps in this set. * * It returns an array of the length equal to GetNumberOfTools(), containing a * mitk::NavigationData for each tool.. */ typedef std::vector< std::vector >::iterator NavigationDataSetIterator; + /** + * \brief This iterator iterates over the distinct time steps in this set. And is const. + * + * It returns an array of the length equal to GetNumberOfTools(), containing a + * mitk::NavigationData for each tool.. + */ + typedef std::vector< std::vector >::const_iterator NavigationDataSetConstIterator; + mitkClassMacro(NavigationDataSet, BaseData); mitkNewMacro1Param(Self, unsigned int); /** * \brief Add mitk::NavigationData of the given tool to the Set. * * @param navigationDatas vector of mitk::NavigationData objects to be added. Make sure that the size of the * vector equals the number of tools given in the constructor * @return true if object was be added to the set successfully, false otherwise */ bool AddNavigationDatas( std::vector navigationDatas ); /** * \brief Get mitk::NavigationData from the given tool at given index. * * @param toolIndex Index of the tool from which mitk::NavigationData should be returned. * @param index Index of the mitk::NavigationData object that should be returned. * @return mitk::NavigationData at the specified indices, 0 if there is no object at the indices. */ NavigationData::Pointer GetNavigationDataForIndex( unsigned int index, unsigned int toolIndex ) const; ///** //* \brief Get last mitk::Navigation object for given tool whose timestamp is less than the given timestamp. //* @param toolIndex Index of the tool from which mitk::NavigationData should be returned. //* @param timestamp Timestamp for selecting last object before. //* @return Last mitk::NavigationData with timestamp less than given timestamp, 0 if there is no adequate object. //*/ // Method not yet supported! //NavigationData::Pointer GetNavigationDataBeforeTimestamp( mitk::NavigationData::TimeStampType timestamp , unsigned int toolIndex ) const; /** * \brief Returns a vector that contains all tracking data for a given tool. * * This is a relatively expensive operation, as it requires the construction of a new vector. * * @param toolIndex Index of the tool for which the stream should be returned. * @return Returns a vector that contains all tracking data for a given tool. */ virtual std::vector< mitk::NavigationData::Pointer > GetDataStreamForTool(unsigned int toolIndex); /** * \brief Returns a vector that contains NavigationDatas for each tool for a given timestep. * * If GetNumberOFTools() equals four, then 4 NavigationDatas will be returned. * * @param index Index of the timeStep for which the datas should be returned. cannot be larger than mitk::NavigationDataSet::Size() * @return Returns a vector that contains all tracking data for a given tool. */ - virtual std::vector< mitk::NavigationData::Pointer > GetTimeStep(unsigned int index); + virtual std::vector< mitk::NavigationData::Pointer > GetTimeStep(unsigned int index) const; /** * \brief Returns the number of tools for which NavigationDatas are stored in this set. * * This is always equal to the number given in the constructor of this class. * * @return the number of tools for which NavigationDatas are stored in this set. */ - unsigned int GetNumberOfTools(); + unsigned int GetNumberOfTools() const; /** * \brief Returns the number of time steps stored in this NavigationDataSet. * * This is not the total number of Navigation Datas stored in this set, but the number stored for each tool. * i.e. the total number of NavigationDatas equals Size() * GetNumberOfTools(); * * @return Returns the number of time steps stored in this NavigationDataSet. */ - unsigned int Size(); + unsigned int Size() const; /** * \brief Returns an iterator pointing to the first TimeStep. * * @return Returns an iterator pointing to the first TimeStep. */ - virtual NavigationDataSetIterator Begin(); + virtual NavigationDataSetConstIterator Begin() const; /** * \brief Returns an iterator pointing behind to the last TimeStep. * * @return Returns an iterator pointing behind to the last TimeStep. */ - virtual NavigationDataSetIterator End(); + virtual NavigationDataSetConstIterator End() const; // virtual methods, that need to be implemented, but aren't reasonable for NavigationData virtual void SetRequestedRegionToLargestPossibleRegion( ) override; virtual bool RequestedRegionIsOutsideOfTheBufferedRegion( ) override; virtual bool VerifyRequestedRegion( ) override; virtual void SetRequestedRegion( const itk::DataObject *data ) override; + /** + * \brief This overrid is probably a little hacky. See Bug 19086. + */ + virtual bool IsEmpty() const override; + protected: /** * \brief Constructs set with fixed number of tools. * @param numTools How many tools are used with this mitk::NavigationDataSet. */ NavigationDataSet( unsigned int numTools ); virtual ~NavigationDataSet( ); /** * \brief Holds all the mitk::NavigationData objects managed by this class. * * The first dimension is the index of the navigation data, the second is the * tool to which this data belongs. i.e. the first dimension is usually the longer one. */ std::vector > m_NavigationDataVectors; /** * \brief The Number of Tools that this class is going to support. */ int m_NumberOfTools; }; } #endif // MITKNAVIGATIONDATASET_H_HEADER_INCLUDED_ diff --git a/Modules/IGTBase/include/mitkQuaternionAveraging.h b/Modules/IGTBase/include/mitkQuaternionAveraging.h new file mode 100644 index 0000000000..da8f5a4859 --- /dev/null +++ b/Modules/IGTBase/include/mitkQuaternionAveraging.h @@ -0,0 +1,56 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef QUATERNIONAVERAGING_H_HEADER_INCLUDED_ +#define QUATERNIONAVERAGING_H_HEADER_INCLUDED_ + +#include "MitkIGTBaseExports.h" +#include +#include +#include +#include +#include +#include + + +namespace mitk { + /**Documentation + * \brief This class offers methods to average quaternions. + * \ingroup IGT Base + */ + class MITKIGTBASE_EXPORT QuaternionAveraging : public itk::Object + { + public: + + mitkClassMacroItkParent(QuaternionAveraging, itk::Object); + itkNewMacro(Self); + + enum Mode + { + SimpleMean, //simple averaging over all components of the quaternion, only valid for small differences. + Slerp //more advanced algorithm for averaging (spherical linear interpolation), may also be used for huge differences + }; + + static mitk::Quaternion CalcAverage(const std::vector quaternions, Mode mode = SimpleMean); + + protected: + QuaternionAveraging(); + virtual ~QuaternionAveraging(); + + }; +} // Ende Namespace +#endif diff --git a/Modules/IGTBase/mitkRealTimeClock.h b/Modules/IGTBase/include/mitkRealTimeClock.h similarity index 100% rename from Modules/IGTBase/mitkRealTimeClock.h rename to Modules/IGTBase/include/mitkRealTimeClock.h diff --git a/Modules/IGTBase/include/mitkStaticIGTHelperFunctions.h b/Modules/IGTBase/include/mitkStaticIGTHelperFunctions.h new file mode 100644 index 0000000000..61546479af --- /dev/null +++ b/Modules/IGTBase/include/mitkStaticIGTHelperFunctions.h @@ -0,0 +1,45 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ +#include +#include +#include +#include "MitkIGTBaseExports.h" + +namespace mitk { + class MITKIGTBASE_EXPORT StaticIGTHelperFunctions + { + public: + /** Computes the angle in the plane perpendicular to the rotation axis of the two quaterions. + * Therefore, a vector is rotated with the difference of both rotations and the angle is computed. + * In some cases you might want to defice this vector e.g., if working with 5D tools. By default + * the vector is defined along the Z-axis which works for Aurora 5D tools. + * @return Returns the angle in degrees. + **/ + static double GetAngleBetweenTwoQuaterions(mitk::Quaternion a, mitk::Quaternion b, itk::Vector rotationVector); + + /** Computes the angle in the plane perpendicular to the rotation axis of the two quaterions. + * Therefore, a vector is rotated with the difference of both rotations and the angle is computed. + * In some cases you might want to defice this vector e.g., if working with 5D tools. By default + * the vector is defined along the Z-axis which works for Aurora 5D tools. + * @return Returns the angle in degrees. + **/ + static double GetAngleBetweenTwoQuaterions(mitk::Quaternion a, mitk::Quaternion b); + + /** Converts euler angles (in degrees) to a rotation matrix. */ + static itk::Matrix ConvertEulerAnglesToRotationMatrix(double alpha, double beta, double gamma); + + }; +} diff --git a/Modules/IGTBase/mitkWindowsRealTimeClock.h b/Modules/IGTBase/include/mitkWindowsRealTimeClock.h similarity index 100% rename from Modules/IGTBase/mitkWindowsRealTimeClock.h rename to Modules/IGTBase/include/mitkWindowsRealTimeClock.h diff --git a/Modules/RDF/mitkRdfNode.h b/Modules/IGTBase/src/mitkIGTException.cpp similarity index 71% copy from Modules/RDF/mitkRdfNode.h copy to Modules/IGTBase/src/mitkIGTException.cpp index 9ade7dee04..b2c4cefa26 100644 --- a/Modules/RDF/mitkRdfNode.h +++ b/Modules/IGTBase/src/mitkIGTException.cpp @@ -1,39 +1,17 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - -#ifndef MITKRDFNODE_H -#define MITKRDFNODE_H - -#include - -namespace mitk { - -/** - * \ingroup MitkRDFModule - */ -class MITKRDF_EXPORT RdfNode -{ - -public: - - bool dummy(); - -}; - -} - -#endif +#include "mitkIGTException.h" diff --git a/Modules/RDF/mitkRdfNode.h b/Modules/IGTBase/src/mitkIGTHardwareException.cpp similarity index 71% copy from Modules/RDF/mitkRdfNode.h copy to Modules/IGTBase/src/mitkIGTHardwareException.cpp index 9ade7dee04..84bf2a068b 100644 --- a/Modules/RDF/mitkRdfNode.h +++ b/Modules/IGTBase/src/mitkIGTHardwareException.cpp @@ -1,39 +1,17 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - -#ifndef MITKRDFNODE_H -#define MITKRDFNODE_H - -#include - -namespace mitk { - -/** - * \ingroup MitkRDFModule - */ -class MITKRDF_EXPORT RdfNode -{ - -public: - - bool dummy(); - -}; - -} - -#endif +#include "mitkIGTHardwareException.h" diff --git a/Modules/RDF/mitkRdfNode.h b/Modules/IGTBase/src/mitkIGTIOException.cpp similarity index 71% copy from Modules/RDF/mitkRdfNode.h copy to Modules/IGTBase/src/mitkIGTIOException.cpp index 9ade7dee04..833d81a9eb 100644 --- a/Modules/RDF/mitkRdfNode.h +++ b/Modules/IGTBase/src/mitkIGTIOException.cpp @@ -1,39 +1,17 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - -#ifndef MITKRDFNODE_H -#define MITKRDFNODE_H - -#include - -namespace mitk { - -/** - * \ingroup MitkRDFModule - */ -class MITKRDF_EXPORT RdfNode -{ - -public: - - bool dummy(); - -}; - -} - -#endif +#include "mitkIGTIOException.h" diff --git a/Modules/IGTBase/src/mitkIGTMimeTypes.cpp b/Modules/IGTBase/src/mitkIGTMimeTypes.cpp new file mode 100644 index 0000000000..f342ad8bea --- /dev/null +++ b/Modules/IGTBase/src/mitkIGTMimeTypes.cpp @@ -0,0 +1,38 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// MITK +#include "mitkIGTMimeTypes.h" + +mitk::CustomMimeType mitk::IGTMimeTypes::NAVIGATIONDATASETXML_MIMETYPE() +{ + mitk::CustomMimeType mimeType(IOMimeTypes::DEFAULT_BASE_NAME() + ".NavigationDataSet.xml"); + std::string category = "NavigationDataSet"; + mimeType.SetComment("NavigationDataSet (XML)"); + mimeType.SetCategory(category); + mimeType.AddExtension("xml"); + return mimeType; +} + +mitk::CustomMimeType mitk::IGTMimeTypes::NAVIGATIONDATASETCSV_MIMETYPE() +{ + mitk::CustomMimeType mimeType(IOMimeTypes::DEFAULT_BASE_NAME() + ".NavigationDataSet.csv"); + std::string category = "NavigationDataSet"; + mimeType.SetComment("NavigationDataSet (csv)"); + mimeType.SetCategory(category); + mimeType.AddExtension("csv"); + return mimeType; +} \ No newline at end of file diff --git a/Modules/IGTBase/mitkLinuxRealTimeClock.cpp b/Modules/IGTBase/src/mitkLinuxRealTimeClock.cpp similarity index 100% rename from Modules/IGTBase/mitkLinuxRealTimeClock.cpp rename to Modules/IGTBase/src/mitkLinuxRealTimeClock.cpp diff --git a/Modules/IGT/DataManagement/mitkNavigationData.cpp b/Modules/IGTBase/src/mitkNavigationData.cpp similarity index 100% rename from Modules/IGT/DataManagement/mitkNavigationData.cpp rename to Modules/IGTBase/src/mitkNavigationData.cpp diff --git a/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp b/Modules/IGTBase/src/mitkNavigationDataSet.cpp similarity index 90% rename from Modules/IGT/DataManagement/mitkNavigationDataSet.cpp rename to Modules/IGTBase/src/mitkNavigationDataSet.cpp index 0b48f14f09..10b596ba56 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp +++ b/Modules/IGTBase/src/mitkNavigationDataSet.cpp @@ -1,161 +1,167 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataSet.h" mitk::NavigationDataSet::NavigationDataSet( unsigned int numberOfTools ) : m_NavigationDataVectors(std::vector >()), m_NumberOfTools(numberOfTools) { } mitk::NavigationDataSet::~NavigationDataSet( ) { } bool mitk::NavigationDataSet::AddNavigationDatas( std::vector navigationDatas ) { // test if tool with given index exist if ( navigationDatas.size() != m_NumberOfTools ) { MITK_WARN("NavigationDataSet") << "Tried to add too many or too few navigation Datas to NavigationDataSet. " << m_NumberOfTools << " required, tried to add " << navigationDatas.size() << "."; return false; } // test for consistent timestamp if ( m_NavigationDataVectors.size() > 0) { for (int i = 0; i < navigationDatas.size(); i++) if (navigationDatas[i]->GetIGTTimeStamp() <= m_NavigationDataVectors.back()[i]->GetIGTTimeStamp()) { MITK_WARN("NavigationDataSet") << "IGTTimeStamp of new NavigationData should be newer than timestamp of last NavigationData."; return false; } } m_NavigationDataVectors.push_back(navigationDatas); return true; } mitk::NavigationData::Pointer mitk::NavigationDataSet::GetNavigationDataForIndex( unsigned int index, unsigned int toolIndex ) const { if ( index >= m_NavigationDataVectors.size() ) { MITK_WARN("NavigationDataSet") << "There is no NavigationData available at index " << index << "."; return nullptr; } if ( toolIndex >= m_NavigationDataVectors.at(index).size() ) { MITK_WARN("NavigationDataSet") << "There is NavigatitionData available at index " << index << " for tool " << toolIndex << "."; return nullptr; } return m_NavigationDataVectors.at(index).at(toolIndex); } // Method not yet supported, code below compiles but delivers wrong results //mitk::NavigationData::Pointer mitk::NavigationDataSet::GetNavigationDataBeforeTimestamp( // mitk::NavigationData::TimeStampType timestamp, unsigned int toolIndex) const //{ // if ( toolIndex >= m_NavigationDataVectors.size() ) // { // MITK_WARN("NavigationDataSet") << "There is no tool with index " << toolIndex << "."; // return NULL; // } // // std::vector::const_iterator it; // // // iterate through all NavigationData objects of the given tool index // // till the timestamp of the NavigationData is greater then the given timestamp // for (it = m_NavigationDataVectors.at(toolIndex).begin(); // it != m_NavigationDataVectors.at(toolIndex).end(); ++it) // { // if ( (*it)->GetIGTTimeStamp() > timestamp) { break; } // } // // // first element was greater than timestamp -> return null // if ( it == m_NavigationDataVectors.at(toolIndex).begin() ) // { // MITK_WARN("NavigationDataSet") << "No NavigationData was recorded before given timestamp."; // return NULL; // } // // // return last element smaller than the given timestamp // return *(it-1); //} std::vector< mitk::NavigationData::Pointer > mitk::NavigationDataSet::GetDataStreamForTool(unsigned int toolIndex) { if (toolIndex >= m_NumberOfTools ) { MITK_WARN("NavigationDataSet") << "Invalid toolIndex: " << m_NumberOfTools << " Tools known, requested index " << toolIndex << ""; return std::vector(); } std::vector< mitk::NavigationData::Pointer > result; for(int i = 0; i < m_NavigationDataVectors.size(); i++) result.push_back(m_NavigationDataVectors[i][toolIndex]); return result; } -std::vector< mitk::NavigationData::Pointer > mitk::NavigationDataSet::GetTimeStep(unsigned int index) +std::vector< mitk::NavigationData::Pointer > mitk::NavigationDataSet::GetTimeStep(unsigned int index) const { return m_NavigationDataVectors[index]; } -unsigned int mitk::NavigationDataSet::GetNumberOfTools() +unsigned int mitk::NavigationDataSet::GetNumberOfTools() const { return m_NumberOfTools; } -unsigned int mitk::NavigationDataSet::Size() +unsigned int mitk::NavigationDataSet::Size() const { return m_NavigationDataVectors.size(); } // ---> methods necessary for BaseData void mitk::NavigationDataSet::SetRequestedRegionToLargestPossibleRegion() { } bool mitk::NavigationDataSet::RequestedRegionIsOutsideOfTheBufferedRegion() { return false; } bool mitk::NavigationDataSet::VerifyRequestedRegion() { return true; } void mitk::NavigationDataSet::SetRequestedRegion(const DataObject * ) { } + +bool mitk::NavigationDataSet::IsEmpty() const +{ + return (Size() == 0); +} + // <--- methods necessary for BaseData // ---> methods for Iterators -mitk::NavigationDataSet::NavigationDataSetIterator mitk::NavigationDataSet::Begin() +mitk::NavigationDataSet::NavigationDataSetConstIterator mitk::NavigationDataSet::Begin() const { - return m_NavigationDataVectors.begin(); + return m_NavigationDataVectors.cbegin(); } -mitk::NavigationDataSet::NavigationDataSetIterator mitk::NavigationDataSet::End() +mitk::NavigationDataSet::NavigationDataSetConstIterator mitk::NavigationDataSet::End() const { - return m_NavigationDataVectors.end(); + return m_NavigationDataVectors.cend(); } diff --git a/Modules/IGTBase/src/mitkQuaternionAveraging.cpp b/Modules/IGTBase/src/mitkQuaternionAveraging.cpp new file mode 100644 index 0000000000..275920a45e --- /dev/null +++ b/Modules/IGTBase/src/mitkQuaternionAveraging.cpp @@ -0,0 +1,69 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkQuaternionAveraging.h" +//#include "bussvrmath/Quaternion.h" +//#include "SphereMean.h" + +mitk::QuaternionAveraging::QuaternionAveraging() +{ + + +} + +mitk::QuaternionAveraging::~QuaternionAveraging() +{ + +} + +mitk::Quaternion mitk::QuaternionAveraging::CalcAverage(const std::vector quaternions, Mode mode) +{ +mitk::Quaternion result; +switch (mode) + { + case SimpleMean: + for (int i=0; i +#include + +double mitk::StaticIGTHelperFunctions::GetAngleBetweenTwoQuaterions(mitk::Quaternion a, mitk::Quaternion b, itk::Vector rotationVector) + { + double returnValue; + + itk::Vector point; //caution 5D-Tools: correct verctor along the tool axis is needed + point[0] = rotationVector[0]; + point[1] = rotationVector[1]; + point[2] = rotationVector[2]; + + //Quaternions used for rotations should alway be normalized, so just to be safe: + a.normalize(); + b.normalize(); + + itk::Matrix rotMatrixA; + for(int i=0; i<3; i++) for(int j=0; j<3; j++) rotMatrixA[i][j] = a.rotation_matrix_transpose().transpose()[i][j]; + + itk::Matrix rotMatrixB; + for(int i=0; i<3; i++) for(int j=0; j<3; j++) rotMatrixB[i][j] = b.rotation_matrix_transpose().transpose()[i][j]; + + itk::Vector pt1 = rotMatrixA * point; + itk::Vector pt2 = rotMatrixB * point; + + returnValue = (pt1[0]*pt2[0]+pt1[1]*pt2[1]+pt1[2]*pt2[2]) / ( sqrt(pow(pt1[0],2.0)+pow(pt1[1],2.0)+pow(pt1[2],2.0)) * sqrt(pow(pt2[0],2.0)+pow(pt2[1],2.0)+pow(pt2[2],2.0))); + returnValue = acos(returnValue) * 57.296; //57,296 = 180/Pi ; conversion to degrees + + return returnValue; + } + +double mitk::StaticIGTHelperFunctions::GetAngleBetweenTwoQuaterions(mitk::Quaternion a, mitk::Quaternion b) +{ + itk::Vector rotationVector = itk::Vector(); + rotationVector[0] = 0; + rotationVector[1] = 0; + rotationVector[2] = 1000; + return GetAngleBetweenTwoQuaterions(a,b,rotationVector); +} + +itk::Matrix mitk::StaticIGTHelperFunctions::ConvertEulerAnglesToRotationMatrix(double alpha, double beta, double gamma) +{ + double PI = 3.141592653589793; + alpha = alpha * PI / 180; + beta = beta * PI / 180; + gamma = gamma * PI / 180; + + //convert angles to matrix: + itk::Matrix matrix; + + /* x-Konvention (Z, X, Z) + matrix[0][0] = cos(alpha) * cos(gamma) - sin(alpha) * cos(beta) * sin(gamma); + matrix[0][1] = -cos(alpha) * sin(gamma)- sin(alpha) * cos(beta) * cos(gamma); + matrix[0][2] = sin(alpha) * sin(beta); + + matrix[1][0] = sin(alpha) * cos(gamma) + cos(alpha) * cos(beta) * sin(gamma); + matrix[1][1] = cos(alpha) * cos(beta) * cos(gamma) - sin(alpha) * sin(gamma); + matrix[1][2] = -cos(alpha) * sin(beta); + + matrix[2][0] = sin(beta) * sin(gamma); + matrix[2][1] = sin(beta) * cos(gamma); + matrix[2][2] = cos(beta); + */ + + //Luftfahrtnorm (DIN 9300) (Yaw-Pitch-Roll, Z, Y, X) + matrix[0][0] = cos(beta) * cos(alpha); + matrix[0][1] = cos(beta) * sin(alpha); + matrix[0][2] = -sin(beta); + + matrix[1][0] = sin(gamma) * sin(beta) * cos(alpha) - cos(gamma) * sin(alpha) ; + matrix[1][1] = sin(gamma) * sin(beta) * sin(alpha) + cos(gamma) * cos(alpha); + matrix[1][2] = sin(gamma) * cos(beta); + + matrix[2][0] = cos(gamma) * sin(beta) * cos(alpha) + sin(gamma) * sin(alpha); + matrix[2][1] = cos(gamma) * sin(beta) * sin(alpha) - sin(gamma) * cos(alpha); + matrix[2][2] = cos(gamma) * cos(beta); + + return matrix; +} diff --git a/Modules/IGTBase/mitkWindowsRealTimeClock.cpp b/Modules/IGTBase/src/mitkWindowsRealTimeClock.cpp similarity index 100% rename from Modules/IGTBase/mitkWindowsRealTimeClock.cpp rename to Modules/IGTBase/src/mitkWindowsRealTimeClock.cpp diff --git a/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp index 8c83ef105a..2784e355fd 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTLoggerWidget.cpp @@ -1,309 +1,309 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTLoggerWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include -#include +#include //itk headers #include //qt headers #include #include #include QmitkIGTLoggerWidget::QmitkIGTLoggerWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_Recorder(NULL), m_RecordingActivated(false) { m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); //set output file this->SetOutputFileName(); //update milliseconds and samples this->SetDefaultRecordingSettings(); } QmitkIGTLoggerWidget::~QmitkIGTLoggerWidget() { m_RecordingTimer->stop(); m_Recorder = NULL; m_RecordingTimer = NULL; } void QmitkIGTLoggerWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLoggerWidgetControls; m_Controls->setupUi(parent); m_RecordingTimer = new QTimer(this); } } void QmitkIGTLoggerWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_pbLoadDir), SIGNAL(clicked()), this, SLOT(OnChangePressed()) ); connect( (QObject*)(m_Controls->m_pbStartRecording), SIGNAL(clicked(bool)), this, SLOT(OnStartRecording(bool)) ); connect( m_RecordingTimer, SIGNAL(timeout()), this, SLOT(OnRecording()) ); connect( (QObject*)(m_Controls->m_leRecordingValue), SIGNAL(editingFinished()), this, SLOT(UpdateRecordingTime()) ); connect( (QObject*)(m_Controls->m_cbRecordingType), SIGNAL(activated(int)), this, SLOT(UpdateRecordingTime()) ); connect( (QObject*)(m_Controls->m_leOutputFile), SIGNAL(editingFinished()), this, SLOT(UpdateOutputFileName()) ); } } void QmitkIGTLoggerWidget::SetDataStorage(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; } void QmitkIGTLoggerWidget::OnStartRecording(bool recording) { if (m_Recorder.IsNull()) { QMessageBox::warning(NULL, "Warning", QString("Please start tracking before recording!")); return; } if (m_CmpFilename.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Please specify filename!")); return; } if(recording) { if (!m_RecordingActivated) { //m_Recorder->SetFileName(m_CmpFilename.toStdString()); try { /*start the recording mechanism */ m_Recorder->StartRecording(); m_RecordingTimer->start(50); //now every update of the recorder stores one line into the file for each added NavigationData mitk::StatusBar::GetInstance()->DisplayText("Recording tracking data now"); // Display recording message for 75ms in status bar emit SignalRecordingStarted(); } catch (std::exception& e) { QMessageBox::warning(NULL, "IGT-Tracking Logger: Error", QString("Error while recording tracking data: %1").arg(e.what())); mitk::StatusBar::GetInstance()->DisplayText(""); // Display recording message for 75ms in status bar } m_Controls->m_pbStartRecording->setText("Stop recording"); m_Controls->m_leRecordingValue->setEnabled(false); m_Controls->m_cbRecordingType->setEnabled(false); m_RecordingActivated = true; if(m_Controls->m_cbRecordingType->currentIndex()==0) { bool success = false; QString str_ms = m_Controls->m_leRecordingValue->text(); int int_ms = str_ms.toInt(&success); if (success) QTimer::singleShot(int_ms, this, SLOT(StopRecording())); } } else { this->StopRecording(); } } else { this->StopRecording(); m_Controls->m_pbStartRecording->setChecked(false); } } void QmitkIGTLoggerWidget::StopRecording() { m_RecordingTimer->stop(); m_Recorder->StopRecording(); mitk::StatusBar::GetInstance()->DisplayText("Recording STOPPED", 2000); // Display message for 2s in status bar m_Controls->m_pbStartRecording->setText("Start recording"); m_Controls->m_pbStartRecording->setChecked(false); m_Controls->m_leRecordingValue->setEnabled(true); m_Controls->m_cbRecordingType->setEnabled(true); m_RecordingActivated = false; try { // write NavigationDataSet on StopRecording - mitk::NavigationDataSetWriterXML().Write(m_CmpFilename.toStdString(), m_Recorder->GetNavigationDataSet()); + mitk::IOUtil::SaveBaseData(m_Recorder->GetNavigationDataSet(), m_CmpFilename.toStdString()); } catch(const std::exception &e) { // TODO: catch must be adapted when new file writer are merged to master QMessageBox::warning(NULL, "IGT-Tracking Logger: Error", QString("Error while writing tracking data: %1").arg(e.what())); MITK_WARN << "File could not be written."; } emit SignalRecordingStopped(); } void QmitkIGTLoggerWidget::OnRecording() { static unsigned int sampleCounter = 0; unsigned int int_samples = m_Samples.toInt(); if(sampleCounter >= int_samples) { this->StopRecording(); sampleCounter=0; return; } m_Recorder->Update(); if (m_Controls->m_cbRecordingType->currentIndex()==1) sampleCounter++; } void QmitkIGTLoggerWidget::OnChangePressed() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = QFileDialog::getSaveFileName( QApplication::activeWindow() , "Save tracking data", "IGT_Tracking_Data.xml", "XML files (*.xml)" ); if (m_CmpFilename.isEmpty())//if something went wrong or user pressed cancel in the save dialog { m_CmpFilename=oldName; } m_Controls->m_leOutputFile->setText(m_CmpFilename); } void QmitkIGTLoggerWidget::UpdateOutputFileName() { QString oldName = m_CmpFilename; m_CmpFilename.clear(); m_CmpFilename = m_Controls->m_leOutputFile->text(); if (m_CmpFilename.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Please enter valid path! Using previous path again.")); m_CmpFilename=oldName; m_Controls->m_leOutputFile->setText(m_CmpFilename); } } void QmitkIGTLoggerWidget::SetRecorder( mitk::NavigationDataRecorder::Pointer recorder ) { m_Recorder = recorder; } void QmitkIGTLoggerWidget::UpdateRecordingTime() { // milliseconds selected in the combobox if (m_Controls->m_cbRecordingType->currentIndex()==0) { m_MilliSeconds = m_Controls->m_leRecordingValue->text(); if(m_MilliSeconds.compare("infinite")==0) { this->SetDefaultRecordingSettings(); } bool success = false; m_MilliSeconds.toInt(&success); if (!success) { QMessageBox::warning(NULL, "Warning", QString("Please enter a number!")); this->SetDefaultRecordingSettings(); return; } } else if(m_Controls->m_cbRecordingType->currentIndex()==1) // #samples selected in the combobox { m_Samples = m_Controls->m_leRecordingValue->text(); if(m_Samples.compare("infinite")==0) { this->SetDefaultRecordingSettings(); } bool success = false; m_Samples.toInt(&success); if (!success) { QMessageBox::warning(NULL, "Warning", QString("Please enter a number!")); this->SetDefaultRecordingSettings(); return; } } else if (m_Controls->m_cbRecordingType->currentIndex()==2)// infinite selected in the combobox { // U+221E unicode symbole for infinite QString infinite("infinite"); m_Controls->m_leRecordingValue->setText(infinite); } // m_Controls->m_leSamples->setText(QString::number(samples)); } void QmitkIGTLoggerWidget::SetDefaultRecordingSettings() { m_Controls->m_leRecordingValue->setText("2000"); m_Controls->m_cbRecordingType->setCurrentIndex(0); m_Samples="100"; m_MilliSeconds="2000"; } void QmitkIGTLoggerWidget::SetOutputFileName() { std::string tmpDir = itksys::SystemTools::GetCurrentWorkingDirectory(); QString dir = QString(tmpDir.c_str()); QString filename = "IGT_Tracking_Data.xml"; m_CmpFilename.append(dir); if(dir.isEmpty()) { QMessageBox::warning(NULL, "Warning", QString("Could not load current working directory")); return; } if(dir.endsWith("/")||dir.endsWith("\\")) { m_CmpFilename.append(filename); } else { m_CmpFilename.append("/"); m_CmpFilename.append(filename); } m_Controls->m_leOutputFile->setText(m_CmpFilename); } diff --git a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp index b0b0d49bca..5f8fbf1aa1 100644 --- a/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkIGTPlayerWidget.cpp @@ -1,575 +1,573 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTPlayerWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include #include -#include "mitkNavigationDataReaderXML.h" +#include //qt headers #include #include #include QmitkIGTPlayerWidget::QmitkIGTPlayerWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_RealTimePlayer(mitk::NavigationDataPlayer::New()), m_SequentialPlayer(mitk::NavigationDataSequentialPlayer::New()), m_StartTime(-1.0), m_CurrentSequentialPointNumber(0), m_Controls(new Ui::QmitkIGTPlayerWidgetControls) { m_Controls->setupUi(this); m_PlayingTimer = new QTimer(this); // initialize update timer CreateConnections(); m_Controls->samplePositionHorizontalSlider->setVisible(false); this->ResetLCDNumbers(); // reset lcd numbers at start } QmitkIGTPlayerWidget::~QmitkIGTPlayerWidget() { m_PlayingTimer->stop(); delete m_Controls; } void QmitkIGTPlayerWidget::CreateConnections() { connect( (QObject*)(m_Controls->playPushButton), SIGNAL(clicked(bool)), this, SLOT(OnPlayButtonClicked(bool)) ); // play button connect( (QObject*)(m_PlayingTimer), SIGNAL(timeout()), this, SLOT(OnPlaying()) ); // update timer connect( (QObject*) (m_Controls->beginPushButton), SIGNAL(clicked()), this, SLOT(OnGoToBegin()) ); // reset player and go to begin connect( (QObject*) (m_Controls->stopPushButton), SIGNAL(clicked()), this, SLOT(OnGoToEnd()) ); // reset player // pass this widgets protected combobox signal to public signal connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); // pass this widgets protected checkbox signal to public signal connect( m_Controls->splineModeCheckBox, SIGNAL(toggled(bool)), this, SIGNAL(SignalSplineModeToggled(bool)) ); //connect( m_Controls->sequencialModeCheckBox, SIGNAL(toggled(bool)), this, SLOT(OnSequencialModeToggled(bool)) ); connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderPressed()), this, SLOT(OnSliderPressed()) ); connect( m_Controls->samplePositionHorizontalSlider, SIGNAL(sliderReleased()), this, SLOT(OnSliderReleased()) ); connect( m_Controls->m_OpenFileButton, SIGNAL(clicked()), this, SLOT(OnOpenFileButtonPressed()) ); } bool QmitkIGTPlayerWidget::IsTrajectoryInSplineMode() { return m_Controls->splineModeCheckBox->isChecked(); } bool QmitkIGTPlayerWidget::CheckInputFileValid() { QFile file(m_CmpFilename); // check if file exists if(!file.exists()) { QMessageBox::warning(NULL, "IGTPlayer: Error", "No valid input file was loaded. Please load input file first!"); return false; } return true; } unsigned int QmitkIGTPlayerWidget::GetNumberOfTools() { unsigned int result = 0; if(this->GetCurrentPlaybackMode() == RealTimeMode) { if(m_RealTimePlayer.IsNotNull()) result = m_RealTimePlayer->GetNumberOfOutputs(); } else if(this->GetCurrentPlaybackMode() == SequentialMode) { if(m_SequentialPlayer.IsNotNull()) result = m_SequentialPlayer->GetNumberOfOutputs(); } // at the moment this works only if player is initialized return result; } void QmitkIGTPlayerWidget::SetUpdateRate(unsigned int msecs) { m_PlayingTimer->setInterval((int) msecs); // set update timer update rate } void QmitkIGTPlayerWidget::OnPlayButtonClicked(bool checked) { if ( ! checked ) { if ( this->GetCurrentPlaybackMode() == RealTimeMode ) { m_RealTimePlayer->StopPlaying(); } else if ( this->GetCurrentPlaybackMode() == SequentialMode ) { // m_SequentialPlayer-> } } if(CheckInputFileValid()) // no playing possible without valid input file { switch ( this->GetCurrentPlaybackMode() ) { case RealTimeMode: { break; } case SequentialMode: { break; } } PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; if(checked) // play { if( (isRealTimeMode && m_RealTimePlayer.IsNull()) || (isSequentialMode && m_SequentialPlayer.IsNull())) // start play { mitk::NavigationDataSet::Pointer navigationDataSet; try { - mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); - navigationDataSet = reader->Read(m_CmpFilename.toStdString()); + navigationDataSet = dynamic_cast (mitk::IOUtil::LoadBaseData(m_CmpFilename.toStdString()).GetPointer()); } catch(mitk::IGTException) { std::string errormessage = "Error during start playing. Invalid or wrong file?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_Controls->playPushButton->setChecked(false); m_RealTimePlayer = NULL; return; } if(isRealTimeMode) { m_RealTimePlayer = mitk::NavigationDataPlayer::New(); m_RealTimePlayer->SetNavigationDataSet(navigationDataSet); try { m_RealTimePlayer->StartPlaying(); } catch(mitk::IGTException) { std::string errormessage = "Error during start playing. Invalid or wrong file?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_Controls->playPushButton->setChecked(false); m_RealTimePlayer = NULL; return; } } else if(isSequentialMode) { m_SequentialPlayer = mitk::NavigationDataSequentialPlayer::New(); try { m_SequentialPlayer->SetNavigationDataSet(navigationDataSet); } catch(mitk::IGTException) { std::string errormessage = "Error during start playing. Invalid or wrong file type?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_Controls->playPushButton->setChecked(false); m_RealTimePlayer = NULL; return; } m_Controls->samplePositionHorizontalSlider->setMinimum(0); m_Controls->samplePositionHorizontalSlider->setMaximum(m_SequentialPlayer->GetNumberOfSnapshots()); m_Controls->samplePositionHorizontalSlider->setEnabled(true); } m_PlayingTimer->start(100); emit SignalPlayingStarted(); } else // resume play { if(isRealTimeMode) m_RealTimePlayer->Resume(); m_PlayingTimer->start(100); emit SignalPlayingResumed(); } } else // pause { if(isRealTimeMode) m_RealTimePlayer->Pause(); m_PlayingTimer->stop(); emit SignalPlayingPaused(); } } else { m_Controls->playPushButton->setChecked(false); // uncheck play button if file unvalid } } QmitkIGTPlayerWidget::PlaybackMode QmitkIGTPlayerWidget::GetCurrentPlaybackMode() { /*if(m_Controls->sequencialModeCheckBox->isChecked()) return SequentialMode; else*/ return RealTimeMode; } QTimer* QmitkIGTPlayerWidget::GetPlayingTimer() { return m_PlayingTimer; } void QmitkIGTPlayerWidget::OnStopPlaying() { this->StopPlaying(); } void QmitkIGTPlayerWidget::StopPlaying() { m_PlayingTimer->stop(); emit SignalPlayingStopped(); if(m_RealTimePlayer.IsNotNull()) m_RealTimePlayer->StopPlaying(); m_StartTime = -1; // set starttime back m_CurrentSequentialPointNumber = 0; m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber); m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); this->ResetLCDNumbers(); m_Controls->playPushButton->setChecked(false); // set play button unchecked } void QmitkIGTPlayerWidget::OnPlaying() { switch ( this->GetCurrentPlaybackMode() ) { case RealTimeMode: { if ( m_RealTimePlayer.IsNull() ) { return; } if ( m_StartTime < 0 ) { // get playback start time m_StartTime = m_RealTimePlayer->GetOutput()->GetTimeStamp(); } if( ! m_RealTimePlayer->IsAtEnd() ) { m_RealTimePlayer->Update(); // update player int msc = (int) (m_RealTimePlayer->GetOutput()->GetTimeStamp() - m_StartTime); // calculation for playing time display int ms = msc % 1000; msc = (msc - ms) / 1000; int s = msc % 60; int min = (msc-s) / 60; // set lcd numbers m_Controls->msecLCDNumber->display(ms); m_Controls->secLCDNumber->display(s); m_Controls->minLCDNumber->display(min); emit SignalPlayerUpdated(); // player successfully updated } else { this->StopPlaying(); // if player is at EOF } break; } case SequentialMode: { if ( m_SequentialPlayer.IsNull() ) { return; } if ( m_CurrentSequentialPointNumber < m_SequentialPlayer->GetNumberOfSnapshots() ) { m_SequentialPlayer->Update(); // update sequential player m_Controls->samplePositionHorizontalSlider->setSliderPosition(m_CurrentSequentialPointNumber++); // refresh slider position m_Controls->sampleLCDNumber->display(static_cast(m_CurrentSequentialPointNumber)); //for debugging purposes //std::cout << "Sample: " << m_CurrentSequentialPointNumber << " X: " << m_SequentialPlayer->GetOutput()->GetPosition()[0] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[1] << " Y: " << m_SequentialPlayer->GetOutput()->GetPosition()[2] << std::endl; emit SignalPlayerUpdated(); // player successfully updated } else { this->StopPlaying(); // if player is at EOF } break; } } } const std::vector QmitkIGTPlayerWidget::GetNavigationDatas() { std::vector navDatas; if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_RealTimePlayer->GetOutput(i)); // push back current navigation data for each tool } } else if(this->GetCurrentPlaybackMode() == SequentialMode && m_SequentialPlayer.IsNotNull()) { for(unsigned int i=0; i < m_SequentialPlayer->GetNumberOfOutputs(); ++i) { navDatas.push_back(m_SequentialPlayer->GetOutput(i)); // push back current navigation data for each tool } } return navDatas; } const mitk::PointSet::Pointer QmitkIGTPlayerWidget::GetNavigationDatasPointSet() { mitk::PointSet::Pointer result = mitk::PointSet::New(); mitk::PointSet::PointType pointType; PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { int numberOfOutputs = 0; if(isRealTimeMode) numberOfOutputs = m_RealTimePlayer->GetNumberOfOutputs(); else if(isSequentialMode) numberOfOutputs = m_SequentialPlayer->GetNumberOfOutputs(); for(unsigned int i=0; i < m_RealTimePlayer->GetNumberOfOutputs(); ++i) { mitk::NavigationData::PositionType position; if(isRealTimeMode) position = m_RealTimePlayer->GetOutput(i)->GetPosition(); else if(isSequentialMode) position = m_SequentialPlayer->GetOutput(i)->GetPosition(); pointType[0] = position[0]; pointType[1] = position[1]; pointType[2] = position[2]; result->InsertPoint(i,pointType); // insert current ND as Pointtype in PointSet for return } } return result; } const mitk::PointSet::PointType QmitkIGTPlayerWidget::GetNavigationDataPoint(unsigned int index) { if( index > this->GetNumberOfTools() || index < 0 ) throw std::out_of_range("Tool Index out of range!"); PlaybackMode currentMode = this->GetCurrentPlaybackMode(); bool isRealTimeMode = currentMode == RealTimeMode; bool isSequentialMode = currentMode == SequentialMode; // create return PointType from current ND for tool index mitk::PointSet::PointType result; if( (isRealTimeMode && m_RealTimePlayer.IsNotNull()) || (isSequentialMode && m_SequentialPlayer.IsNotNull())) { mitk::NavigationData::PositionType position; if(isRealTimeMode) position = m_RealTimePlayer->GetOutput(index)->GetPosition(); else if(isSequentialMode) position = m_SequentialPlayer->GetOutput(index)->GetPosition(); result[0] = position[0]; result[1] = position[1]; result[2] = position[2]; } return result; } /*void QmitkIGTPlayerWidget::SetRealTimePlayer( mitk::NavigationDataPlayer::Pointer player ) { if(player.IsNotNull()) m_RealTimePlayer = player; } void QmitkIGTPlayerWidget::SetSequentialPlayer( mitk::NavigationDataSequentialPlayer::Pointer player ) { if(player.IsNotNull()) m_SequentialPlayer = player; }*/ void QmitkIGTPlayerWidget::OnOpenFileButtonPressed() { QString filename = QFileDialog::getOpenFileName(this, "Load tracking data", QDir::currentPath(),"XML files (*.xml)"); QFile file(filename); // if something went wrong or user pressed cancel in the save dialog if ( filename.isEmpty() || ! file.exists() ) { QMessageBox::warning(NULL, "Warning", QString("Please enter valid path. Using previous path again.")); return; } m_CmpFilename = filename; this->OnGoToEnd(); /// stops playing and resets lcd numbers m_Controls->m_ActiveFileLabel->setText(m_CmpFilename); emit SignalInputFileChanged(); - mitk::NavigationDataReaderInterface::Pointer navigationDataReader = mitk::NavigationDataReaderXML::New().GetPointer(); - mitk::NavigationDataSet::Pointer navigationDataSet = navigationDataReader->Read(m_CmpFilename.toStdString()); + mitk::NavigationDataSet::Pointer navigationDataSet = dynamic_cast (mitk::IOUtil::LoadBaseData(m_CmpFilename.toStdString()).GetPointer()); m_RealTimePlayer->SetNavigationDataSet(navigationDataSet); m_SequentialPlayer->SetNavigationDataSet(navigationDataSet); m_Controls->m_PlayerControlsGroupBox->setEnabled(true); } void QmitkIGTPlayerWidget::OnGoToEnd() { this->StopPlaying(); // reset lcd numbers this->ResetLCDNumbers(); } void QmitkIGTPlayerWidget::OnGoToBegin() { // stop player manual so no PlayingStopped() m_PlayingTimer->stop(); if(this->GetCurrentPlaybackMode() == RealTimeMode && m_RealTimePlayer.IsNotNull()) { m_RealTimePlayer->StopPlaying(); m_RealTimePlayer = NULL; // set player to NULL so it can be initialized again if playback is called afterwards } m_StartTime = -1; // set starttime back //reset view elements m_Controls->playPushButton->setChecked(false); this->ResetLCDNumbers(); } void QmitkIGTPlayerWidget::ResetLCDNumbers() { m_Controls->minLCDNumber->display(QString("00")); m_Controls->secLCDNumber->display(QString("00")); m_Controls->msecLCDNumber->display(QString("000")); } void QmitkIGTPlayerWidget::SetTrajectoryNames(const QStringList toolNames) { QComboBox* cBox = m_Controls->trajectorySelectComboBox; if(cBox->count() > 0) this->ClearTrajectorySelectCombobox(); // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); if(!toolNames.isEmpty()) m_Controls->trajectorySelectComboBox->insertItems(0, toolNames); // adding current tool names to combobox // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } int QmitkIGTPlayerWidget::GetResolution() { return m_Controls->resolutionSpinBox->value(); // return currently selected trajectory resolution } void QmitkIGTPlayerWidget::ClearTrajectorySelectCombobox() { // before making changed to QComboBox it is recommended to disconnet it's SIGNALS and SLOTS disconnect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); m_Controls->trajectorySelectComboBox->clear(); // reconnect after performed changes connect( (QObject*) (m_Controls->trajectorySelectComboBox), SIGNAL(currentIndexChanged(int)), this, SIGNAL(SignalCurrentTrajectoryChanged(int)) ); } void QmitkIGTPlayerWidget::OnSequencialModeToggled(bool toggled) { this->StopPlaying(); // stop playing when mode is changed if(toggled) { m_Controls->samplePositionHorizontalSlider->setEnabled(true); // enable slider if sequential mode } else if(!toggled) { m_Controls->samplePositionHorizontalSlider->setSliderPosition(0); // set back and disable slider m_Controls->samplePositionHorizontalSlider->setDisabled(true); } } void QmitkIGTPlayerWidget::OnSliderReleased() { int currentSliderValue = m_Controls->samplePositionHorizontalSlider->value(); // current slider value selected through user movement if(currentSliderValue > m_CurrentSequentialPointNumber) // at the moment only forward scrolling is possible { unsigned int snapshotNumber = currentSliderValue; m_SequentialPlayer->GoToSnapshot(snapshotNumber); // move player to selected snapshot m_CurrentSequentialPointNumber = currentSliderValue; m_Controls->sampleLCDNumber->display(currentSliderValue); // update lcdnumber in widget } else m_Controls->samplePositionHorizontalSlider->setValue(m_CurrentSequentialPointNumber); } void QmitkIGTPlayerWidget::OnSliderPressed() { if(m_Controls->playPushButton->isChecked()) // check if widget is playing m_Controls->playPushButton->click(); // perform click to pause the play } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp index 31465aa432..9ea0da3db6 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.cpp @@ -1,336 +1,341 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNavigationToolCreationWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //poco headers #include // vtk #include #include const std::string QmitkNavigationToolCreationWidget::VIEW_ID = "org.mitk.views.navigationtoolcreationwizardwidget"; QmitkNavigationToolCreationWidget::QmitkNavigationToolCreationWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = NULL; m_AdvancedWidget = new QmitkNavigationToolCreationAdvancedWidget(this); m_AdvancedWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); m_AdvancedWidget->setWindowTitle("Tool Creation Advanced Options"); m_AdvancedWidget->setModal(false); CreateQtPartControl(this); CreateConnections(); } QmitkNavigationToolCreationWidget::~QmitkNavigationToolCreationWidget() { m_Controls->m_CalibrationLandmarksList->SetPointSetNode(NULL); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(NULL); delete m_AdvancedWidget; } void QmitkNavigationToolCreationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolCreationWidgetControls; m_Controls->setupUi(parent); } } void QmitkNavigationToolCreationWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_cancel), SIGNAL(clicked()), this, SLOT(OnCancel()) ); connect( (QObject*)(m_Controls->m_finished), SIGNAL(clicked()), this, SLOT(OnFinished()) ); connect( (QObject*)(m_Controls->m_LoadSurface), SIGNAL(clicked()), this, SLOT(OnLoadSurface()) ); connect( (QObject*)(m_Controls->m_LoadCalibrationFile), SIGNAL(clicked()), this, SLOT(OnLoadCalibrationFile()) ); connect( (QObject*)(m_Controls->m_ShowAdvancedOptionsPB), SIGNAL(toggled(bool)), this, SLOT(OnShowAdvancedOptions(bool)) ); connect( (QObject*)(m_AdvancedWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessDialogCloseRequest()) ); connect( (QObject*)(m_AdvancedWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation()) ); connect( m_Controls->m_Surface_Use_Other, SIGNAL(toggled(bool)), this, SLOT(OnSurfaceUseOtherToggled(bool))); } } void QmitkNavigationToolCreationWidget::Initialize(mitk::DataStorage* dataStorage, const std::string& supposedIdentifier, const std::string& supposedName) { m_DataStorage = dataStorage; //initialize UI components m_Controls->m_SurfaceChooser->SetDataStorage(m_DataStorage); m_Controls->m_SurfaceChooser->SetAutoSelectNewItems(true); m_Controls->m_SurfaceChooser->SetPredicate(mitk::NodePredicateDataType::New("Surface")); //set default data m_Controls->m_ToolNameEdit->setText(supposedName.c_str()); m_Controls->m_CalibrationFileName->setText("none"); m_Controls->m_Surface_Use_Sphere->setChecked(true); m_AdvancedWidget->SetDataStorage(m_DataStorage); m_Controls->m_IdentifierEdit->setText(supposedIdentifier.c_str()); this->InitializeUIToolLandmarkLists(); m_Controls->m_CalibrationLandmarksList->EnableEditButton(false); m_Controls->m_RegistrationLandmarksList->EnableEditButton(false); } void QmitkNavigationToolCreationWidget::SetTrackingDeviceType(mitk::TrackingDeviceType type, bool changeable) { switch(type) { case mitk::NDIAurora: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break; case mitk::NDIPolaris: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break; case mitk::ClaronMicron: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break; case mitk::NPOptitrack: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(3);break; case mitk::VirtualTracker: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(4);break; + case mitk::OpenIGTLinkTrackingDeviceConnection: + m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(5);break; default: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(4); } m_Controls->m_TrackingDeviceTypeChooser->setEnabled(changeable); } mitk::NavigationTool::Pointer QmitkNavigationToolCreationWidget::GetCreatedTool() { return m_CreatedTool; } //################################################################################## //############################## slots ############################ //################################################################################## void QmitkNavigationToolCreationWidget::OnFinished() { //here we create a new tool m_CreatedTool = mitk::NavigationTool::New(); //create DataNode... mitk::DataNode::Pointer newNode = mitk::DataNode::New(); if(m_Controls->m_Surface_Use_Sphere->isChecked()) { //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkConeSource *vtkData = vtkConeSource::New(); vtkData->SetAngle(5.0); vtkData->SetResolution(50); vtkData->SetHeight(6.0f); vtkData->SetRadius(2.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); newNode->SetData(mySphere); } else { newNode->SetData(m_Controls->m_SurfaceChooser->GetSelectedNode()->GetData()); } newNode->SetName(m_Controls->m_ToolNameEdit->text().toLatin1()); m_CreatedTool->SetDataNode(newNode); //fill NavigationTool object m_CreatedTool->SetCalibrationFile(m_Controls->m_CalibrationFileName->text().toLatin1().data()); m_CreatedTool->SetIdentifier(m_Controls->m_IdentifierEdit->text().toLatin1().data()); m_CreatedTool->SetSerialNumber(m_Controls->m_SerialNumberEdit->text().toLatin1().data()); //Tracking Device if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Aurora") m_CreatedTool->SetTrackingDeviceType(mitk::NDIAurora); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NDI Polaris") m_CreatedTool->SetTrackingDeviceType(mitk::NDIPolaris); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="CT MicronTracker") m_CreatedTool->SetTrackingDeviceType(mitk::ClaronMicron); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="NP Optitrack") m_CreatedTool->SetTrackingDeviceType(mitk::NPOptitrack); else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="Virtual Tracker") m_CreatedTool->SetTrackingDeviceType(mitk::VirtualTracker); +else if (m_Controls->m_TrackingDeviceTypeChooser->currentText()=="Open IGT Link") m_CreatedTool->SetTrackingDeviceType(mitk::OpenIGTLinkTrackingDeviceConnection); else m_CreatedTool->SetTrackingDeviceType(mitk::TrackingSystemNotSpecified); //ToolType if (m_Controls->m_ToolTypeChooser->currentText()=="Instrument") m_CreatedTool->SetType(mitk::NavigationTool::Instrument); else if (m_Controls->m_ToolTypeChooser->currentText()=="Fiducial") m_CreatedTool->SetType(mitk::NavigationTool::Fiducial); else if (m_Controls->m_ToolTypeChooser->currentText()=="Skinmarker") m_CreatedTool->SetType(mitk::NavigationTool::Skinmarker); else m_CreatedTool->SetType(mitk::NavigationTool::Unknown); //Tool Tip mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_AdvancedWidget->GetManipulatedToolTip()); m_CreatedTool->SetToolTipOrientation(tempND->GetOrientation()); m_CreatedTool->SetToolTipPosition(tempND->GetPosition()); //Tool Landmarks mitk::PointSet::Pointer toolCalLandmarks, toolRegLandmarks; GetUIToolLandmarksLists(toolCalLandmarks,toolRegLandmarks); m_CreatedTool->SetToolCalibrationLandmarks(toolCalLandmarks); m_CreatedTool->SetToolRegistrationLandmarks(toolRegLandmarks); emit NavigationToolFinished(); } void QmitkNavigationToolCreationWidget::OnCancel() { m_CreatedTool = NULL; emit Canceled(); } void QmitkNavigationToolCreationWidget::OnLoadSurface() { std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Surface"), "/", tr("STL (*.stl)")).toLatin1().data(); try { mitk::IOUtil::Load(filename.c_str(), *m_DataStorage); } catch (mitk::Exception &e) { MITK_ERROR << "Exception occured: " << e.what(); } } void QmitkNavigationToolCreationWidget::OnLoadCalibrationFile() { m_Controls->m_CalibrationFileName->setText(QFileDialog::getOpenFileName(NULL,tr("Open Calibration File"), "/", "*.*")); } void QmitkNavigationToolCreationWidget::SetDefaultData(mitk::NavigationTool::Pointer DefaultTool) { m_Controls->m_ToolNameEdit->setText(QString(DefaultTool->GetDataNode()->GetName().c_str())); m_Controls->m_IdentifierEdit->setText(QString(DefaultTool->GetIdentifier().c_str())); m_Controls->m_SerialNumberEdit->setText(QString(DefaultTool->GetSerialNumber().c_str())); m_AdvancedWidget->SetDefaultTooltip( DefaultTool->GetToolTipTransform() ); switch(DefaultTool->GetTrackingDeviceType()) { case mitk::NDIAurora: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0);break; case mitk::NDIPolaris: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(1);break; case mitk::ClaronMicron: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(2);break; case mitk::NPOptitrack: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(3);break; case mitk::VirtualTracker: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(4);break; +case mitk::OpenIGTLinkTrackingDeviceConnection: +m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(5);break; default: m_Controls->m_TrackingDeviceTypeChooser->setCurrentIndex(0); } m_Controls->m_CalibrationFileName->setText(QString(DefaultTool->GetCalibrationFile().c_str())); m_Controls->m_Surface_Use_Other->setChecked(true); switch(DefaultTool->GetType()) { case mitk::NavigationTool::Instrument: m_Controls->m_ToolTypeChooser->setCurrentIndex(0); break; case mitk::NavigationTool::Fiducial: m_Controls->m_ToolTypeChooser->setCurrentIndex(1); break; case mitk::NavigationTool::Skinmarker: m_Controls->m_ToolTypeChooser->setCurrentIndex(2); break; case mitk::NavigationTool::Unknown: m_Controls->m_ToolTypeChooser->setCurrentIndex(3); break; } m_Controls->m_SurfaceChooser->SetSelectedNode(DefaultTool->GetDataNode()); FillUIToolLandmarkLists(DefaultTool->GetToolCalibrationLandmarks(),DefaultTool->GetToolRegistrationLandmarks()); } //################################################################################## //############################## internal help methods ############################# //################################################################################## void QmitkNavigationToolCreationWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkNavigationToolCreationWidget::OnShowAdvancedOptions(bool state) { if(state) { m_AdvancedWidget->show(); m_AdvancedWidget->SetDefaultTooltip(m_AdvancedWidget->GetManipulatedToolTip()); //use the last one, if there is one m_AdvancedWidget->ReInitialize(); // reinit the views with the new nodes mitk::DataStorage::SetOfObjects::ConstPointer rs = m_DataStorage->GetAll(); mitk::TimeGeometry::Pointer bounds = m_DataStorage->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } else { m_AdvancedWidget->hide(); } } void QmitkNavigationToolCreationWidget::OnProcessDialogCloseRequest() { m_AdvancedWidget->hide(); m_Controls->m_ShowAdvancedOptionsPB->setChecked(false); } void QmitkNavigationToolCreationWidget::OnRetrieveDataForManualTooltipManipulation() { if(m_Controls->m_Surface_Use_Sphere->isChecked()) { m_AdvancedWidget->SetToolTipSurface(true); } else { m_AdvancedWidget->SetToolTipSurface(false, dynamic_cast(m_Controls->m_SurfaceChooser->GetSelectedNode().GetPointer())); } } void QmitkNavigationToolCreationWidget::OnSurfaceUseOtherToggled(bool checked) { m_Controls->m_LoadSurface->setEnabled(checked); } void QmitkNavigationToolCreationWidget::FillUIToolLandmarkLists(mitk::PointSet::Pointer calLandmarks, mitk::PointSet::Pointer regLandmarks) { m_calLandmarkNode->SetData(calLandmarks); m_regLandmarkNode->SetData(regLandmarks); m_Controls->m_CalibrationLandmarksList->SetPointSetNode(m_calLandmarkNode); m_Controls->m_RegistrationLandmarksList->SetPointSetNode(m_regLandmarkNode); } void QmitkNavigationToolCreationWidget::GetUIToolLandmarksLists(mitk::PointSet::Pointer& calLandmarks, mitk::PointSet::Pointer& regLandmarks) { calLandmarks = dynamic_cast(m_calLandmarkNode->GetData()); regLandmarks = dynamic_cast(m_regLandmarkNode->GetData()); } void QmitkNavigationToolCreationWidget::InitializeUIToolLandmarkLists() { m_calLandmarkNode = mitk::DataNode::New(); m_regLandmarkNode = mitk::DataNode::New(); FillUIToolLandmarkLists(mitk::PointSet::New(),mitk::PointSet::New()); } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui index 079e60455e..6bb7a309a6 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolCreationWidget.ui @@ -1,536 +1,541 @@ QmitkNavigationToolCreationWidgetControls 0 0 254 309 Form Device Type: 150 0 150 16777215 NDI Aurora NDI Polaris CT MicronTracker NP Optitrack Virtual Tracker + + + Open IGT Link + + 0 0 0 236 115 Basic Information 100 0 Name: NewTool 100 0 Calibration File: none 40 16777215 Load Qt::Vertical 20 40 0 0 303 - 98 + 95 Tool Visualization Use Simple Cone true Use Surface: Qt::Horizontal QSizePolicy::Fixed 25 20 200 0 150 16777215 false 40 16777215 Load Qt::Horizontal 40 20 Qt::Vertical 20 8 0 0 - 236 - 115 + 145 + 73 Tool Landmarks 0 Calibration Landmarks Registration Landmarks 0 0 276 133 Advanced 100 0 Tool Type: 150 0 150 16777215 Instrument Fiducial Skinmarker Unkown 100 0 Identifier: <not given> 100 0 Serial Number: <not given> Tooltip: Qt::Horizontal 40 20 Edit Tooltip true Qt::Vertical 20 40 Qt::Horizontal Qt::Horizontal 40 20 Cancel Finished QmitkDataStorageComboBox QComboBox
QmitkDataStorageComboBox.h
1
QmitkPointListWidget QWidget
QmitkPointListWidget.h
1
diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp index f20f76c80a..45a309efb0 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.cpp @@ -1,359 +1,382 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkNavigationToolManagementWidget.h" //mitk headers #include "mitkTrackingTypes.h" #include #include #include #include #include #include //qt headers #include #include #include //poco headers #include const std::string QmitkNavigationToolManagementWidget::VIEW_ID = "org.mitk.views.navigationtoolmanagementwidget"; QmitkNavigationToolManagementWidget::QmitkNavigationToolManagementWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); } QmitkNavigationToolManagementWidget::~QmitkNavigationToolManagementWidget() { } void QmitkNavigationToolManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkNavigationToolManagementWidgetControls; m_Controls->setupUi(parent); } //Disable StorageControls in the beginning, because there is no storage to edit DisableStorageControls(); } void QmitkNavigationToolManagementWidget::OnLoadTool() { if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } mitk::NavigationToolReader::Pointer myReader = mitk::NavigationToolReader::New(); std::string filename = QFileDialog::getOpenFileName(NULL,tr("Add Navigation Tool"), "/", "*.IGTTool").toLatin1().data(); if (filename == "") return; mitk::NavigationTool::Pointer readTool = myReader->DoRead(filename); if (readTool.IsNull()) MessageBox("Error: " + myReader->GetErrorMessage()); else { if (!m_NavigationToolStorage->AddTool(readTool)) { MessageBox("Error: Can't add tool!"); m_DataStorage->Remove(readTool->GetDataNode()); } UpdateToolTable(); } } void QmitkNavigationToolManagementWidget::OnSaveTool() { //if no item is selected, show error message: if (m_Controls->m_ToolList->currentItem() == NULL) {MessageBox("Error: Please select tool first!");return;} mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); std::string filename = QFileDialog::getSaveFileName(NULL,tr("Save Navigation Tool"), "/", "*.IGTTool").toLatin1().data(); if (filename == "") return; if (!myWriter->DoWrite(filename,m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()))) MessageBox("Error: "+ myWriter->GetErrorMessage()); } void QmitkNavigationToolManagementWidget::CreateConnections() { if ( m_Controls ) { //main widget page: connect( (QObject*)(m_Controls->m_AddTool), SIGNAL(clicked()), this, SLOT(OnAddTool()) ); connect( (QObject*)(m_Controls->m_DeleteTool), SIGNAL(clicked()), this, SLOT(OnDeleteTool()) ); connect( (QObject*)(m_Controls->m_EditTool), SIGNAL(clicked()), this, SLOT(OnEditTool()) ); + connect( (QObject*)(m_Controls->m_MoveToolUp), SIGNAL(clicked()), this, SLOT(OnMoveToolUp()) ); + connect( (QObject*)(m_Controls->m_MoveToolDown), SIGNAL(clicked()), this, SLOT(OnMoveToolDown()) ); connect( (QObject*)(m_Controls->m_LoadStorage), SIGNAL(clicked()), this, SLOT(OnLoadStorage()) ); connect( (QObject*)(m_Controls->m_SaveStorage), SIGNAL(clicked()), this, SLOT(OnSaveStorage()) ); connect( (QObject*)(m_Controls->m_LoadTool), SIGNAL(clicked()), this, SLOT(OnLoadTool()) ); connect( (QObject*)(m_Controls->m_SaveTool), SIGNAL(clicked()), this, SLOT(OnSaveTool()) ); connect( (QObject*)(m_Controls->m_CreateNewStorage), SIGNAL(clicked()), this, SLOT(OnCreateStorage()) ); //widget page "add tool": connect( (QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(Canceled()), this, SLOT(OnAddToolCancel()) ); connect( (QObject*)(m_Controls->m_ToolCreationWidget), SIGNAL(NavigationToolFinished()), this, SLOT(OnAddToolSave()) ); } } void QmitkNavigationToolManagementWidget::Initialize(mitk::DataStorage* dataStorage) { m_DataStorage = dataStorage; m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage,"Tool0"); } void QmitkNavigationToolManagementWidget::LoadStorage(mitk::NavigationToolStorage::Pointer storageToLoad) { if(storageToLoad.IsNotNull()) { m_NavigationToolStorage = storageToLoad; m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); } else { m_NavigationToolStorage = NULL; DisableStorageControls(); } UpdateToolTable(); } //################################################################################## //############################## slots: main widget ################################ //################################################################################## +void QmitkNavigationToolManagementWidget::OnMoveToolUp() +{ + std::string currentIdentifier = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetIdentifier(); + int NewNumber = m_Controls->m_ToolList->currentIndex().row() - 1; + if (NewNumber<0) {MITK_WARN << "Cannot move tool up because it is on the top!";} + else {m_NavigationToolStorage->AssignToolNumber(currentIdentifier,NewNumber);} + UpdateToolTable(); +} + +void QmitkNavigationToolManagementWidget::OnMoveToolDown() +{ + std::string currentIdentifier = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetIdentifier(); + int NewNumber = m_Controls->m_ToolList->currentIndex().row() + 1; + if (NewNumber>=m_NavigationToolStorage->GetToolCount()) {MITK_WARN << "Cannot move tool down because it is the last tool in this storage!";} + else {m_NavigationToolStorage->AssignToolNumber(currentIdentifier,NewNumber);} + UpdateToolTable(); +} + + void QmitkNavigationToolManagementWidget::OnAddTool() { if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } QString defaultIdentifier = "NavigationTool#"+QString::number(m_NavigationToolStorage->GetToolCount()); QString defaultName = "NavigationTool"+QString::number(m_NavigationToolStorage->GetToolCount()); m_Controls->m_ToolCreationWidget->Initialize(m_DataStorage,defaultIdentifier.toStdString(),defaultName.toStdString()); m_edit = false; m_Controls->m_MainWidgets->setCurrentIndex(1); } void QmitkNavigationToolManagementWidget::OnDeleteTool() { //first: some checks if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } m_DataStorage->Remove(m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row())->GetDataNode()); m_NavigationToolStorage->DeleteTool(m_Controls->m_ToolList->currentIndex().row()); UpdateToolTable(); } void QmitkNavigationToolManagementWidget::OnEditTool() { if(m_NavigationToolStorage->isLocked()) { MessageBox("Storage is locked, cannot modify it. Maybe the tracking device which uses this storage is connected. If you want to modify the storage please disconnect the device first."); return; } else if (m_Controls->m_ToolList->currentItem() == NULL) //if no item is selected, show error message: { MessageBox("Error: Please select tool first!"); return; } mitk::NavigationTool::Pointer selectedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); m_Controls->m_ToolCreationWidget->SetDefaultData(selectedTool); m_edit = true; m_Controls->m_MainWidgets->setCurrentIndex(1); } void QmitkNavigationToolManagementWidget::OnCreateStorage() { QString storageName = QInputDialog::getText(NULL,"Storage Name","Name of the new tool storage:"); if (storageName.isNull()) return; m_NavigationToolStorage = mitk::NavigationToolStorage::New(this->m_DataStorage); m_NavigationToolStorage->SetName(storageName.toStdString()); m_Controls->m_StorageName->setText(m_NavigationToolStorage->GetName().c_str()); EnableStorageControls(); emit NewStorageAdded(m_NavigationToolStorage, storageName.toStdString()); } void QmitkNavigationToolManagementWidget::OnLoadStorage() { mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(m_DataStorage); std::string filename = QFileDialog::getOpenFileName(NULL, tr("Open Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")).toStdString(); if (filename == "") return; try { mitk::NavigationToolStorage::Pointer tempStorage = myDeserializer->Deserialize(filename); if (tempStorage.IsNull()) MessageBox("Error" + myDeserializer->GetErrorMessage()); else { Poco::Path myPath = Poco::Path(filename.c_str()); tempStorage->SetName(myPath.getFileName()); //set the filename as name for the storage, so the user can identify it this->LoadStorage(tempStorage); emit NewStorageAdded(m_NavigationToolStorage,myPath.getFileName()); } } catch (const mitk::Exception& exception) { MessageBox(exception.GetDescription()); } } void QmitkNavigationToolManagementWidget::OnSaveStorage() { //read in filename QString filename = QFileDialog::getSaveFileName(NULL, tr("Save Navigation Tool Storage"), "/", tr("IGT Tool Storage (*.IGTToolStorage)")); if (filename.isEmpty()) return; //canceled by the user // add file extension if it wasn't added by the file dialog if ( filename.right(15) != ".IGTToolStorage" ) { filename += ".IGTToolStorage"; } //serialize tool storage mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); if (!mySerializer->Serialize(filename.toStdString(),m_NavigationToolStorage)) { MessageBox("Error: " + mySerializer->GetErrorMessage()); return; } Poco::Path myPath = Poco::Path(filename.toStdString()); m_Controls->m_StorageName->setText(QString::fromStdString(myPath.getFileName())); } //################################################################################## //############################## slots: add tool widget ############################ //################################################################################## void QmitkNavigationToolManagementWidget::OnAddToolSave() { mitk::NavigationTool::Pointer newTool = m_Controls->m_ToolCreationWidget->GetCreatedTool(); if (m_edit) //here we edit a existing tool { mitk::NavigationTool::Pointer editedTool = m_NavigationToolStorage->GetTool(m_Controls->m_ToolList->currentIndex().row()); editedTool->Graft(newTool); } else //here we create a new tool { m_NavigationToolStorage->AddTool(newTool); } UpdateToolTable(); m_Controls->m_MainWidgets->setCurrentIndex(0); } void QmitkNavigationToolManagementWidget::OnAddToolCancel() { m_Controls->m_MainWidgets->setCurrentIndex(0); } //################################################################################## //############################## private help methods ############################## //################################################################################## void QmitkNavigationToolManagementWidget::UpdateToolTable() { m_Controls->m_ToolList->clear(); if(m_NavigationToolStorage.IsNull()) return; for(int i=0; iGetToolCount(); i++) { QString currentTool = "Tool" + QString::number(i) + ": " + QString(m_NavigationToolStorage->GetTool(i)->GetDataNode()->GetName().c_str())+ " "; switch (m_NavigationToolStorage->GetTool(i)->GetTrackingDeviceType()) { case mitk::ClaronMicron: currentTool += "(MicronTracker/"; break; case mitk::NDIAurora: currentTool += "(NDI Aurora/"; break; case mitk::NDIPolaris: currentTool += "(NDI Polaris/"; break; case mitk::NPOptitrack: currentTool += "(NP Optitrack/"; break; case mitk::VirtualTracker: currentTool += "(Virtual Tracker/"; break; + case mitk::OpenIGTLinkTrackingDeviceConnection: + currentTool += "(Open IGT Link/"; break; default: currentTool += "(unknown tracking system/"; break; } switch (m_NavigationToolStorage->GetTool(i)->GetType()) { case mitk::NavigationTool::Instrument: currentTool += "Instrument)"; break; case mitk::NavigationTool::Fiducial: currentTool += "Fiducial)"; break; case mitk::NavigationTool::Skinmarker: currentTool += "Skinmarker)"; break; default: currentTool += "Unknown)"; } m_Controls->m_ToolList->addItem(currentTool); } } void QmitkNavigationToolManagementWidget::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkNavigationToolManagementWidget::DisableStorageControls() { m_Controls->m_StorageName->setText(""); m_Controls->m_AddTool->setEnabled(false); m_Controls->m_LoadTool->setEnabled(false); m_Controls->m_selectedLabel->setEnabled(false); m_Controls->m_DeleteTool->setEnabled(false); m_Controls->m_EditTool->setEnabled(false); m_Controls->m_SaveTool->setEnabled(false); m_Controls->m_ToolList->setEnabled(false); m_Controls->m_SaveStorage->setEnabled(false); m_Controls->m_ToolLabel->setEnabled(false); } void QmitkNavigationToolManagementWidget::EnableStorageControls() { m_Controls->m_AddTool->setEnabled(true); m_Controls->m_LoadTool->setEnabled(true); m_Controls->m_selectedLabel->setEnabled(true); m_Controls->m_DeleteTool->setEnabled(true); m_Controls->m_EditTool->setEnabled(true); m_Controls->m_SaveTool->setEnabled(true); m_Controls->m_ToolList->setEnabled(true); m_Controls->m_SaveStorage->setEnabled(true); m_Controls->m_ToolLabel->setEnabled(true); } diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h index 8d5f83139c..60e23cd47c 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidget.h @@ -1,110 +1,112 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKNAVIGATIONTOOLMANAGEMENTWIDGET_H #define QMITKNAVIGATIONTOOLMANAGEMENTWIDGET_H //QT headers #include //mitk headers #include "MitkIGTUIExports.h" #include "mitkNavigationTool.h" #include //ui header #include "ui_QmitkNavigationToolManagementWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to manage NavigationTools and * NavigationToolStorages. This means a user may create, save and load * single NavigationTools and/or NavigationToolStorages with this widget. * * Be sure to call the Initialize-methode before you start the widget * otherwise some errors might occure. * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkNavigationToolManagementWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** Initializes the widget. Has to be called before any action, otherwise errors might occur. */ void Initialize(mitk::DataStorage* dataStorage); /** Loads a storage to the widget. The old storage storage is dropped, so be careful, if the * storage is not saved somewhere else it might be lost. You might want to ask the user if he * wants to save the storage to the harddisk before calling this method. * @param storageToLoad This storage will be loaded and might be modified by the user. */ void LoadStorage(mitk::NavigationToolStorage::Pointer storageToLoad); QmitkNavigationToolManagementWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkNavigationToolManagementWidget(); signals: /** This signal is emmited if a new storage was added by the widget itself, e.g. because * a storage was loaded from the harddisk. * @param newStorage Holds the new storage which was added. * @param storageName Name of the new storage (e.g. filename) */ void NewStorageAdded(mitk::NavigationToolStorage::Pointer newStorage, std::string storageName); protected slots: //main widget page: void OnAddTool(); void OnDeleteTool(); void OnEditTool(); void OnLoadTool(); void OnSaveTool(); + void OnMoveToolUp(); + void OnMoveToolDown(); void OnLoadStorage(); void OnSaveStorage(); void OnCreateStorage(); //widget page "add tool": void OnAddToolCancel(); void OnAddToolSave(); protected: /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkNavigationToolManagementWidgetControls* m_Controls; /** @brief holds the DataStorage */ mitk::DataStorage* m_DataStorage; /** @brief holds the NavigationToolStorage we are working with. */ mitk::NavigationToolStorage::Pointer m_NavigationToolStorage; /** @brief shows if we are in edit mode, if not we create new navigation tool objects. */ bool m_edit; //############## private help methods ####################### void MessageBox(std::string s); void UpdateToolTable(); void DisableStorageControls(); void EnableStorageControls(); }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui index 2cc67461de..a80055349a 100644 --- a/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkNavigationToolManagementWidgetControls.ui @@ -1,282 +1,308 @@ QmitkNavigationToolManagementWidgetControls 0 0 443 781 Form Qt::Horizontal 40 20 Whole Storage: Create New Load Save Qt::Horizontal 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Storage Name:</span></p></body></html> <none> Qt::Horizontal 40 20 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Tools:</span></p></body></html> Qt::Horizontal 40 20 50 16777215 Add 50 16777215 Load <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Selected:</span></p></body></html> + + + + + 50 + 16777215 + + + + Up + + + + + + + + 50 + 16777215 + + + + Down + + + 50 16777215 Delete 50 16777215 Edit 50 16777215 Save Qt::Vertical 20 40 0 150 Qt::Vertical 20 40 QmitkNavigationToolCreationWidget QWidget
QmitkNavigationToolCreationWidget.h
1
diff --git a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp index f9bde59929..b4b17ce60e 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp @@ -1,749 +1,758 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkTrackingDeviceConfigurationWidget.h" #include #include #include #include +#include #include #include #include #include #include #include #include #include #include #include const std::string QmitkTrackingDeviceConfigurationWidget::VIEW_ID = "org.mitk.views.trackingdeviceconfigurationwidget"; QmitkTrackingDeviceConfigurationWidget::QmitkTrackingDeviceConfigurationWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { //initialize worker thread m_TestConnectionWorker = new QmitkTrackingDeviceConfigurationWidgetConnectionWorker(); m_ScanPortsWorker = new QmitkTrackingDeviceConfigurationWidgetScanPortsWorker(); m_ScanPortsWorkerThread = new QThread(); m_TestConnectionWorkerThread = new QThread(); //initializations m_Controls = NULL; CreateQtPartControl(this); CreateConnections(); m_MTCalibrationFile = ""; m_AdvancedUserControl = true; //initialize a few UI elements this->m_TrackingDeviceConfigurated = false; AddOutput("
NDI Polaris selected"); //Polaris is selected by default m_Controls->m_trackingDeviceChooser->setCurrentIndex(0); m_Controls->m_TrackingSystemWidget->setCurrentIndex(0); //reset a few things ResetOutput(); //restore old UI settings LoadUISettings(); } void QmitkTrackingDeviceConfigurationWidget::SetGUIStyle(QmitkTrackingDeviceConfigurationWidget::Style style) { switch(style) { case QmitkTrackingDeviceConfigurationWidget::SIMPLE: //move all UI elements to an empty dummy layout //m_Controls->dummyLayout->addItem(m_Controls->mainLayout); m_Controls->dummyLayout->addWidget(m_Controls->widget_title_label); m_Controls->dummyLayout->addWidget(m_Controls->choose_tracking_device_label); m_Controls->dummyLayout->addWidget(m_Controls->polaris_label); m_Controls->dummyLayout->addWidget(m_Controls->aurora_label); //m_Controls->dummyLayout->addWidget(m_Controls->aurora_label); m_Controls->dummyLayout->addWidget(m_Controls->microntracker_label); m_Controls->dummyLayout->addWidget(m_Controls->m_testConnectionMicronTracker); m_Controls->dummyLayout->addWidget(m_Controls->m_outputTextMicronTracker); m_Controls->dummyLayout->addWidget(m_Controls->m_outputTextAurora); m_Controls->dummyLayout->addWidget(m_Controls->m_testConnectionAurora); m_Controls->dummyLayout->addWidget(m_Controls->m_outputTextPolaris); m_Controls->dummyLayout->addWidget(m_Controls->m_testConnectionPolaris); m_Controls->dummyLayout->addWidget(m_Controls->m_polarisTrackingModeBox); m_Controls->dummyLayout->addWidget(m_Controls->m_testConnectionOptitrack); m_Controls->dummyLayout->addWidget(m_Controls->m_outputTextOptitrack); m_Controls->dummyLayout->addWidget(m_Controls->m_OptitrackExp); m_Controls->dummyLayout->addWidget(m_Controls->m_OptitrackThr); m_Controls->dummyLayout->addWidget(m_Controls->m_OptitrackLed); m_Controls->dummyLayout->addWidget(m_Controls->Optitrack_label); m_Controls->dummyLayout->addWidget(m_Controls->m_finishedLine); m_Controls->dummyLayout->addWidget(m_Controls->line); m_Controls->dummyLayout->addWidget(m_Controls->configuration_finished_label); m_Controls->dummyLayout->addItem(m_Controls->horizontalLayout_4); m_Controls->mainLayout->removeItem(m_Controls->horizontalLayout_4); m_Controls->dummyLayout->addWidget(m_Controls->configuration_finished_label); m_Controls->dummyLayout->addItem(m_Controls->verticalSpacer_2); m_Controls->verticalLayout_3->removeItem(m_Controls->verticalSpacer_2); m_Controls->dummyLayout->addItem(m_Controls->horizontalSpacer_9); m_Controls->horizontalLayout_9->removeItem(m_Controls->horizontalSpacer_9); m_Controls->dummyLayout->addItem(m_Controls->horizontalSpacer_3); m_Controls->horizontalLayout_11->removeItem(m_Controls->horizontalSpacer_3); m_Controls->dummyLayout->addItem(m_Controls->verticalSpacer_3); m_Controls->verticalLayout_7->removeItem(m_Controls->verticalSpacer_3); m_Controls->dummyLayout->addItem(m_Controls->verticalSpacer_4); m_Controls->verticalLayout_10->removeItem(m_Controls->verticalSpacer_4); m_Controls->dummyLayout->addItem(m_Controls->horizontalSpacer_10); m_Controls->verticalLayout_10->removeItem(m_Controls->horizontalSpacer_10); //set height to min m_Controls->m_outputTextPolaris->setMinimumHeight(0); m_Controls->m_outputTextPolaris->setMaximumHeight(0); m_Controls->m_outputTextMicronTracker->setMinimumHeight(0); m_Controls->m_outputTextMicronTracker->setMaximumHeight(0); m_Controls->m_outputTextAurora->setMinimumHeight(0); m_Controls->m_outputTextAurora->setMaximumHeight(0); m_Controls->m_finishedButton->setMinimumHeight(0); m_Controls->m_finishedButton->setMaximumHeight(0); m_Controls->m_resetButton->setMinimumHeight(0); m_Controls->m_resetButton->setMaximumHeight(0); //set the height of the tracking device combo box m_Controls->m_trackingDeviceChooser->setMinimumHeight(50); //move back the used elemets to the main layout m_Controls->simpleLayout->addWidget(m_Controls->m_trackingDeviceChooser); m_Controls->simpleLayout->addWidget(m_Controls->m_TrackingSystemWidget); m_Controls->mainWidget->setCurrentIndex(1); this->setMaximumHeight(150); this->EnableAdvancedUserControl(false); break; case QmitkTrackingDeviceConfigurationWidget::ADVANCED: //default at the moment => start settings are advanced break; } } QmitkTrackingDeviceConfigurationWidget::~QmitkTrackingDeviceConfigurationWidget() { StoreUISettings(); if (m_ScanPortsWorker) delete m_ScanPortsWorker; if (m_TestConnectionWorker) delete m_TestConnectionWorker; if (m_ScanPortsWorkerThread) delete m_ScanPortsWorkerThread; if (m_TestConnectionWorkerThread) delete m_TestConnectionWorkerThread; } void QmitkTrackingDeviceConfigurationWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkTrackingDeviceConfigurationWidgetControls; m_Controls->setupUi(parent); } } void QmitkTrackingDeviceConfigurationWidget::CreateConnections() { if ( m_Controls ) { connect( (QObject*)(m_Controls->m_trackingDeviceChooser), SIGNAL(currentIndexChanged(int)), this, SLOT(TrackingDeviceChanged()) ); connect( (QObject*)(m_Controls->m_testConnectionPolaris), SIGNAL(clicked()), this, SLOT(TestConnection()) ); connect( (QObject*)(m_Controls->m_testConnectionAurora), SIGNAL(clicked()), this, SLOT(TestConnection()) ); connect( (QObject*)(m_Controls->m_testConnectionMicronTracker), SIGNAL(clicked()), this, SLOT(TestConnection()) ); connect( (QObject*)(m_Controls->m_testConnectionOptitrack), SIGNAL(clicked()), this, SLOT(TestConnection()) ); connect( (QObject*)(m_Controls->m_resetButton), SIGNAL(clicked()), this, SLOT(ResetByUser()) ); connect( (QObject*)(m_Controls->m_finishedButton), SIGNAL(clicked()), this, SLOT(Finished()) ); connect( (QObject*)(m_Controls->m_AutoScanPolaris), SIGNAL(clicked()), this, SLOT(AutoScanPorts()) ); connect( (QObject*)(m_Controls->m_AutoScanAurora), SIGNAL(clicked()), this, SLOT(AutoScanPorts()) ); connect( (QObject*)(m_Controls->m_SetMTCalibrationFile), SIGNAL(clicked()), this, SLOT(SetMTCalibrationFileClicked()) ); connect( (QObject*)(m_Controls->m_SetOptitrackCalibrationFile), SIGNAL(clicked()), this, SLOT(SetOptitrackCalibrationFileClicked()) ); //slots for the worker thread connect(m_ScanPortsWorker, SIGNAL(PortsScanned(int,int,QString,int,int)), this, SLOT(AutoScanPortsFinished(int,int,QString,int,int)) ); connect(m_TestConnectionWorker, SIGNAL(ConnectionTested(bool,QString)), this, SLOT(TestConnectionFinished(bool,QString)) ); connect(m_ScanPortsWorkerThread,SIGNAL(started()), m_ScanPortsWorker, SLOT(ScanPortsThreadFunc()) ); connect(m_TestConnectionWorkerThread,SIGNAL(started()), m_TestConnectionWorker, SLOT(TestConnectionThreadFunc()) ); //move the worker to the thread m_ScanPortsWorker->moveToThread(m_ScanPortsWorkerThread); m_TestConnectionWorker->moveToThread(m_TestConnectionWorkerThread); //set a few UI components depending on Windows / Linux #ifdef WIN32 m_Controls->portTypeLabelPolaris->setVisible(false); m_Controls->portTypePolaris->setVisible(false); m_Controls->portTypeLabelAurora->setVisible(false); m_Controls->portTypeAurora->setVisible(false); #else m_Controls->comPortLabelAurora->setText("Port Nr:"); m_Controls->m_comPortLabelPolaris->setText("Port Nr:"); m_Controls->m_portSpinBoxAurora->setPrefix(""); m_Controls->m_portSpinBoxPolaris->setPrefix(""); #endif //disable unused UI component m_Controls->m_polarisTrackingModeBox->setVisible(false); //don't delete this component, because it is used in the MBI part of MITK } } void QmitkTrackingDeviceConfigurationWidget::TrackingDeviceChanged() { //show the correspondig widget m_Controls->m_TrackingSystemWidget->setCurrentIndex(m_Controls->m_trackingDeviceChooser->currentIndex()); //the new trackingdevice is not configurated yet m_TrackingDeviceConfigurated = false; //reset output ResetOutput(); //print output and do further initializations if (m_Controls->m_trackingDeviceChooser->currentIndex()==0)//NDI Polaris { AddOutput("
NDI Polaris selected"); } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==1) //NDI Aurora { AddOutput("
NDI Aurora selected"); } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==2) //ClaronTechnology MicronTracker 2 { AddOutput("
Microntracker selected"); if (!mitk::ClaronTrackingDevice::New()->IsDeviceInstalled()) { AddOutput("
ERROR: not installed!"); } else if (this->m_MTCalibrationFile == "") //if configuration file for MicronTracker is empty: load default { mitk::ClaronTrackingDevice::Pointer tempDevice = mitk::ClaronTrackingDevice::New(); m_MTCalibrationFile = tempDevice->GetCalibrationDir(); Poco::Path myPath = Poco::Path(m_MTCalibrationFile.c_str()); m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString(myPath.getFileName().c_str())); } } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==3) { AddOutput("
Optitrack selected"); if (!mitk::OptitrackTrackingDevice::New()->IsDeviceInstalled()) { AddOutput("
ERROR: not installed!"); } } emit TrackingDeviceSelectionChanged(); } void QmitkTrackingDeviceConfigurationWidget::EnableUserReset(bool enable) { if (enable) m_Controls->m_resetButton->setVisible(true); else m_Controls->m_resetButton->setVisible(false); } void QmitkTrackingDeviceConfigurationWidget::TestConnection() { this->setEnabled(false); //construct a tracking device: mitk::TrackingDevice::Pointer testTrackingDevice = ConstructTrackingDevice(); m_TestConnectionWorker->SetTrackingDevice(testTrackingDevice); m_TestConnectionWorkerThread->start(); emit ProgressStarted(); } void QmitkTrackingDeviceConfigurationWidget::TestConnectionFinished(bool connected, QString output) { m_TestConnectionWorkerThread->quit(); AddOutput(output.toStdString()); MITK_INFO << "Test connection: " << connected; this->setEnabled(true); emit ProgressFinished(); } void QmitkTrackingDeviceConfigurationWidget::Finished() { m_TrackingDevice = ConstructTrackingDevice(); m_Controls->m_TrackingSystemWidget->setEnabled(false); m_Controls->m_trackingDeviceChooser->setEnabled(false); m_Controls->choose_tracking_device_label->setEnabled(false); m_Controls->configuration_finished_label->setText("\n\n

Configuration finished

"); this->m_TrackingDeviceConfigurated = true; emit TrackingDeviceConfigurationFinished(); } void QmitkTrackingDeviceConfigurationWidget::Reset() { m_TrackingDevice = NULL; m_Controls->m_TrackingSystemWidget->setEnabled(true); m_Controls->m_trackingDeviceChooser->setEnabled(true); m_Controls->choose_tracking_device_label->setEnabled(true); m_Controls->configuration_finished_label->setText("\n\n

Press \"Finished\" to confirm configuration

"); this->m_TrackingDeviceConfigurated = false; emit TrackingDeviceConfigurationReseted(); } void QmitkTrackingDeviceConfigurationWidget::ResetByUser() { Reset(); } void QmitkTrackingDeviceConfigurationWidget::AutoScanPorts() { this->setEnabled(false); AddOutput("
Scanning..."); m_ScanPortsWorkerThread->start(); emit ProgressStarted(); } void QmitkTrackingDeviceConfigurationWidget::AutoScanPortsFinished(int PolarisPort, int AuroraPort, QString result, int PortTypePolaris, int PortTypeAurora) { m_ScanPortsWorkerThread->quit(); #ifdef WIN32 if((PortTypePolaris!=-1)||(PortTypeAurora!=-1)) {MITK_WARN << "Port type is specified although this should not be the case for Windows. Ignoring port type.";} #else //linux systems if (PortTypePolaris!=-1) {m_Controls->portTypePolaris->setCurrentIndex(PortTypePolaris);} if (PortTypeAurora!=-1) {m_Controls->portTypeAurora->setCurrentIndex(PortTypeAurora);} #endif m_Controls->m_portSpinBoxPolaris->setValue(PolarisPort); m_Controls->m_portSpinBoxAurora->setValue(AuroraPort); AddOutput(result.toStdString()); this->setEnabled(true); emit ProgressFinished(); } void QmitkTrackingDeviceConfigurationWidget::SetMTCalibrationFileClicked() { std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Calibration File"), "/", "*.*").toLatin1().data(); if (filename=="") {return;} else { m_MTCalibrationFile = filename; Poco::Path myPath = Poco::Path(m_MTCalibrationFile.c_str()); m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString(myPath.getFileName().c_str())); } } void QmitkTrackingDeviceConfigurationWidget::SetOptitrackCalibrationFileClicked() { std::string filename = QFileDialog::getOpenFileName(NULL,tr("Open Calibration File"), "/", "*.*").toLatin1().data(); if (filename=="") {return;} else { m_OptitrackCalibrationFile = filename; Poco::Path myPath = Poco::Path(m_OptitrackCalibrationFile.c_str()); m_Controls->m_OptitrackCalibrationFile->setText("Calibration File: " + QString(myPath.getFileName().c_str())); } } //######################### internal help methods ####################################### void QmitkTrackingDeviceConfigurationWidget::ResetOutput() { m_output.str(""); m_output <<"output:"; m_Controls->m_outputTextAurora->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextPolaris->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextMicronTracker->setHtml(QString(m_output.str().c_str())); } void QmitkTrackingDeviceConfigurationWidget::AddOutput(std::string s) { //print output m_output << s; m_Controls->m_outputTextAurora->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextPolaris->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextMicronTracker->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextOptitrack->setHtml(QString(m_output.str().c_str())); m_Controls->m_outputTextPolaris->verticalScrollBar()->setValue(m_Controls->m_outputTextPolaris->verticalScrollBar()->maximum()); m_Controls->m_outputTextAurora->verticalScrollBar()->setValue(m_Controls->m_outputTextAurora->verticalScrollBar()->maximum()); m_Controls->m_outputTextMicronTracker->verticalScrollBar()->setValue(m_Controls->m_outputTextMicronTracker->verticalScrollBar()->maximum()); m_Controls->m_outputTextOptitrack->verticalScrollBar()->setValue(m_Controls->m_outputTextOptitrack->verticalScrollBar()->maximum()); repaint(); } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::ConstructTrackingDevice() { mitk::TrackingDevice::Pointer returnValue; //#### Step 1: configure tracking device: if (m_Controls->m_trackingDeviceChooser->currentIndex()==0)//NDI Polaris { if(m_Controls->m_radioPolaris5D->isChecked()) //5D Tracking { //not yet in the open source part so we'll only get NULL here. returnValue = ConfigureNDI5DTrackingDevice(); } else //6D Tracking { returnValue = ConfigureNDI6DTrackingDevice(); returnValue->SetType(mitk::NDIPolaris); } } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==1)//NDI Aurora { returnValue = ConfigureNDI6DTrackingDevice(); returnValue->SetType(mitk::NDIAurora); } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==2)//ClaronTechnology MicronTracker 2 { mitk::ClaronTrackingDevice::Pointer newDevice = mitk::ClaronTrackingDevice::New(); if(this->m_MTCalibrationFile=="") AddOutput("
Warning: Calibration file is not set!"); else { //extract path from calibration file and set the calibration dir of the device std::string path = itksys::SystemTools::GetFilenamePath(m_MTCalibrationFile); newDevice->SetCalibrationDir(path); } returnValue = newDevice; } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==3) { // Create the Tracking Device this->m_OptitrackDevice = mitk::OptitrackTrackingDevice::New(); returnValue = ConfigureOptitrackTrackingDevice(); returnValue->SetType(mitk::NPOptitrack); } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==4) //Virtual Tracker { // Create the Virtual Tracking Device returnValue = mitk::VirtualTrackingDevice::New(); } + else if (m_Controls->m_trackingDeviceChooser->currentIndex()==5) //OpenIGTLink + { + // Create the Virtual Tracking Device + mitk::OpenIGTLinkTrackingDevice::Pointer OIGTLDevice = mitk::OpenIGTLinkTrackingDevice::New(); + OIGTLDevice->SetPortNumber(m_Controls->m_OpenIGTLinkPort->text().toInt()); + OIGTLDevice->SetHostname(m_Controls->m_OpenIGTLinkHostname->text().toStdString()); + returnValue = OIGTLDevice; + } return returnValue; } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::ConfigureNDI5DTrackingDevice() { return NULL; } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::ConfigureOptitrackTrackingDevice() { mitk::OptitrackTrackingDevice::Pointer tempTrackingDevice = mitk::OptitrackTrackingDevice::New(); // Set the calibration File tempTrackingDevice->SetCalibrationPath(m_OptitrackCalibrationFile); //Set the camera parameters tempTrackingDevice->SetExp(m_Controls->m_OptitrackExp->value()); tempTrackingDevice->SetLed(m_Controls->m_OptitrackLed->value()); tempTrackingDevice->SetThr(m_Controls->m_OptitrackThr->value()); mitk::TrackingDevice::Pointer returnValue = static_cast(tempTrackingDevice); return returnValue; } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::ConfigureNDI6DTrackingDevice() { mitk::NDITrackingDevice::Pointer tempTrackingDevice = mitk::NDITrackingDevice::New(); //get port int port = 0; if (m_Controls->m_trackingDeviceChooser->currentIndex()==1) port = m_Controls->m_portSpinBoxAurora->value(); else port = m_Controls->m_portSpinBoxPolaris->value(); //build prefix (depends on linux/win) QString prefix = ""; #ifdef WIN32 prefix ="COM"; tempTrackingDevice->SetPortNumber(static_cast(port)); //also set the com port for compatibility if (m_Controls->m_trackingDeviceChooser->currentIndex()==0) //Polaris { tempTrackingDevice->SetIlluminationActivationRate(GetPolarisFrameRate()); } #else if (m_Controls->m_trackingDeviceChooser->currentIndex()==1) //Aurora { prefix = m_Controls->portTypeAurora->currentText(); } else if (m_Controls->m_trackingDeviceChooser->currentIndex()==0) //Polaris { prefix = m_Controls->portTypePolaris->currentText(); tempTrackingDevice->SetIlluminationActivationRate(GetPolarisFrameRate()); } #endif //build port name string QString portName = prefix + QString::number(port); tempTrackingDevice->SetDeviceName(portName.toStdString()); //set the port name tempTrackingDevice->SetBaudRate(mitk::SerialCommunication::BaudRate115200);//set baud rate mitk::TrackingDevice::Pointer returnValue = static_cast(tempTrackingDevice); return returnValue; } mitk::TrackingDevice::Pointer QmitkTrackingDeviceConfigurationWidget::GetTrackingDevice() { if (!m_AdvancedUserControl) m_TrackingDevice = ConstructTrackingDevice(); if (m_TrackingDevice.IsNull() || !m_TrackingDevice->IsDeviceInstalled()) return NULL; else return this->m_TrackingDevice; } bool QmitkTrackingDeviceConfigurationWidget::GetTrackingDeviceConfigured() { return this->m_TrackingDeviceConfigurated; } mitk::IlluminationActivationRate QmitkTrackingDeviceConfigurationWidget::GetPolarisFrameRate() { mitk::IlluminationActivationRate frameRate; QString comboBox = m_Controls->m_frameRateComboBoxPolaris->currentText(); if(comboBox == "20 Hz") frameRate = mitk::Hz20; else if(comboBox == "30 Hz") frameRate = mitk::Hz30; else if(comboBox == "60 Hz") frameRate = mitk::Hz60; return frameRate; } void QmitkTrackingDeviceConfigurationWidget::ConfigurationFinished() { Finished(); } void QmitkTrackingDeviceConfigurationWidget::EnableAdvancedUserControl(bool enable) { m_AdvancedUserControl = enable; m_Controls->configuration_finished_label->setVisible(enable); m_Controls->m_finishedLine->setVisible(enable); m_Controls->m_resetButton->setVisible(enable); m_Controls->m_finishedButton->setVisible(enable); } void QmitkTrackingDeviceConfigurationWidget::StoreUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; int selectedDevice = m_Controls->m_trackingDeviceChooser->currentIndex(); if ( this->GetPeristenceService() ) // now save the settings using the persistence service { mitk::PropertyList::Pointer propList = this->GetPeristenceService()->GetPropertyList(id); propList->Set("PolarisPortWin",m_Controls->m_portSpinBoxPolaris->value()); propList->Set("AuroraPortWin",m_Controls->m_portSpinBoxAurora->value()); propList->Set("PortTypePolaris", m_Controls->portTypePolaris->currentIndex()); propList->Set("PortTypeAurora", m_Controls->portTypeAurora->currentIndex()); propList->Set("MTCalibrationFile",m_MTCalibrationFile); propList->Set("SelectedDevice",selectedDevice); } else // QSettings as a fallback if the persistence service is not available { QSettings settings; settings.beginGroup(QString::fromStdString(id)); settings.setValue("trackingDeviceChooser", QVariant(selectedDevice)); settings.setValue("portSpinBoxAurora", QVariant(m_Controls->m_portSpinBoxAurora->value())); settings.setValue("portSpinBoxPolaris", QVariant(m_Controls->m_portSpinBoxPolaris->value())); settings.setValue("portTypePolaris", QVariant(m_Controls->portTypePolaris->currentIndex())); settings.setValue("portTypeAurora", QVariant(m_Controls->portTypeAurora->currentIndex())); settings.setValue("mTCalibrationFile", QVariant(QString::fromStdString(m_MTCalibrationFile))); settings.endGroup(); } } void QmitkTrackingDeviceConfigurationWidget::LoadUISettings() { std::string id = "org.mitk.modules.igt.ui.trackingdeviceconfigurationwidget"; int SelectedDevice = 0; if ( this->GetPeristenceService() ) { mitk::PropertyList::Pointer propList = this->GetPeristenceService()->GetPropertyList(id); if (propList.IsNull()) {MITK_ERROR << "Property list for this UI (" << id <<") is not available, could not load UI settings!"; return;} int portPolarisWin,portAuroraWin,portTypePolaris,portTypeAurora; propList->Get("PolarisPortWin",portPolarisWin); propList->Get("AuroraPortWin",portAuroraWin); propList->Get("PortTypePolaris", portTypePolaris); propList->Get("PortTypeAurora", portTypeAurora); propList->Get("MTCalibrationFile",m_MTCalibrationFile); propList->Get("SelectedDevice",SelectedDevice); if (SelectedDevice<0) { MITK_ERROR << "Loaded data from persistence service is invalid (SelectedDevice:" <m_portSpinBoxPolaris->setValue(portPolarisWin); m_Controls->m_portSpinBoxAurora->setValue(portAuroraWin); m_Controls->portTypePolaris->setCurrentIndex(portTypePolaris); m_Controls->portTypeAurora->setCurrentIndex(portTypeAurora); MITK_INFO << "Sucessfully restored UI settings"; } else { // QSettings as a fallback if the persistence service is not available QSettings settings; settings.beginGroup(QString::fromStdString(id)); SelectedDevice = settings.value("trackingDeviceChooser", 0).toInt(); m_Controls->m_portSpinBoxAurora->setValue(settings.value("portSpinBoxAurora", 0).toInt()); m_Controls->m_portSpinBoxPolaris->setValue(settings.value("portSpinBoxPolaris", 0).toInt()); m_Controls->portTypePolaris->setCurrentIndex(settings.value("portTypePolaris", 0).toInt()); m_Controls->portTypeAurora->setCurrentIndex(settings.value("portTypeAurora", 0).toInt()); m_MTCalibrationFile = settings.value("mTCalibrationFile", "").toString().toStdString(); settings.endGroup(); } //the selected device requires some checks because a device that is not installed should not be restored to avoids bugs int selectedDeviceChecked = SelectedDevice; if (SelectedDevice==2 && !mitk::ClaronTrackingDevice::New()->IsDeviceInstalled()) {selectedDeviceChecked = 0;} //0 = Polaris (default) else if (SelectedDevice==3 && !mitk::OptitrackTrackingDevice::New()->IsDeviceInstalled()) {selectedDeviceChecked = 0;} m_Controls->m_TrackingSystemWidget->setCurrentIndex(selectedDeviceChecked); m_Controls->m_trackingDeviceChooser->setCurrentIndex(selectedDeviceChecked); m_Controls->m_MTCalibrationFile->setText("Calibration File: " + QString::fromStdString(m_MTCalibrationFile)); } void QmitkTrackingDeviceConfigurationWidgetConnectionWorker::TestConnectionThreadFunc() { MITK_INFO << "Testing Connection!"; QString output; bool connected = false; mitk::ProgressBar::GetInstance()->AddStepsToDo(4); try { if (!m_TrackingDevice->IsDeviceInstalled()) { output = "ERROR: Device is not installed!"; } else { //test connection and start tracking, generate output output = "
testing connection
..."; m_TrackingDevice->OpenConnection(); output += "OK"; mitk::ProgressBar::GetInstance()->Progress(); //try start/stop tracking output += "
testing tracking
..."; m_TrackingDevice->StartTracking(); mitk::ProgressBar::GetInstance()->Progress(); m_TrackingDevice->StopTracking(); mitk::ProgressBar::GetInstance()->Progress(); //try close connection m_TrackingDevice->CloseConnection(); mitk::ProgressBar::GetInstance()->Progress(); output += "OK"; connected = true; } } catch(mitk::IGTException &e) { output += "ERROR!"; MITK_WARN << "Error while testing connection / start tracking of the device: " << e.GetDescription(); } mitk::ProgressBar::GetInstance()->Progress(4); emit ConnectionTested(connected,output); } void QmitkTrackingDeviceConfigurationWidgetScanPortsWorker::ScanPortsThreadFunc() { int PolarisPort = -1; int AuroraPort = -1; int PortTypePolaris = -1; int PortTypeAurora = -1; QString result = "
Found Devices:"; int resultSize = result.size(); //remember size of result: if it stays the same no device were found #ifdef WIN32 mitk::ProgressBar::GetInstance()->AddStepsToDo(19); QString devName; for (unsigned int i = 1; i < 20; ++i) { QString statusOutput = "Scanning Port #" + QString::number(i); MITK_INFO << statusOutput.toStdString().c_str(); if (i<10) devName = QString("COM%1").arg(i); else devName = QString("\\\\.\\COM%1").arg(i); // prepend "\\.\ to COM ports >9, to be able to allow connection" mitk::TrackingDeviceType scannedPort = ScanPort(devName); switch (scannedPort) { case mitk::NDIPolaris: result += "
" + devName + ": " + "NDI Polaris"; PolarisPort = i; break; case mitk::NDIAurora: result += "
" + devName + ": " + "NDI Aurora"; AuroraPort = i; break; } mitk::ProgressBar::GetInstance()->Progress(); } #else //linux systems for(unsigned int i = 1; i < 6; ++i) { QString devName = QString("/dev/ttyS%1").arg(i); mitk::TrackingDeviceType scannedPort = ScanPort(devName); switch (scannedPort) { case mitk::NDIPolaris: result += "
" + devName + ": " + "NDI Polaris"; PolarisPort = i; PortTypePolaris = 1; break; case mitk::NDIAurora: result += "
" + devName + ": " + "NDI Aurora"; AuroraPort = i; PortTypeAurora = 1; break; } } for(unsigned int i = 0; i <7; ++i) { QString devName = QString("/dev/ttyUSB%1").arg(i); mitk::TrackingDeviceType scannedPort = ScanPort(devName); switch (scannedPort) { case mitk::NDIPolaris: result += "
" + devName + ": " + "NDI Polaris"; PolarisPort = i; PortTypePolaris = 0; break; case mitk::NDIAurora: result += "
" + devName + ": " + "NDI Aurora"; AuroraPort = i; PortTypeAurora = 0; break; } } #endif if ( result.size() == resultSize) result += "
none"; emit PortsScanned(PolarisPort,AuroraPort,result,PortTypePolaris,PortTypeAurora); } mitk::TrackingDeviceType QmitkTrackingDeviceConfigurationWidgetScanPortsWorker::ScanPort(QString port) { mitk::NDITrackingDevice::Pointer tracker = mitk::NDITrackingDevice::New(); tracker->SetDeviceName(port.toStdString()); mitk::TrackingDeviceType returnValue = mitk::TrackingSystemInvalid; try {returnValue = tracker->TestConnection();} catch (mitk::IGTException) {}//do nothing: there is simply no device on this port return returnValue; } void QmitkTrackingDeviceConfigurationWidgetConnectionWorker::SetTrackingDevice(mitk::TrackingDevice::Pointer t) { m_TrackingDevice = t; } diff --git a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui index afec742192..9acbe52590 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui @@ -1,1127 +1,1215 @@ QmitkTrackingDeviceConfigurationWidgetControls 0 0 449 536 0 0 Form 0 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tracking Device Configuration</span></p></body></html> Qt::Horizontal 40 20 Choose tracking device: Qt::Horizontal 128 20 0 0 Polaris Aurora MicronTracker Optitrack VirtualTracker + + + Open IGT Link + + Qt::Horizontal true 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Polaris</span></p></body></html> Com Port: COM Auto Scan Qt::Horizontal 40 20 Port Type: /dev/ttyUSB /dev/ttyS Qt::Horizontal 40 20 Frame Rate: 20 Hz 30 Hz 60 Hz Qt::Horizontal 40 20 0 0 Tracking Mode 6D true false 5D false Qt::Horizontal 62 20 Qt::Vertical QSizePolicy::Expanding 258 13 120 50 120 80 120 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;" bgcolor="#000000"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:7pt; color:#ffffff;">NDI Polaris selected</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:7pt; color:#ffffff;">NDI Polaris selected</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 Test Connection <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Aurora</span></p></body></html> Com Port: COM Auto Scan Qt::Horizontal 40 20 Port Type: /dev/ttyUSB /dev/ttyS Qt::Horizontal 40 20 Qt::Vertical 20 40 120 50 120 80 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;" bgcolor="#000000"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 Test Connection <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">MicronTracker</span></p></body></html> Calibration File: <none> Set Calibration File Qt::Horizontal 40 20 Qt::Horizontal 40 20 Qt::Vertical 20 40 120 50 120 80 120 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;" bgcolor="#000000"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 120 0 test connection 0 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Optitrack</span></p></body></html> Calibration File: <none> Set Calibration File Qt::Horizontal 40 20 Camera Settings: 1 480 50 Exposition 250 200 Threshold 15 15 LED Power Qt::Vertical 20 5 false 120 50 120 80 120 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } -</style></head><body style=" font-family:'Ubuntu'; font-size:11pt; font-weight:400; font-style:normal;" bgcolor="#000000"> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p> -<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-family:'MS Shell Dlg 2'; font-size:8pt;"> </span></p></body></html> +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;" bgcolor="#000000"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline; color:#ffffff;">output:</span><span style=" font-size:8pt;"> </span></p></body></html> Qt::NoTextInteraction 120 0 120 16777215 120 0 test connection 0 0 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Virtual Tracker</span></p></body></html> Qt::Vertical 20 136 + + + + + + + 0 + 0 + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Open IGT Link Connection</span></p></body></html> + + + + + + + + + + + Hostname + + + + + + + 127.0.0.1 + + + + + + + Port + + + + + + + 18944 + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Vertical + + + + 20 + 66 + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"> </p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;"> </span></p> <p align="right" style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt;">Press &quot;Finished&quot; to confirm configuration</span> </p></body></html> Qt::Vertical 20 14 Qt::Horizontal Qt::Horizontal 40 20 Reset Finished 0 Qt::Vertical 20 289 true 0 0 - 64 + 63 26 Qt::Vertical 20 269 16777215 0 Qt::Vertical 20 40 diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.cpp b/Modules/OpenIGTLink/mitkIGTLDevice.cpp index bae5493e69..994e758cf5 100644 --- a/Modules/OpenIGTLink/mitkIGTLDevice.cpp +++ b/Modules/OpenIGTLink/mitkIGTLDevice.cpp @@ -1,485 +1,542 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIGTLDevice.h" +//#include "mitkIGTException.h" //#include "mitkIGTTimeStamp.h" #include #include #include #include #include #include //remove later #include #include static const int SOCKET_SEND_RECEIVE_TIMEOUT_MSEC = 1; typedef itk::MutexLockHolder MutexLockHolder; mitk::IGTLDevice::IGTLDevice() : // m_Data(mitk::DeviceDataUnspecified), m_State(mitk::IGTLDevice::Setup), m_Name("Unspecified Device"), m_StopCommunication(false), + m_Hostname("127.0.0.1"), m_PortNumber(-1), - m_MultiThreader(nullptr), m_ThreadID(0) + m_MultiThreader(nullptr), m_SendThreadID(0), m_ReceiveThreadID(0), m_ConnectThreadID(0) { m_StopCommunicationMutex = itk::FastMutexLock::New(); m_StateMutex = itk::FastMutexLock::New(); // m_LatestMessageMutex = itk::FastMutexLock::New(); - m_CommunicationFinishedMutex = itk::FastMutexLock::New(); + m_SendingFinishedMutex = itk::FastMutexLock::New(); + m_ReceivingFinishedMutex = itk::FastMutexLock::New(); + m_ConnectingFinishedMutex = itk::FastMutexLock::New(); // execution rights are owned by the application thread at the beginning - m_CommunicationFinishedMutex->Lock(); + m_SendingFinishedMutex->Lock(); + m_ReceivingFinishedMutex->Lock(); + m_ConnectingFinishedMutex->Lock(); m_MultiThreader = itk::MultiThreader::New(); // m_Data = mitk::DeviceDataUnspecified; // m_LatestMessage = igtl::MessageBase::New(); m_MessageFactory = mitk::IGTLMessageFactory::New(); m_SendQueue = mitk::IGTLMessageQueue::New(); m_ReceiveQueue = mitk::IGTLMessageQueue::New(); m_CommandQueue = mitk::IGTLMessageQueue::New(); } mitk::IGTLDevice::~IGTLDevice() { /* stop communication and disconnect from igtl device */ if (GetState() == Running) { this->StopCommunication(); } if (GetState() == Ready) { this->CloseConnection(); } /* cleanup tracking thread */ - if ((m_ThreadID != 0) && (m_MultiThreader.IsNotNull())) + if (m_MultiThreader.IsNotNull()) { - m_MultiThreader->TerminateThread(m_ThreadID); + if ((m_SendThreadID != 0)) + { + m_MultiThreader->TerminateThread(m_SendThreadID); + } + if ((m_ReceiveThreadID != 0)) + { + m_MultiThreader->TerminateThread(m_ReceiveThreadID); + } + if ((m_ConnectThreadID != 0)) + { + m_MultiThreader->TerminateThread(m_ConnectThreadID); + } } m_MultiThreader = nullptr; } mitk::IGTLDevice::IGTLDeviceState mitk::IGTLDevice::GetState() const { MutexLockHolder lock(*m_StateMutex); return m_State; } void mitk::IGTLDevice::SetState( IGTLDeviceState state ) { itkDebugMacro("setting m_State to " << state); m_StateMutex->Lock(); // MutexLockHolder lock(*m_StateMutex); // lock and unlock the mutex if (m_State == state) { m_StateMutex->Unlock(); return; } m_State = state; m_StateMutex->Unlock(); this->Modified(); } bool mitk::IGTLDevice::TestConnection() { return true; } unsigned int mitk::IGTLDevice::ReceivePrivate(igtl::Socket* socket) { // Create a message buffer to receive header igtl::MessageHeader::Pointer headerMsg; headerMsg = igtl::MessageHeader::New(); // Initialize receive buffer headerMsg->InitPack(); // Receive generic header from the socket int r = - socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(), 1); + socket->Receive(headerMsg->GetPackPointer(), headerMsg->GetPackSize(), 0); if (r == 0) //connection error { // an error was received, therefor the communication with this socket // must be stopped return IGTL_STATUS_NOT_PRESENT; } else if (r == -1 ) //timeout { // a timeout was received, this is no error state, thus, do nothing return IGTL_STATUS_TIME_OUT; } else if (r == headerMsg->GetPackSize()) { // Deserialize the header and check the CRC int crcCheck = headerMsg->Unpack(1); if (crcCheck & igtl::MessageHeader::UNPACK_HEADER) { // Allocate a time stamp igtl::TimeStamp::Pointer ts; ts = igtl::TimeStamp::New(); // Get time stamp igtlUint32 sec; igtlUint32 nanosec; headerMsg->GetTimeStamp(ts); ts->GetTimeStamp(&sec, &nanosec); // std::cerr << "Time stamp: " // << sec << "." // << nanosec << std::endl; // std::cerr << "Dev type and name: " << headerMsg->GetDeviceType() << " " // << headerMsg->GetDeviceName() << std::endl; // headerMsg->Print(std::cout); //check the type of the received message //if it is a GET_, STP_ or RTS_ command push it into the command queue //otherwise continue reading the whole message from the socket const char* curDevType = headerMsg->GetDeviceType(); if ( std::strstr( curDevType, "GET_" ) != nullptr || std::strstr( curDevType, "STP_" ) != nullptr || std::strstr( curDevType, "RTS_" ) != nullptr) { this->m_CommandQueue->PushMessage(headerMsg); this->InvokeEvent(CommandReceivedEvent()); return IGTL_STATUS_OK; } //Create a message according to the header message igtl::MessageBase::Pointer curMessage; curMessage = m_MessageFactory->CreateInstance(headerMsg); //check if the curMessage is created properly, if not the message type is //not supported and the message has to be skipped if ( curMessage.IsNull() ) { socket->Skip(headerMsg->GetBodySizeToRead(), 0); MITK_ERROR("IGTLDevice") << "The received type is not supported. Please " "add it to the message factory."; return IGTL_STATUS_NOT_FOUND; } //insert the header to the message and allocate the pack curMessage->SetMessageHeader(headerMsg); curMessage->AllocatePack(); // Receive transform data from the socket int receiveCheck = 0; receiveCheck = socket->Receive(curMessage->GetPackBodyPointer(), - curMessage->GetPackBodySize()); + curMessage->GetPackBodySize(), 0); if ( receiveCheck > 0 ) { int c = curMessage->Unpack(1); if ( !(c & igtl::MessageHeader::UNPACK_BODY) ) { // mitkThrow() << "crc error"; return IGTL_STATUS_CHECKSUM_ERROR; } //check the type of the received message //if it is a command push it into the command queue //otherwise into the normal receive queue //STP_ commands are handled here because they implemented additional //member variables that are not stored in the header message if ( std::strstr( curDevType, "STT_" ) != nullptr ) { this->m_CommandQueue->PushMessage(curMessage); this->InvokeEvent(CommandReceivedEvent()); } else { this->m_ReceiveQueue->PushMessage(curMessage); this->InvokeEvent(MessageReceivedEvent()); } return IGTL_STATUS_OK; } else { MITK_ERROR("IGTLDevice") << "Received a valid header but could not " << "read the whole message."; return IGTL_STATUS_UNKNOWN_ERROR; } } else { //CRC check failed return IGTL_STATUS_CHECKSUM_ERROR; } } else { //Message size information and actual data size don't match. //this state is not suppossed to be reached, return unknown error return IGTL_STATUS_UNKNOWN_ERROR; } } void mitk::IGTLDevice::SendMessage(const mitk::IGTLMessage* msg) { this->SendMessage(msg->GetMessage()); } void mitk::IGTLDevice::SendMessage(igtl::MessageBase::Pointer msg) { //add the message to the queue m_SendQueue->PushMessage(msg); } unsigned int mitk::IGTLDevice::SendMessagePrivate(igtl::MessageBase::Pointer msg, igtl::Socket::Pointer socket) { //check the input message if ( msg.IsNull() ) { MITK_ERROR("IGTLDevice") << "Could not send message because message is not " "valid. Please check."; return false; } // add the name of this device to the message msg->SetDeviceName(this->GetName().c_str()); // Pack (serialize) and send msg->Pack(); int sendSuccess = socket->Send(msg->GetPackPointer(), msg->GetPackSize()); if (sendSuccess) - return IGTL_STATUS_OK; + { + this->InvokeEvent(MessageSentEvent()); + return IGTL_STATUS_OK; + } else - return IGTL_STATUS_UNKNOWN_ERROR; + { + return IGTL_STATUS_UNKNOWN_ERROR; + } } -void mitk::IGTLDevice::RunCommunication() +void mitk::IGTLDevice::RunCommunication(void (IGTLDevice::*ComFunction)(void), itk::FastMutexLock* mutex) { if (this->GetState() != Running) return; - // keep lock until end of scope - MutexLockHolder communicationFinishedLockHolder(*m_CommunicationFinishedMutex); - - // Because m_StopCommunication is used by two threads, access has to be guarded - // by a mutex. To minimize thread locking, a local copy is used here - bool localStopCommunication; - - // update the local copy of m_StopCommunication - this->m_StopCommunicationMutex->Lock(); - localStopCommunication = this->m_StopCommunication; - this->m_StopCommunicationMutex->Unlock(); - while ((this->GetState() == Running) && (localStopCommunication == false)) + try { - // Check if other igtl devices want to connect with this one. This method - // is overwritten for igtl servers but is doing nothing in case of a igtl - // client - this->Connect(); - - // Check if there is something to receive and store it in the message queue - this->Receive(); - - // Check if there is something to send - this->Send(); - - /* Update the local copy of m_StopCommunication */ - this->m_StopCommunicationMutex->Lock(); - localStopCommunication = m_StopCommunication; - this->m_StopCommunicationMutex->Unlock(); - - // time to relax -// itksys::SystemTools::Delay(1); + // keep lock until end of scope + MutexLockHolder communicationFinishedLockHolder(*mutex); + + // Because m_StopCommunication is used by two threads, access has to be guarded + // by a mutex. To minimize thread locking, a local copy is used here + bool localStopCommunication; + + // update the local copy of m_StopCommunication + this->m_StopCommunicationMutex->Lock(); + localStopCommunication = this->m_StopCommunication; + this->m_StopCommunicationMutex->Unlock(); + while ((this->GetState() == Running) && (localStopCommunication == false)) + { + (this->*ComFunction)(); + + /* Update the local copy of m_StopCommunication */ + this->m_StopCommunicationMutex->Lock(); + localStopCommunication = m_StopCommunication; + this->m_StopCommunicationMutex->Unlock(); + + // time to relax + itksys::SystemTools::Delay(1); + } + } + catch (...) + { + mutex->Unlock(); + this->StopCommunication(); + MITK_ERROR("IGTLDevice::RunCommunication") << "Error while communicating. Thread stopped."; + //mitkThrowException(mitk::IGTException) << "Error while communicating. Thread stopped."; } // StopCommunication was called, thus the mode should be changed back to Ready now // that the tracking loop has ended. - this->SetState(Ready); + //this->SetState(Ready); //this is done elsewhere MITK_DEBUG("IGTLDevice::RunCommunication") << "Reached end of communication."; // returning from this function (and ThreadStartCommunication()) // this will end the thread return; } bool mitk::IGTLDevice::StartCommunication() { if (this->GetState() != Ready) return false; // go to mode Running this->SetState(Running); // set a timeout for the sending and receiving this->m_Socket->SetTimeout(SOCKET_SEND_RECEIVE_TIMEOUT_MSEC); // update the local copy of m_StopCommunication this->m_StopCommunicationMutex->Lock(); this->m_StopCommunication = false; this->m_StopCommunicationMutex->Unlock(); // transfer the execution rights to tracking thread - m_CommunicationFinishedMutex->Unlock(); - - // start a new thread that executes the communication - m_ThreadID = - m_MultiThreader->SpawnThread(this->ThreadStartCommunication, this); + m_SendingFinishedMutex->Unlock(); + m_ReceivingFinishedMutex->Unlock(); + m_ConnectingFinishedMutex->Unlock(); + + // start new threads that execute the communication + m_SendThreadID = + m_MultiThreader->SpawnThread(this->ThreadStartSending, this); + m_ReceiveThreadID = + m_MultiThreader->SpawnThread(this->ThreadStartReceiving, this); + m_ConnectThreadID = + m_MultiThreader->SpawnThread(this->ThreadStartConnecting, this); // mitk::IGTTimeStamp::GetInstance()->Start(this); return true; } bool mitk::IGTLDevice::StopCommunication() { if (this->GetState() == Running) // Only if the object is in the correct state { // m_StopCommunication is used by two threads, so we have to ensure correct // thread handling m_StopCommunicationMutex->Lock(); m_StopCommunication = true; m_StopCommunicationMutex->Unlock(); // we have to wait here that the other thread recognizes the STOP-command // and executes it - m_CommunicationFinishedMutex->Lock(); + m_SendingFinishedMutex->Lock(); + m_ReceivingFinishedMutex->Lock(); + m_ConnectingFinishedMutex->Lock(); // mitk::IGTTimeStamp::GetInstance()->Stop(this); // notify realtime clock // StopCommunication was called, thus the mode should be changed back // to Ready now that the tracking loop has ended. this->SetState(Ready); } return true; } bool mitk::IGTLDevice::CloseConnection() { if (this->GetState() == Setup) { return true; } else if (this->GetState() == Running) { this->StopCommunication(); } m_Socket->CloseSocket(); /* return to setup mode */ this->SetState(Setup); // this->InvokeEvent(mitk::LostConnectionEvent()); return true; } bool mitk::IGTLDevice::SendRTSMessage(const char* type) { //construct the device type for the return message, it starts with RTS_ and //continues with the requested type std::string returnType("RTS_"); returnType.append(type); //create a return message igtl::MessageBase::Pointer rtsMsg = this->m_MessageFactory->CreateInstance(returnType); //if retMsg is NULL there is no return message defined and thus it is not //necessary to send one back if ( rtsMsg.IsNotNull() ) { this->SendMessage(rtsMsg); return true; } else { return false; } } void mitk::IGTLDevice::Connect() { } igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextMessage() { //copy the next message into the given msg igtl::MessageBase::Pointer msg = this->m_ReceiveQueue->PullMessage(); return msg; } igtl::MessageBase::Pointer mitk::IGTLDevice::GetNextCommand() { //copy the next command into the given msg igtl::MessageBase::Pointer msg = this->m_CommandQueue->PullMessage(); return msg; } void mitk::IGTLDevice::EnableInfiniteBufferingMode( mitk::IGTLMessageQueue::Pointer queue, bool enable) { queue->EnableInfiniteBuffering(enable); } -//std::string mitk::IGTLDevice::GetNextMessageInformation() -//{ -// return this->m_ReceiveQueue->GetNextMsgInformationString(); -//} - -//std::string mitk::IGTLDevice::GetNextMessageDeviceType() -//{ -// return this->m_ReceiveQueue->GetNextMsgDeviceType(); -//} - -//std::string mitk::IGTLDevice::GetNextCommandInformation() -//{ -// return this->m_CommandQueue->GetNextMsgInformationString(); -//} +ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartSending(void* pInfoStruct) +{ + /* extract this pointer from Thread Info structure */ + struct itk::MultiThreader::ThreadInfoStruct * pInfo = + (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; + if (pInfo == nullptr) + { + return ITK_THREAD_RETURN_VALUE; + } + if (pInfo->UserData == nullptr) + { + return ITK_THREAD_RETURN_VALUE; + } + IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; + if (igtlDevice != nullptr) + { + igtlDevice->RunCommunication(&mitk::IGTLDevice::Send, igtlDevice->m_SendingFinishedMutex); + } + igtlDevice->m_SendThreadID = 0; // erase thread id because thread will end. + return ITK_THREAD_RETURN_VALUE; +} -//std::string mitk::IGTLDevice::GetNextCommandDeviceType() -//{ -// return this->m_CommandQueue->GetNextMsgDeviceType(); -//} +ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartReceiving(void* pInfoStruct) +{ + /* extract this pointer from Thread Info structure */ + struct itk::MultiThreader::ThreadInfoStruct * pInfo = + (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; + if (pInfo == nullptr) + { + return ITK_THREAD_RETURN_VALUE; + } + if (pInfo->UserData == nullptr) + { + return ITK_THREAD_RETURN_VALUE; + } + IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; + if (igtlDevice != nullptr) + { + igtlDevice->RunCommunication(&mitk::IGTLDevice::Receive, + igtlDevice->m_ReceivingFinishedMutex); + } + igtlDevice->m_ReceiveThreadID = 0; // erase thread id because thread will end. + return ITK_THREAD_RETURN_VALUE; +} -ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartCommunication(void* pInfoStruct) +ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartConnecting(void* pInfoStruct) { - /* extract this pointer from Thread Info structure */ - struct itk::MultiThreader::ThreadInfoStruct * pInfo = - (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; - if (pInfo == nullptr) - { - return ITK_THREAD_RETURN_VALUE; - } - if (pInfo->UserData == nullptr) - { - return ITK_THREAD_RETURN_VALUE; - } - IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; - if (igtlDevice != nullptr) - { - igtlDevice->RunCommunication(); - } - igtlDevice->m_ThreadID = 0; // erase thread id because thread will end. - return ITK_THREAD_RETURN_VALUE; + /* extract this pointer from Thread Info structure */ + struct itk::MultiThreader::ThreadInfoStruct * pInfo = + (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; + if (pInfo == nullptr) + { + return ITK_THREAD_RETURN_VALUE; + } + if (pInfo->UserData == nullptr) + { + return ITK_THREAD_RETURN_VALUE; + } + IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; + if (igtlDevice != nullptr) + { + igtlDevice->RunCommunication(&mitk::IGTLDevice::Connect, + igtlDevice->m_ConnectingFinishedMutex); + } + igtlDevice->m_ConnectThreadID = 0; // erase thread id because thread will end. + return ITK_THREAD_RETURN_VALUE; } diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.h b/Modules/OpenIGTLink/mitkIGTLDevice.h index b98cbea86b..4e3b4c394e 100644 --- a/Modules/OpenIGTLink/mitkIGTLDevice.h +++ b/Modules/OpenIGTLink/mitkIGTLDevice.h @@ -1,384 +1,414 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef MITKIGTLDEVICE_H #define MITKIGTLDEVICE_H #include "mitkCommon.h" //itk #include "itkObject.h" #include "itkFastMutexLock.h" #include "itkMultiThreader.h" //igtl #include "igtlSocket.h" #include "igtlMessageBase.h" #include "igtlTransformMessage.h" //mitkIGTL #include "MitkOpenIGTLinkExports.h" #include "mitkIGTLMessageFactory.h" #include "mitkIGTLMessageQueue.h" #include "mitkIGTLMessage.h" namespace mitk { /** * \brief Interface for all OpenIGTLink Devices * * Defines the methods that are common for all devices using OpenIGTLink. It * can open/close a connection, start/stop a communication and send/receive * messages. * * It uses message queues to store the incoming and outgoing mails. They are * configurable, you can set buffering on and off. * * The device is in one of three different states: Setup, Ready or Running. * Setup is the initial state. From this state on you can call * OpenConnection() and arrive in the Ready state. From the Ready state you * call StartCommunication() to arrive in the Running state. Now the device * is continuosly checking for new connections, receiving messages and * sending messages. This runs in a seperate thread. To stop the communication * call StopCommunication() (to arrive in Ready state) or CloseConnection() * (to arrive in the Setup state). * * \ingroup OpenIGTLink * */ class MITKOPENIGTLINK_EXPORT IGTLDevice : public itk::Object { public: mitkClassMacroItkParent(IGTLDevice, itk::Object) /** * \brief Type for state variable. * The IGTLDevice is always in one of these states. * */ enum IGTLDeviceState {Setup, Ready, Running}; /** * \brief Opens a connection to the device * * This may only be called if there is currently no connection to the * device. If OpenConnection() is successful, the object will change from * Setup state to Ready state. */ virtual bool OpenConnection() = 0; /** * \brief Closes the connection to the device * * This may only be called if there is currently a connection to the * device, but device is not running (e.g. object is in Ready state) */ virtual bool CloseConnection(); /** * \brief Stops the communication between the two devices * * This may only be called if the device is in Running state. */ virtual bool StopCommunication(); /** * \brief Starts the communication between the two devices * * This may only be called if the device is in Ready state. */ bool StartCommunication(); /** - * \brief Continuously checks for new connections, receives messages and - * sends messages. + * \brief Continuously calls the given function * * This may only be called if the device is in Running state and only from * a seperate thread. + * + * \param ComFunction function pointer that specifies the method to be executed + * \param mutex the mutex that corresponds to the function pointer */ - void RunCommunication(); + void RunCommunication(void (IGTLDevice::*ComFunction)(void), itk::FastMutexLock* mutex); /** * \brief Adds the given message to the sending queue * * This may only be called after the connection to the device has been * established with a call to OpenConnection(). Note that the message * is not send directly. This method just adds it to the send queue. * \param msg The message to be added to the sending queue */ void SendMessage(igtl::MessageBase::Pointer msg); /** * \brief Adds the given message to the sending queue * * Convenience function to work with mitk::IGTLMessage directly. * \param msg The message to be added to the sending queue */ void SendMessage(const IGTLMessage* msg); /** * \brief Returns current object state (Setup, Ready or Running) */ IGTLDeviceState GetState() const; /** * \brief Returns the oldest message in the command queue * \return The oldest message from the command queue. */ igtl::MessageBase::Pointer GetNextCommand(); /** * \brief Returns the oldest message in the receive queue * \return The oldest message from the receive queue */ igtl::MessageBase::Pointer GetNextMessage(); /** * \brief Sets the port number of the device */ itkSetMacro(PortNumber,int); /** * \brief Returns the port number of the device */ itkGetMacro(PortNumber,int); /** * \brief Sets the ip/hostname of the device */ itkSetMacro(Hostname,std::string); /** * \brief Returns the ip/hostname of the device */ itkGetMacro(Hostname,std::string); /** * \brief Returns the name of this device */ itkGetConstMacro(Name, std::string); /** * \brief Sets the name of this device */ itkSetMacro(Name, std::string); /** * \brief Returns a const reference to the receive queue */ itkGetConstMacro(ReceiveQueue, mitk::IGTLMessageQueue::Pointer); /** * \brief Returns a const reference to the command queue */ itkGetConstMacro(CommandQueue, mitk::IGTLMessageQueue::Pointer); /** * \brief Returns a const reference to the send queue */ itkGetConstMacro(SendQueue, mitk::IGTLMessageQueue::Pointer); /** * \brief Returns the message factory */ itkGetMacro(MessageFactory, mitk::IGTLMessageFactory::Pointer); /** - * \brief static start method for the tracking thread. - * \param data a void pointer to the IGTLDevice object. - */ - static ITK_THREAD_RETURN_TYPE ThreadStartCommunication(void* data); + * \brief static start method for the sending thread. + * \param data a void pointer to the IGTLDevice object. + */ + static ITK_THREAD_RETURN_TYPE ThreadStartSending(void* data); + + /** + * \brief static start method for the receiving thread. + * \param data a void pointer to the IGTLDevice object. + */ + static ITK_THREAD_RETURN_TYPE ThreadStartReceiving(void* data); + + /** + * \brief static start method for the connection thread. + * \param data a void pointer to the IGTLDevice object. + */ + static ITK_THREAD_RETURN_TYPE ThreadStartConnecting(void* data); /** * \brief TestConnection() tries to connect to a IGTL device on the current * ip and port * * \todo Implement this method. Send a status message and check the answer. * * TestConnection() tries to connect to a IGTL server on the current * ip and port and returns which device it has found. * \return It returns the type of the device that answers. Throws an * exception * if no device is available on that ip/port. * @throw mitk::Exception Throws an exception if there are errors * while connecting to the device. */ virtual bool TestConnection(); /** * \brief Send RTS message of given type */ bool SendRTSMessage(const char* type); /** * \brief Sets the buffering mode of the given queue */ void EnableInfiniteBufferingMode(mitk::IGTLMessageQueue::Pointer queue, bool enable = true); /** * \brief Returns the number of connections of this device */ virtual unsigned int GetNumberOfConnections() = 0; protected: /** * \brief Sends a message. * * This may only be called after the connection to the device has been * established with a call to OpenConnection(). This method uses the given * socket to send the given MessageReceivedEvent * * \param msg the message to be sent * \param socket the socket used to communicate with the other device * * \retval IGTL_STATUS_OK the message was sent * \retval IGTL_STATUS_UNKONWN_ERROR the message was not sent because an * unknown error occurred */ unsigned int SendMessagePrivate(igtl::MessageBase::Pointer msg, igtl::Socket::Pointer socket); /** * \brief Call this method to receive a message. * * The message will be saved in the receive queue. */ virtual void Receive() = 0; /** * \brief Call this method to receive a message from the given device. * * The message will be saved in the receive queue. * * \param device the socket that connects this device with the other one. * * \retval IGTL_STATUS_OK a message or a command was received * \retval IGTL_STATUS_NOT_PRESENT the socket is not connected anymore * \retval IGTL_STATUS_TIME_OUT the socket timed out * \retval IGTL_STATUS_CHECKSUM_ERROR the checksum of the received msg was * incorrect * \retval IGTL_STATUS_UNKNOWN_ERROR an unknown error occurred */ unsigned int ReceivePrivate(igtl::Socket* device); /** * \brief Call this method to send a message. The message will be read from * the queue. */ virtual void Send() = 0; /** * \brief Call this method to check for other devices that want to connect * to this one. * * In case of a client this method is doing nothing. In case of a server it * is checking for other devices and if there is one it establishes a * connection. */ virtual void Connect(); /** * \brief Stops the communication with the given socket * */ virtual void StopCommunicationWithSocket(igtl::Socket* socket) = 0; /** * \brief change object state */ void SetState(IGTLDeviceState state); IGTLDevice(); virtual ~IGTLDevice(); /** current object state (Setup, Ready or Running) */ IGTLDeviceState m_State; /** the name of this device */ std::string m_Name; /** signal used to stop the thread*/ bool m_StopCommunication; /** mutex to control access to m_StopCommunication */ itk::FastMutexLock::Pointer m_StopCommunicationMutex; - /** mutex used to make sure that the thread is just started once */ - itk::FastMutexLock::Pointer m_CommunicationFinishedMutex; + /** mutex used to make sure that the send thread is just started once */ + itk::FastMutexLock::Pointer m_SendingFinishedMutex; + /** mutex used to make sure that the receive thread is just started once */ + itk::FastMutexLock::Pointer m_ReceivingFinishedMutex; + /** mutex used to make sure that the connect thread is just started once */ + itk::FastMutexLock::Pointer m_ConnectingFinishedMutex; /** mutex to control access to m_State */ itk::FastMutexLock::Pointer m_StateMutex; /** the hostname or ip of the device */ std::string m_Hostname; /** the port number of the device */ int m_PortNumber; /** the socket used to communicate with other IGTL devices */ igtl::Socket::Pointer m_Socket; /** The message receive queue */ mitk::IGTLMessageQueue::Pointer m_ReceiveQueue; /** The message send queue */ mitk::IGTLMessageQueue::Pointer m_SendQueue; /** A queue that stores just command messages received by this device */ mitk::IGTLMessageQueue::Pointer m_CommandQueue; /** A message factory that provides the New() method for all msg types */ mitk::IGTLMessageFactory::Pointer m_MessageFactory; private: /** creates worker thread that continuously polls interface for new messages */ itk::MultiThreader::Pointer m_MultiThreader; - /** ID of polling thread */ - int m_ThreadID; + /** ID of sending thread */ + int m_SendThreadID; + /** ID of receiving thread */ + int m_ReceiveThreadID; + /** ID of connecting thread */ + int m_ConnectThreadID; }; /** - * \brief connect to this Event to get noticed when a message was received + * \brief connect to this Event to get notified when a message was successfully sent + * + * \note This event is invoked in the communication thread, therefore do not use it to make + * changes in the GUI!!! Use the QT signal slot system to decouple this call from the com thread + * */ + itkEventMacro( MessageSentEvent , itk::AnyEvent ); + + /** + * \brief connect to this Event to get notified when a message was received * * \note Check if you can invoke this events like this or if you have to make * it thread-safe. They are not invoked in the main thread!!! * */ itkEventMacro( MessageReceivedEvent , itk::AnyEvent ); /** - * \brief connect to this Event to get noticed when a command was received + * \brief connect to this Event to get notified when a command was received * * \note Check if you can invoke this events like this or if you have to make * it thread-safe. They are not invoked in the main thread!!! * */ itkEventMacro( CommandReceivedEvent , itk::AnyEvent ); /** - * \brief connect to this Event to get noticed when another igtl device + * \brief connect to this Event to get notified when another igtl device * connects with this device. * * \note Check if you can invoke this events like this or if you have to make * it thread-safe. They are not invoked in the main thread!!! * */ itkEventMacro( NewClientConnectionEvent , itk::AnyEvent ); /** - * \brief connect to this Event to get noticed when this device looses the + * \brief connect to this Event to get notified when this device looses the * connection to a socket. * * \note Check if you can invoke this events like this or if you have to make * it thread-safe. They are not invoked in the main thread!!! * */ itkEventMacro( LostConnectionEvent , itk::AnyEvent ); } // namespace mitk #endif /* MITKIGTLDEVICE_H */ diff --git a/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp b/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp index 69942a3288..d2a5202b73 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp +++ b/Modules/OpenIGTLink/mitkIGTLMessageProvider.cpp @@ -1,371 +1,374 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIGTLMessageProvider.h" #include "mitkIGTLDevice.h" #include "mitkIGTLMessage.h" #include "mitkIGTLMessageFactory.h" #include "mitkCallbackFromGUIThread.h" //Microservices #include "usServiceReference.h" #include "usModuleContext.h" #include "usServiceEvent.h" #include "mitkServiceInterface.h" #include "usGetModuleContext.h" //igt (remove this later) #include "igtlBindMessage.h" #include "igtlQuaternionTrackingDataMessage.h" #include "igtlTrackingDataMessage.h" #ifndef WIN32 #include #endif mitk::IGTLMessageProvider::IGTLMessageProvider() : mitk::IGTLDeviceSource() { this->SetName("IGTLMessageProvider"); m_MultiThreader = itk::MultiThreader::New(); m_StreamingTimeMutex = itk::FastMutexLock::New(); m_StopStreamingThreadMutex = itk::FastMutexLock::New(); m_ThreadId = 0; m_IsStreaming = false; } mitk::IGTLMessageProvider::~IGTLMessageProvider() { // terminate worker thread on destruction this->m_StopStreamingThreadMutex->Lock(); this->m_StopStreamingThread = true; this->m_StopStreamingThreadMutex->Unlock(); if ( m_ThreadId >= 0) { this->m_MultiThreader->TerminateThread(m_ThreadId); } } void mitk::IGTLMessageProvider::GenerateData() { if (this->m_IGTLDevice.IsNull()) return; for (unsigned int index = 0; index < this->GetNumberOfIndexedInputs(); index++) { const IGTLMessage* msg = this->GetInput(index); - assert(msg); + if (msg == nullptr) + { + continue; + } if ( !msg->IsDataValid() ) { continue; } igtl::MessageBase::Pointer igtlMsg = msg->GetMessage(); if ( igtlMsg.IsNotNull() ) { //send the message this->m_IGTLDevice->SendMessage(igtlMsg); } } } void mitk::IGTLMessageProvider::CreateOutputs() { //if outputs are set then delete them if (this->GetNumberOfOutputs() > 0) { for (int numOP = this->GetNumberOfOutputs() - 1; numOP >= 0; numOP--) this->RemoveOutput(numOP); this->Modified(); } //fill the outputs if a valid OpenIGTLink device is set if (m_IGTLDevice.IsNull()) return; this->SetNumberOfIndexedOutputs(1); if (this->GetOutput(0) == NULL) { DataObjectPointer newOutput = this->MakeOutput(0); this->SetNthOutput(0, newOutput); this->Modified(); } } //void mitk::IGTLMessageProvider::UpdateOutputInformation() //{ // this->Modified(); // make sure that we need to be updated // Superclass::UpdateOutputInformation(); //} void mitk::IGTLMessageProvider::OnIncomingMessage() { } std::string RemoveRequestPrefixes(std::string requestType) { return requestType.substr(4); } void mitk::IGTLMessageProvider::OnIncomingCommand() { //get the next command igtl::MessageBase::Pointer curCommand = this->m_IGTLDevice->GetNextCommand(); //extract the type const char * requestType = curCommand->GetDeviceType(); //check the type std::string reqType(requestType); bool isGetMsg = !reqType.find("GET_"); bool isSTTMsg = !reqType.find("STT_"); bool isSTPMsg = !reqType.find("STP_"); bool isRTSMsg = !reqType.find("RTS_"); //get the type from the request type (remove STT_, STP_, GET_, RTS_) std::string type = RemoveRequestPrefixes(requestType); //check all microservices if there is a fitting source for the requested type mitk::IGTLMessageSource::Pointer source = this->GetFittingSource(type.c_str()); //if there is no fitting source return a RTS message, if there is a RTS //type defined in the message factory send it if ( source.IsNull() ) { if ( !this->GetIGTLDevice()->SendRTSMessage(type.c_str()) ) { //sending RTS message failed, probably because the type is not in the //message factory MITK_WARN("IGTLMessageProvider") << "Tried to send a RTS message but did " "not succeed. Check if this type ( " << type << " ) was added to the message " "factory. "; } } else { if ( isGetMsg ) //if it is a single value push it into sending queue { //first it is necessary to update the source. This needs additional time //but is necessary. But are we really allowed to call this here? In which //thread are we? Is the source thread safe? source->Update(); mitk::IGTLMessage::Pointer sourceOutput = source->GetOutput(); if (sourceOutput.IsNotNull() && sourceOutput->IsDataValid()) { igtl::MessageBase::Pointer sourceMsg = sourceOutput->GetMessage(); if ( source.IsNotNull() ) { this->GetIGTLDevice()->SendMessage(sourceMsg); } } } else if ( isSTTMsg ) { //read the requested frames per second int fps = 10; //read the fps from the command igtl::MessageBase* curCommandPt = curCommand.GetPointer(); if ( std::strcmp( curCommand->GetDeviceType(), "STT_BIND" ) == 0 ) { fps = ((igtl::StartBindMessage*)curCommandPt)->GetResolution(); } else if ( std::strcmp( curCommand->GetDeviceType(), "STT_QTDATA" ) == 0 ) { fps = ((igtl::StartQuaternionTrackingDataMessage*)curCommandPt)->GetResolution(); } else if ( std::strcmp( curCommand->GetDeviceType(), "STT_TDATA" ) == 0 ) { fps = ((igtl::StartTrackingDataMessage*)curCommandPt)->GetResolution(); } this->StartStreamingOfSource(source, fps); } else if ( isSTPMsg ) { this->StopStreamingOfSource(source); } else { //do nothing } } } bool mitk::IGTLMessageProvider::IsStreaming() { return m_IsStreaming; } void mitk::IGTLMessageProvider::StartStreamingOfSource(IGTLMessageSource* src, unsigned int fps) { if ( src == NULL ) return; //so far the provider allows the streaming of a single source only //if the streaming thread is already running return a RTS message if ( !m_IsStreaming ) { //if it is a stream establish a connection between the provider and the //source this->ConnectTo(src); // calculate the streaming time this->m_StreamingTimeMutex->Lock(); this->m_StreamingTime = 1.0 / (double) fps * 1000.0; this->m_StreamingTimeMutex->Unlock(); // Create a command object. The function will be called later from the // main thread this->m_StreamingCommand = ProviderCommand::New(); m_StreamingCommand->SetCallbackFunction(this, &mitk::IGTLMessageProvider::Update); // For streaming we need a continues time signal, since there is no timer // available we start a thread that generates a timing signal // This signal is invoked from the other thread the update of the pipeline // has to be executed from the main thread. Thus, we use the // callbackfromGUIThread class to pass the execution to the main thread this->m_ThreadId = m_MultiThreader->SpawnThread(this->TimerThread, this); this->m_IsStreaming = true; } else { MITK_WARN("IGTLMessageProvider") << "This provider just supports the " "streaming of one source."; } } void mitk::IGTLMessageProvider::StopStreamingOfSource(IGTLMessageSource* src) { //this is something bad!!! The streaming thread has to be stopped before the //source is disconnected otherwise it can cause a crash. This has to be added!! this->DisconnectFrom(src); this->m_StopStreamingThreadMutex->Lock(); this->m_StopStreamingThread = true; this->m_StopStreamingThreadMutex->Unlock(); //does this flag needs a mutex??? this->m_IsStreaming = false; } mitk::IGTLMessageSource::Pointer mitk::IGTLMessageProvider::GetFittingSource(const char* requestedType) { //get the context us::ModuleContext* context = us::GetModuleContext(); //define the interface name std::string interface = mitk::IGTLMessageSource::US_INTERFACE_NAME; //specify a filter that defines the requested type std::string filter = "(" + mitk::IGTLMessageSource::US_PROPKEY_DEVICETYPE + "=" + requestedType + ")"; //find the fitting service std::vector serviceReferences = context->GetServiceReferences(interface, filter); //check if a service reference was found. It is also possible that several //services were found. This is not checked here, just the first one is taken. if ( serviceReferences.size() ) { mitk::IGTLMessageSource::Pointer curSource = context->GetService(serviceReferences.front()); if ( curSource.IsNotNull() ) return curSource; } //no service reference was found or found service reference has no valid source return NULL; } void mitk::IGTLMessageProvider::Send(const mitk::IGTLMessage* msg) { if (msg != NULL) this->m_IGTLDevice->SendMessage(msg); } void mitk::IGTLMessageProvider::ConnectTo( mitk::IGTLMessageSource* UpstreamFilter ) { for (DataObjectPointerArraySizeType i = 0; i < UpstreamFilter->GetNumberOfOutputs(); i++) { this->SetInput(i, UpstreamFilter->GetOutput(i)); } } void mitk::IGTLMessageProvider::DisconnectFrom( mitk::IGTLMessageSource* UpstreamFilter ) { for (DataObjectPointerArraySizeType i = 0; i < UpstreamFilter->GetNumberOfOutputs(); i++) { this->RemoveInput(UpstreamFilter->GetOutput(i)); } } ITK_THREAD_RETURN_TYPE mitk::IGTLMessageProvider::TimerThread(void* pInfoStruct) { // extract this pointer from thread info structure struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; mitk::IGTLMessageProvider* thisObject = static_cast(pInfo->UserData); itk::SimpleMutexLock mutex; mutex.Lock(); thisObject->m_StopStreamingThreadMutex->Lock(); thisObject->m_StopStreamingThread = false; thisObject->m_StopStreamingThreadMutex->Unlock(); thisObject->m_StreamingTimeMutex->Lock(); unsigned int waitingTime = thisObject->m_StreamingTime; thisObject->m_StreamingTimeMutex->Unlock(); while (true) { thisObject->m_StopStreamingThreadMutex->Lock(); bool stopThread = thisObject->m_StopStreamingThread; thisObject->m_StopStreamingThreadMutex->Unlock(); if (stopThread) { break; } //wait for the time given //I know it is not the nicest solution but we just need an approximate time //sleeps for 20 ms #if defined (WIN32) || defined (_WIN32) Sleep(waitingTime); #else usleep(waitingTime * 1000); #endif // Ask to execute that command from the GUI thread mitk::CallbackFromGUIThread::GetInstance()->CallThisFromGUIThread( thisObject->m_StreamingCommand); } thisObject->m_ThreadId = 0; mutex.Unlock(); return ITK_THREAD_RETURN_VALUE; } diff --git a/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp b/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp index 0ff2b4ae5a..50f8f4fc3b 100644 --- a/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp +++ b/Modules/OpenIGTLink/mitkIGTLMessageSource.cpp @@ -1,196 +1,197 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIGTLMessageSource.h" #include "mitkUIDGenerator.h" //Microservices #include #include #include #include const std::string mitk::IGTLMessageSource::US_INTERFACE_NAME = "org.mitk.services.IGTLMessageSource"; const std::string mitk::IGTLMessageSource::US_PROPKEY_DEVICENAME = US_INTERFACE_NAME + ".devicename"; const std::string mitk::IGTLMessageSource::US_PROPKEY_DEVICETYPE = US_INTERFACE_NAME + ".devicetype"; const std::string mitk::IGTLMessageSource::US_PROPKEY_ID = US_INTERFACE_NAME + ".id"; const std::string mitk::IGTLMessageSource::US_PROPKEY_ISACTIVE = US_INTERFACE_NAME + ".isActive"; mitk::IGTLMessageSource::IGTLMessageSource() : itk::ProcessObject(), m_Name("IGTLMessageSource (no defined type)"), m_Type("NONE"), m_StreamingFPS(0) { m_StreamingFPSMutex = itk::FastMutexLock::New(); } mitk::IGTLMessageSource::~IGTLMessageSource() { - this->UnRegisterMicroservice(); + //this->UnRegisterMicroservice(); } mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput() { if (this->GetNumberOfIndexedOutputs() < 1) - return NULL; + return nullptr; return static_cast(this->ProcessObject::GetPrimaryOutput()); } mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput( DataObjectPointerArraySizeType idx) { IGTLMessage* out = dynamic_cast( this->ProcessObject::GetOutput(idx) ); - if ( out == NULL && this->ProcessObject::GetOutput(idx) != NULL ) + if ( out == nullptr && this->ProcessObject::GetOutput(idx) != NULL ) { itkWarningMacro (<< "Unable to convert output number " << idx << " to type " << typeid( IGTLMessage ).name () ); } return out; } mitk::IGTLMessage* mitk::IGTLMessageSource::GetOutput( const std::string& messageName) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::iterator it = outputs.begin(); it != outputs.end(); ++it) { if (messageName == (static_cast(it->GetPointer()))->GetName()) { return static_cast(it->GetPointer()); } } - return NULL; + return nullptr; } itk::ProcessObject::DataObjectPointerArraySizeType mitk::IGTLMessageSource::GetOutputIndex( std::string messageName ) { DataObjectPointerArray outputs = this->GetOutputs(); for (DataObjectPointerArray::size_type i = 0; i < outputs.size(); ++i) { if (messageName == (static_cast(outputs.at(i).GetPointer()))->GetName()) { return i; } } throw std::invalid_argument("output name does not exist"); } void mitk::IGTLMessageSource::RegisterAsMicroservice() { // Get Context us::ModuleContext* context = us::GetModuleContext(); // Define ServiceProps us::ServiceProperties props; mitk::UIDGenerator uidGen = mitk::UIDGenerator ("org.mitk.services.IGTLMessageSource.id_", 16); props[ US_PROPKEY_ID ] = uidGen.GetUID(); props[ US_PROPKEY_DEVICENAME ] = m_Name; props[ US_PROPKEY_DEVICETYPE ] = m_Type; m_ServiceRegistration = context->RegisterService(this, props); } void mitk::IGTLMessageSource::UnRegisterMicroservice() { - if (m_ServiceRegistration != NULL) m_ServiceRegistration.Unregister(); + if (m_ServiceRegistration != nullptr) + m_ServiceRegistration.Unregister(); m_ServiceRegistration = 0; } std::string mitk::IGTLMessageSource::GetMicroserviceID() { us::Any referenceProperty = this->m_ServiceRegistration.GetReference().GetProperty(US_PROPKEY_ID); return referenceProperty.ToString(); } void mitk::IGTLMessageSource::GraftOutput(itk::DataObject *graft) { this->GraftNthOutput(0, graft); } void mitk::IGTLMessageSource::GraftNthOutput(unsigned int idx, itk::DataObject *graft) { if ( idx >= this->GetNumberOfIndexedOutputs() ) { itkExceptionMacro(<<"Requested to graft output " << idx << " but this filter" "only has " << this->GetNumberOfIndexedOutputs() << " Outputs."); } if ( !graft ) { itkExceptionMacro(<<"Requested to graft output with a NULL pointer object" ); } itk::DataObject* output = this->GetOutput(idx); if ( !output ) { itkExceptionMacro(<<"Requested to graft output that is a NULL pointer" ); } // Call Graft on IGTLMessage to copy member data output->Graft( graft ); } itk::DataObject::Pointer mitk::IGTLMessageSource::MakeOutput ( DataObjectPointerArraySizeType /*idx*/ ) { return IGTLMessage::New().GetPointer(); } itk::DataObject::Pointer mitk::IGTLMessageSource::MakeOutput( const DataObjectIdentifierType & name ) { itkDebugMacro("MakeOutput(" << name << ")"); if( this->IsIndexedOutputName(name) ) { return this->MakeOutput( this->MakeIndexFromOutputName(name) ); } return static_cast(IGTLMessage::New().GetPointer()); } mitk::PropertyList::ConstPointer mitk::IGTLMessageSource::GetParameters() const { mitk::PropertyList::Pointer p = mitk::PropertyList::New(); // add properties to p like this: //p->SetProperty("MyFilter_MyParameter", mitk::PropertyDataType::New(m_MyParameter)); return mitk::PropertyList::ConstPointer(p); } void mitk::IGTLMessageSource::SetFPS(unsigned int fps) { this->m_StreamingFPSMutex->Lock(); this->m_StreamingFPS = fps; this->m_StreamingFPSMutex->Unlock(); } unsigned int mitk::IGTLMessageSource::GetFPS() { unsigned int fps = 0; this->m_StreamingFPSMutex->Lock(); fps = this->m_StreamingFPS; this->m_StreamingFPSMutex->Unlock(); return fps; } diff --git a/Modules/OpenIGTLink/mitkIGTLServer.cpp b/Modules/OpenIGTLink/mitkIGTLServer.cpp index 6315d62a08..2978ec7a9d 100644 --- a/Modules/OpenIGTLink/mitkIGTLServer.cpp +++ b/Modules/OpenIGTLink/mitkIGTLServer.cpp @@ -1,194 +1,194 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkIGTLServer.h" #include #include #include #include #include mitk::IGTLServer::IGTLServer() : IGTLDevice() { } mitk::IGTLServer::~IGTLServer() { } bool mitk::IGTLServer::OpenConnection() { if (this->GetState() != Setup) { mitkThrowException(mitk::Exception) << "Can only try to create a server if in setup mode"; return false; } int portNumber = this->GetPortNumber(); if (portNumber == -1 ) { //port number was not correct return false; } //create a new server socket m_Socket = igtl::ServerSocket::New(); //try to create the igtl server int response = dynamic_cast(m_Socket.GetPointer())-> CreateServer(portNumber); //check the response if ( response != 0 ) { mitkThrowException(mitk::Exception) << "The server could not be created. Port: " << portNumber; return false; } // everything is initialized and connected so the communication can be started this->SetState(Ready); return true; } bool mitk::IGTLServer::CloseConnection() { //remove all registered clients SocketListType allRegisteredSockets = m_RegisteredClients; this->StopCommunicationWithSocket(allRegisteredSockets); return mitk::IGTLDevice::CloseConnection(); } void mitk::IGTLServer::Connect() { igtl::Socket::Pointer socket; //check if another igtl device wants to connect to this socket socket = ((igtl::ServerSocket*)(this->m_Socket.GetPointer()))->WaitForConnection(1); //if there is a new connection the socket is not null if ( socket.IsNotNull() ) { //add the new client socket to the list of registered clients this->m_RegisteredClients.push_back(socket); //inform observers about this new client this->InvokeEvent(NewClientConnectionEvent()); MITK_INFO("IGTLServer") << "Connected to a new client."; } } void mitk::IGTLServer::Receive() { unsigned int status = IGTL_STATUS_OK; SocketListType socketsToBeRemoved; //the server can be connected with several clients, therefore it has to check //all registered clients SocketListIteratorType it; auto it_end = this->m_RegisteredClients.end(); for ( it = this->m_RegisteredClients.begin(); it != it_end; ++it ) { //it is possible that ReceivePrivate detects that the current socket is //already disconnected. Therefore, it is necessary to remove this socket //from the registered clients list status = this->ReceivePrivate(*it); - if ( status == IGTL_STATUS_NOT_PRESENT ) + if (status == IGTL_STATUS_NOT_PRESENT) { //remember this socket for later, it is not a good idea to remove it - //from the list directly because we iterator over the list at this point + //from the list directly because we iterate over the list at this point socketsToBeRemoved.push_back(*it); MITK_WARN("IGTLServer") << "Lost connection to a client socket. "; } } if ( socketsToBeRemoved.size() > 0 ) { //remove the sockets that are not connected anymore this->StopCommunicationWithSocket(socketsToBeRemoved); //inform observers about loosing the connection to these sockets this->InvokeEvent(LostConnectionEvent()); } } void mitk::IGTLServer::Send() { igtl::MessageBase::Pointer curMessage; //get the latest message from the queue curMessage = this->m_SendQueue->PullMessage(); // there is no message => return if ( curMessage.IsNull() ) return; //the server can be connected with several clients, therefore it has to check //all registered clients //sending a message to all registered clients might not be the best solution, //it could be better to store the client together with the requested type. Then //the data would be send to the appropriate client and to noone else. //(I know it is no excuse but PLUS is doing exactly the same, they broadcast //everything) SocketListIteratorType it; auto it_end = this->m_RegisteredClients.end(); for ( it = this->m_RegisteredClients.begin(); it != it_end; ++it ) { //maybe there should be a check here if the current socket is still active this->SendMessagePrivate(curMessage.GetPointer(), *it); } } void mitk::IGTLServer::StopCommunicationWithSocket( SocketListType& toBeRemovedSockets) { auto it = toBeRemovedSockets.begin(); auto itEnd = toBeRemovedSockets.end(); for (; it != itEnd; ++it ) { this->StopCommunicationWithSocket(*it); } } void mitk::IGTLServer::StopCommunicationWithSocket(igtl::Socket* client) { auto it = this->m_RegisteredClients.begin(); auto itEnd = this->m_RegisteredClients.end(); for (; it != itEnd; ++it ) { if ( (*it) == client ) { //close the socket (*it)->CloseSocket(); //and remove it from the list this->m_RegisteredClients.remove(*it); break; } } MITK_INFO("IGTLServer") << "Removed client socket from server client list."; } unsigned int mitk::IGTLServer::GetNumberOfConnections() { return this->m_RegisteredClients.size(); } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp index 74e8505e67..7bd7536c4e 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.cpp @@ -1,282 +1,293 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTLDeviceCommandWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //igtl #include #include #include #include //poco headers #include const std::string QmitkIGTLDeviceCommandWidget::VIEW_ID = "org.mitk.views.igtldevicesourcemanagementwidget"; QmitkIGTLDeviceCommandWidget::QmitkIGTLDeviceCommandWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_IsClient(false) { m_Controls = NULL; this->m_IGTLDevice = NULL; CreateQtPartControl(this); } QmitkIGTLDeviceCommandWidget::~QmitkIGTLDeviceCommandWidget() { + this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); } void QmitkIGTLDeviceCommandWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLDeviceCommandWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } //connect slots with signals CreateConnections(); } void QmitkIGTLDeviceCommandWidget::CreateConnections() { if (m_Controls) { // connect the widget items with the methods connect( m_Controls->butSendCommand, SIGNAL(clicked()), this, SLOT(OnSendCommand())); connect( m_Controls->commandsComboBox, SIGNAL(currentIndexChanged(const QString &)), this, SLOT(OnCommandChanged(const QString &))); } + //this is used for thread seperation, otherwise the worker thread would change the ui elements + //which would cause an exception + connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState())); } void QmitkIGTLDeviceCommandWidget::OnDeviceStateChanged() { - this->AdaptGUIToState(); + //this->AdaptGUIToState(); + emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceCommandWidget::AdaptGUIToState() { if (this->m_IGTLDevice.IsNotNull()) { //check the state of the device mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState(); switch (state) { case mitk::IGTLDevice::Setup: this->m_Controls->commandsComboBox->setEnabled(false); this->m_Controls->butSendCommand->setEnabled(false); this->m_Controls->fpsSpinBox->setEnabled(false); break; case mitk::IGTLDevice::Ready: this->m_Controls->commandsComboBox->setEnabled(true); this->m_Controls->butSendCommand->setEnabled(true); this->m_Controls->fpsSpinBox->setEnabled(false); break; case mitk::IGTLDevice::Running: if ( this->m_IGTLDevice->GetNumberOfConnections() == 0 ) { //just a server can run and have 0 connections this->m_Controls->butSendCommand->setEnabled(false); this->m_Controls->fpsSpinBox->setEnabled(false); this->m_Controls->commandsComboBox->setEnabled(false); } else { this->m_Controls->commandsComboBox->setEnabled(true); this->m_Controls->butSendCommand->setEnabled(true); // this->m_Controls->fpsSpinBox->setEnabled(true); } break; default: mitkThrow() << "Invalid Device State"; break; } } else { this->DisableSourceControls(); } } void QmitkIGTLDeviceCommandWidget::Initialize(mitk::IGTLDevice::Pointer device) { //reset the GUI DisableSourceControls(); //reset the observers if ( this->m_IGTLDevice.IsNotNull() ) { this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); } if(device.IsNotNull()) { //get the device this->m_IGTLDevice = device; //check if the device is a server or a client if ( dynamic_cast( this->m_IGTLDevice.GetPointer()) == NULL ) { m_IsClient = false; } else { m_IsClient = true; } typedef itk::SimpleMemberCommand< QmitkIGTLDeviceCommandWidget > CurCommandType; // CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); // messageReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLDeviceCommandWidget::OnMessageReceived ); // this->m_MessageReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); // CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); // commandReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLDeviceCommandWidget::OnCommandReceived ); // this->m_CommandReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); connectionLostCommand->SetCallbackFunction( this, &QmitkIGTLDeviceCommandWidget::OnLostConnection ); this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::LostConnectionEvent(), connectionLostCommand); CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); newConnectionCommand->SetCallbackFunction( this, &QmitkIGTLDeviceCommandWidget::OnNewConnection ); this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::NewClientConnectionEvent(), newConnectionCommand); CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); stateModifiedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceCommandWidget::OnDeviceStateChanged ); this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( itk::ModifiedEvent(), stateModifiedCommand); //Fill the commands combo box with all available commands FillCommandsComboBox(); } else { m_IGTLDevice = NULL; } this->AdaptGUIToState(); } void QmitkIGTLDeviceCommandWidget::DisableSourceControls() { this->m_Controls->commandsComboBox->setEnabled(false); this->m_Controls->butSendCommand->setEnabled(false); this->m_Controls->fpsSpinBox->setEnabled(false); } void QmitkIGTLDeviceCommandWidget::OnSendCommand() { //Set the frames per second of the current command in case of a STT_ command if ( std::strcmp( m_CurrentCommand->GetDeviceType(), "STT_BIND" ) == 0 ) { ((igtl::StartBindMessage*)this->m_CurrentCommand.GetPointer())-> SetResolution(this->m_Controls->fpsSpinBox->value()); } else if ( std::strcmp( m_CurrentCommand->GetDeviceType(), "STT_QTDATA" ) == 0 ) { ((igtl::StartQuaternionTrackingDataMessage*)m_CurrentCommand.GetPointer())-> SetResolution(this->m_Controls->fpsSpinBox->value()); } else if ( std::strcmp( m_CurrentCommand->GetDeviceType(), "STT_TDATA" ) == 0 ) { ((igtl::StartTrackingDataMessage*)this->m_CurrentCommand.GetPointer())-> SetResolution(this->m_Controls->fpsSpinBox->value()); } m_IGTLDevice->SendMessage(m_CurrentCommand.GetPointer()); } void QmitkIGTLDeviceCommandWidget::OnCommandChanged( const QString & curCommand) { if ( curCommand.isEmpty() ) return; mitk::IGTLMessageFactory::Pointer msgFactory = this->m_IGTLDevice->GetMessageFactory(); //create a new message that fits to the selected get message type command this->m_CurrentCommand = msgFactory->CreateInstance( curCommand.toStdString()); //enable/disable the FPS spinbox this->m_Controls->fpsSpinBox->setEnabled(curCommand.contains("STT_")); } void QmitkIGTLDeviceCommandWidget::OnLostConnection() { //get the IGTL device that invoked this event // mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - this->AdaptGUIToState(); + //this->AdaptGUIToState(); + emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceCommandWidget::OnNewConnection() { - this->AdaptGUIToState(); + //this->AdaptGUIToState(); + emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceCommandWidget::FillCommandsComboBox() { //load the msg factory from the client (maybe this will be moved later on) mitk::IGTLMessageFactory::Pointer msgFactory = this->m_IGTLDevice->GetMessageFactory(); //get the available commands as std::list std::list commandsList_ = msgFactory->GetAvailableMessageRequestTypes(); //create a string list to convert the std::list this->m_Controls->commandsComboBox->clear(); while ( commandsList_.size() ) { //fill the combo box with life this->m_Controls->commandsComboBox->addItem( QString::fromStdString(commandsList_.front())); commandsList_.pop_front(); } } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.h index 6327c6e75a..c4cb93c233 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.h +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceCommandWidget.h @@ -1,132 +1,139 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKIGTLDeviceCommandWIDGET_H #define QMITKIGTLDeviceCommandWIDGET_H //QT headers #include #include //mitk headers #include "MitkOpenIGTLinkUIExports.h" #include "mitkIGTLDeviceSource.h" #include "mitkIGTLClient.h" #include "mitkDataStorage.h" //itk #include //ui header #include "ui_QmitkIGTLDeviceCommandWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to send OpenIGTLink commands. * * * \ingroup OpenIGTLinkUI */ class MITKOPENIGTLINKUI_EXPORT QmitkIGTLDeviceCommandWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** * \brief Initializes the widget with the given device. * * The old device is * dropped, so be careful, if the source is not saved somewhere else it might * be lost. You might want to ask the user if he wants to save the changes * before calling this method. * \param device The widget will be initialized corresponding to the state of * this device. */ void Initialize(mitk::IGTLDevice::Pointer device); QmitkIGTLDeviceCommandWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkIGTLDeviceCommandWidget(); - /** - * \brief Is called when the current device received a message - */ - void OnMessageReceived(); - /** - * \brief Is called when the current device received a command - */ - void OnCommandReceived(); + protected slots: + void OnCommandChanged(const QString& curCommand); + + void OnSendCommand(); + + ///** + //* \brief Is called when the current device received a message + //*/ + //void OnMessageReceived(); + + ///** + //* \brief Is called when the current device received a command + //*/ + //void OnCommandReceived(); /** - * \brief Is called when the current device lost a connection to one of its - * sockets + * \brief Is called when the current device lost a connection to one of its + * sockets */ void OnLostConnection(); /** - * \brief Is called when the current device connected to another device + * \brief Is called when the current device connected to another device */ void OnNewConnection(); + /** + * \brief Adapts the GUI to the state of the device + */ + void AdaptGUIToState(); - protected slots: - void OnCommandChanged(const QString& curCommand); - - void OnSendCommand(); + signals: + /** + * \brief used for thread seperation, the worker thread must not call AdaptGUIToState directly + * QT signals are thread safe and seperate the threads + */ + void AdaptGUIToStateSignal(); protected: - /** - * \brief Adapts the GUI to the state of the device - */ - void AdaptGUIToState(); - /** * \brief Calls AdaptGUIToState() */ void OnDeviceStateChanged(); /// \brief Fills the commands combo box with available commands void FillCommandsComboBox(); /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkIGTLDeviceCommandWidgetControls* m_Controls; /** @brief holds the OpenIGTLink device */ mitk::IGTLDevice::Pointer m_IGTLDevice; igtl::MessageBase::Pointer m_CurrentCommand; /** @brief flag to indicate if the IGTL device is a client or a server */ bool m_IsClient; unsigned long m_MessageReceivedObserverTag; unsigned long m_CommandReceivedObserverTag; unsigned long m_LostConnectionObserverTag; unsigned long m_NewConnectionObserverTag; unsigned long m_StateModifiedObserverTag; //############## private help methods ####################### void DisableSourceControls(); void EnableSourceControls(); }; #endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp index e5c130a026..396383bbbc 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.cpp @@ -1,363 +1,370 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTLDeviceSetupConnectionWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //igtl #include #include #include #include //poco headers #include const std::string QmitkIGTLDeviceSetupConnectionWidget::VIEW_ID = "org.mitk.views.igtldevicesetupconnectionwidget"; QmitkIGTLDeviceSetupConnectionWidget::QmitkIGTLDeviceSetupConnectionWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_IsClient(false) { m_Controls = NULL; this->m_IGTLDevice = NULL; CreateQtPartControl(this); } QmitkIGTLDeviceSetupConnectionWidget::~QmitkIGTLDeviceSetupConnectionWidget() { + this->RemoveObserver(); +} + +void QmitkIGTLDeviceSetupConnectionWidget::RemoveObserver() +{ + if (this->m_IGTLDevice.IsNotNull()) + { + this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_MessageSentObserverTag); + this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); + } } void QmitkIGTLDeviceSetupConnectionWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLDeviceSetupConnectionWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } // set the validator for the ip edit box (values must be between 0 and 255 and // there are four of them, seperated with a point QRegExpValidator *v = new QRegExpValidator(this); QRegExp rx("((1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})\\.){3,3}(1{0,1}[0-9]{0,2}|2[0-4]{1,1}[0-9]{1,1}|25[0-5]{1,1})"); v->setRegExp(rx); m_Controls->editIP->setValidator(v); // set the validator for the port edit box (values must be between 1 and 65535) m_Controls->editPort->setValidator(new QIntValidator(1, 65535, this)); //connect slots with signals CreateConnections(); } void QmitkIGTLDeviceSetupConnectionWidget::CreateConnections() { if (m_Controls) { // connect the widget items with the methods connect( m_Controls->butConnect, SIGNAL(clicked()), this, SLOT(OnConnect())); connect( m_Controls->editPort, SIGNAL(editingFinished()), this, SLOT(OnPortChanged()) ); connect( m_Controls->editIP, SIGNAL(editingFinished()), this, SLOT(OnHostnameChanged()) ); - connect( m_Controls->bufferMsgCheckBox, SIGNAL(stateChanged(int)), + connect( m_Controls->bufferInMsgCheckBox, SIGNAL(stateChanged(int)), this, SLOT(OnBufferIncomingMessages(int))); + connect( m_Controls->bufferOutMsgCheckBox, SIGNAL(stateChanged(int)), + this, SLOT(OnBufferOutgoingMessages(int))); } + //this is used for thread seperation, otherwise the worker thread would change the ui elements + //which would cause an exception + connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState())); } void QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged() { - this->AdaptGUIToState(); + emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceSetupConnectionWidget::AdaptGUIToState() { //check the validity of the device if ( this->m_IGTLDevice.IsNull() ) { return; } //check the state of the device mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState(); switch (state) { case mitk::IGTLDevice::Setup: if ( !m_IsClient ) { m_Controls->butConnect->setText("Go Online"); this->m_Controls->editIP->setEnabled(false); } else { m_Controls->butConnect->setText("Connect"); this->m_Controls->editIP->setEnabled(true); } this->m_Controls->editPort->setEnabled(true); - this->m_Controls->logSendReceiveMsg->setEnabled(false); - this->m_Controls->bufferMsgCheckBox->setEnabled(false); + this->m_Controls->logIncomingMsg->setEnabled(false); + this->m_Controls->logOutgoingMsg->setEnabled(false); + this->m_Controls->bufferInMsgCheckBox->setEnabled(false); + this->m_Controls->bufferOutMsgCheckBox->setEnabled(false); this->m_Controls->butConnect->setEnabled(true); break; case mitk::IGTLDevice::Ready: this->m_Controls->butConnect->setText("Disconnect"); this->m_Controls->editIP->setEnabled(false); this->m_Controls->editPort->setEnabled(false); - this->m_Controls->logSendReceiveMsg->setEnabled(true); - this->m_Controls->bufferMsgCheckBox->setEnabled(true); + this->m_Controls->logIncomingMsg->setEnabled(true); + this->m_Controls->logOutgoingMsg->setEnabled(true); + this->m_Controls->bufferInMsgCheckBox->setEnabled(true); + this->m_Controls->bufferOutMsgCheckBox->setEnabled(true); this->m_Controls->butConnect->setEnabled(true); break; case mitk::IGTLDevice::Running: this->m_Controls->butConnect->setText("Disconnect"); this->m_Controls->editIP->setEnabled(false); this->m_Controls->editPort->setEnabled(false); - this->m_Controls->logSendReceiveMsg->setEnabled(true); - this->m_Controls->bufferMsgCheckBox->setEnabled(true); + this->m_Controls->logIncomingMsg->setEnabled(true); + this->m_Controls->logOutgoingMsg->setEnabled(true); + this->m_Controls->bufferInMsgCheckBox->setEnabled(true); + this->m_Controls->bufferOutMsgCheckBox->setEnabled(true); this->m_Controls->butConnect->setEnabled(true); break; default: mitkThrow() << "Invalid Device State"; break; } } void QmitkIGTLDeviceSetupConnectionWidget::Initialize( mitk::IGTLDevice::Pointer device) { //reset the GUI DisableSourceControls(); //reset the observers - if ( this->m_IGTLDevice.IsNotNull() ) - { - this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); - this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); - this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); - this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); - this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); - } + this->RemoveObserver(); if(device.IsNotNull()) { this->m_IGTLDevice = device; //check if the device is a server or a client if ( dynamic_cast( this->m_IGTLDevice.GetPointer()) == NULL ) { m_IsClient = false; } else { m_IsClient = true; } this->AdaptGUIToState(); typedef itk::SimpleMemberCommand< QmitkIGTLDeviceSetupConnectionWidget > CurCommandType; + CurCommandType::Pointer messageSentCommand = CurCommandType::New(); + messageSentCommand->SetCallbackFunction( + this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageSent); + this->m_MessageSentObserverTag = this->m_IGTLDevice->AddObserver( + mitk::MessageSentEvent(), messageSentCommand); + CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); messageReceivedCommand->SetCallbackFunction( - this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived ); + this, &QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived); this->m_MessageReceivedObserverTag = this->m_IGTLDevice->AddObserver( - mitk::MessageReceivedEvent(), messageReceivedCommand); + mitk::MessageReceivedEvent(), messageReceivedCommand); CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); commandReceivedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived ); this->m_CommandReceivedObserverTag = this->m_IGTLDevice->AddObserver( mitk::CommandReceivedEvent(), commandReceivedCommand); CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); connectionLostCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection ); this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::LostConnectionEvent(), connectionLostCommand); CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); newConnectionCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection ); this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::NewClientConnectionEvent(), newConnectionCommand); CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); stateModifiedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSetupConnectionWidget::OnDeviceStateChanged ); this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( itk::ModifiedEvent(), stateModifiedCommand); + + OnBufferIncomingMessages(m_Controls->bufferInMsgCheckBox->isChecked()); + OnBufferOutgoingMessages(m_Controls->bufferOutMsgCheckBox->isChecked()); } else { m_IGTLDevice = NULL; } } void QmitkIGTLDeviceSetupConnectionWidget::DisableSourceControls() { m_Controls->editIP->setEnabled(false); m_Controls->editPort->setEnabled(false); m_Controls->butConnect->setEnabled(false); - m_Controls->bufferMsgCheckBox->setEnabled(false); - m_Controls->logSendReceiveMsg->setEnabled(false); + m_Controls->bufferInMsgCheckBox->setEnabled(false); + m_Controls->bufferOutMsgCheckBox->setEnabled(false); + m_Controls->logIncomingMsg->setEnabled(false); + m_Controls->logOutgoingMsg->setEnabled(false); } void QmitkIGTLDeviceSetupConnectionWidget::OnConnect() { if(m_Controls->butConnect->text() == "Connect" || m_Controls->butConnect->text() == "Go Online" ) { QString port = m_Controls->editPort->text(); m_IGTLDevice->SetPortNumber(port.toInt()); std::string hostname = m_Controls->editIP->text().toStdString(); m_IGTLDevice->SetHostname(hostname); //connect with the other OpenIGTLink device => changes the state from Setup //to Ready if ( m_IGTLDevice->OpenConnection() ) { //starts the communication thread => changes the state from Ready to //Running if ( m_IGTLDevice->StartCommunication() ) { if ( this->m_IsClient ) { MITK_INFO("IGTLDeviceSourceManagementWidget") << "Successfully connected to " << hostname << " on port " << port.toStdString(); } } else { MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") << "Could not start a communication with the" "server because the client is in the wrong state"; } } else { MITK_ERROR("QmitkIGTLDeviceSetupConnectionWidget") << "Could not connect to the server. " "Please check the hostname and port."; } } else { m_IGTLDevice->CloseConnection(); MITK_INFO("QmitkIGTLDeviceSetupConnectionWidget") << "Closed connection"; } this->AdaptGUIToState(); } void QmitkIGTLDeviceSetupConnectionWidget::OnPortChanged() { } void QmitkIGTLDeviceSetupConnectionWidget::OnHostnameChanged() { } void QmitkIGTLDeviceSetupConnectionWidget::OnLostConnection() { - //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - - this->AdaptGUIToState(); - -// unsigned int numConnections = dev->GetNumberOfConnections(); - -// if ( numConnections == 0 ) -// { -// if ( this->m_IsClient ) -// { -// //Setup connection groupbox -// m_Controls->editIP->setEnabled(true); -// m_Controls->editPort->setEnabled(true); -// m_Controls->butConnect->setText("Connect"); -// m_Controls->logSendReceiveMsg->setEnabled(false); -// m_Controls->bufferMsgCheckBox->setEnabled(false); -// } -// } + emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceSetupConnectionWidget::OnNewConnection() { - this->AdaptGUIToState(); - - //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - -// unsigned int numConnections = dev->GetNumberOfConnections(); - -// if ( numConnections != 0 ) -// { -// //Setup connection groupbox -// m_Controls->editIP->setEnabled(false); -// m_Controls->editPort->setEnabled(false); -// m_Controls->butConnect->setText("Disconnect"); -// m_Controls->logSendReceiveMsg->setEnabled(true); -// m_Controls->bufferMsgCheckBox->setEnabled(true); -// } + emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceSetupConnectionWidget::OnMessageReceived() { -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; + if (this->m_Controls->logIncomingMsg->isChecked()) + { + MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a message: " + << this->m_IGTLDevice->GetReceiveQueue()->GetLatestMsgInformationString(); + } +} - if ( this->m_Controls->logSendReceiveMsg->isChecked() ) - { - MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a message: " - << this->m_IGTLDevice->GetReceiveQueue()->GetLatestMsgInformationString(); - } +void QmitkIGTLDeviceSetupConnectionWidget::OnMessageSent() +{ + if (this->m_Controls->logOutgoingMsg->isChecked()) + { + MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Sent a message."; + } } void QmitkIGTLDeviceSetupConnectionWidget::OnCommandReceived() { -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - - if ( this->m_Controls->logSendReceiveMsg->isChecked() ) + if (this->m_Controls->logIncomingMsg->isChecked()) { MITK_INFO("IGTLDeviceSetupConnectionWidget") << "Received a command: " << this->m_IGTLDevice->GetCommandQueue()->GetLatestMsgInformationString(); } } void QmitkIGTLDeviceSetupConnectionWidget::OnBufferIncomingMessages(int state) { - if ( this->m_IGTLDevice ) - { - this->m_IGTLDevice->EnableInfiniteBufferingMode( - this->m_IGTLDevice->GetReceiveQueue(), (bool)state); - } + if (this->m_IGTLDevice.IsNotNull()) + { + this->m_IGTLDevice->EnableInfiniteBufferingMode( + this->m_IGTLDevice->GetReceiveQueue(), (bool)state); + } +} + +void QmitkIGTLDeviceSetupConnectionWidget::OnBufferOutgoingMessages(int state) +{ + if (this->m_IGTLDevice.IsNotNull()) + { + this->m_IGTLDevice->EnableInfiniteBufferingMode( + this->m_IGTLDevice->GetSendQueue(), (bool)state); + } } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h index b5edab6886..cfeb26068b 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidget.h @@ -1,142 +1,162 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkIGTLDeviceSetupConnectionWidget_H #define QmitkIGTLDeviceSetupConnectionWidget_H //QT headers #include #include //mitk headers #include "MitkOpenIGTLinkUIExports.h" #include "mitkIGTLDeviceSource.h" #include "mitkIGTLClient.h" #include "mitkDataStorage.h" //itk #include //ui header #include "ui_QmitkIGTLDeviceSetupConnectionWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to setup the connection of an * OpenIGTLink device. * * * \ingroup OpenIGTLinkUI */ class MITKOPENIGTLINKUI_EXPORT QmitkIGTLDeviceSetupConnectionWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** * \brief Initializes the widget with the given device. * * The old device is * dropped, so be careful, if the source is not saved somewhere else it might * be lost. You might want to ask the user if he wants to save the changes * before calling this method. * \param device The widget will be initialized corresponding to the state of * this device. */ void Initialize(mitk::IGTLDevice::Pointer device); QmitkIGTLDeviceSetupConnectionWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkIGTLDeviceSetupConnectionWidget(); // /** // * \brief Is called when the current device received a message // */ // void OnMessageReceived(itk::Object* caller, const itk::EventObject&); // /** // * \brief Is called when the current device received a command // */ // void OnCommandReceived(itk::Object* caller, const itk::EventObject&); /** * \brief Is called when the current device lost a connection to one of its * sockets */ void OnLostConnection(); /** * \brief Is called when the current device connected to another device */ void OnNewConnection(); /** * \brief Is called when the current device received a message */ void OnMessageReceived(); + /** + * \brief Is called when the current device received a message + */ + void OnMessageSent(); + /** * \brief Is called when the current device received a command */ void OnCommandReceived(); protected slots: void OnConnect(); void OnPortChanged(); void OnHostnameChanged(); /** - * \brief Enables/Disables the buffering of incoming messages - */ + * \brief Enables/Disables the buffering of incoming messages + */ void OnBufferIncomingMessages(int state); - protected: - /** - * \brief Adapts the GUI to the state of the device + * \brief Enables/Disables the buffering of outgoing messages + * + * This can be necessary when the data is faster produced then sent */ + void OnBufferOutgoingMessages(int state); + + /** + * \brief Adapts the GUI to the state of the device + */ void AdaptGUIToState(); + signals: + /** + * \brief used for thread seperation, the worker thread must not call AdaptGUIToState directly. + * QT signals are thread safe and seperate the threads + */ + void AdaptGUIToStateSignal(); + + protected: /** * \brief Calls AdaptGUIToState() */ void OnDeviceStateChanged(); /** \brief Creation of the connections */ virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkIGTLDeviceSetupConnectionWidgetControls* m_Controls; /** @brief holds the OpenIGTLink device */ mitk::IGTLDevice::Pointer m_IGTLDevice; /** @brief flag to indicate if the IGTL device is a client or a server */ bool m_IsClient; + unsigned long m_MessageSentObserverTag; unsigned long m_MessageReceivedObserverTag; unsigned long m_CommandReceivedObserverTag; unsigned long m_LostConnectionObserverTag; unsigned long m_NewConnectionObserverTag; unsigned long m_StateModifiedObserverTag; //############## private help methods ####################### void DisableSourceControls(); // void EnableSourceControls(); + void RemoveObserver(); }; #endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui index ab9774356a..05bead4b1b 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSetupConnectionWidgetControls.ui @@ -1,137 +1,161 @@ QmitkIGTLDeviceSetupConnectionWidgetControls 0 0 443 169 Form false Connect with the host/Start server Connect false false false false false - - - - false - - - Enable this checkbox to log the send and receive message events - - - Log Send and Receive Messages - - - Port Server-IP false Enter the port number of the host 18944 5 true Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Port false Enter the IP address of the host 127.0.0.1 Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - - - - false - - - If this checkbox is set the device stores all incoming messages in the queue. If it is not set it always overwrites the current value. - - - Buffer Incoming Messages - - - true - - + + + + + + false + + + Enable this checkbox to log the send and receive message events + + + Log Incoming Messages + + + + + + + false + + + Buffer Outgoing Messages + + + + + + + false + + + If this checkbox is set the device stores all incoming messages in the queue. If it is not set it always overwrites the current value. + + + Buffer Incoming Messages + + + false + + + + + + + false + + + Log Outgoing Messages + + + + diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp index 7fdd56d625..2e0205aeeb 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.cpp @@ -1,307 +1,246 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTLDeviceSourceManagementWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //igtl #include #include #include #include //poco headers #include const std::string QmitkIGTLDeviceSourceManagementWidget::VIEW_ID = "org.mitk.views.igtldevicesourcemanagementwidget"; QmitkIGTLDeviceSourceManagementWidget::QmitkIGTLDeviceSourceManagementWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_IsClient(false) { m_Controls = NULL; this->m_IGTLDevice = NULL; CreateQtPartControl(this); } QmitkIGTLDeviceSourceManagementWidget::~QmitkIGTLDeviceSourceManagementWidget() { + this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); + this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); } void QmitkIGTLDeviceSourceManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLDeviceSourceManagementWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } //connect slots with signals CreateConnections(); } void QmitkIGTLDeviceSourceManagementWidget::CreateConnections() { if (m_Controls) { connect( m_Controls->butSend, SIGNAL(clicked()), this, SLOT(OnSendMessage())); } + //this is used for thread seperation, otherwise the worker thread would change the ui elements + //which would cause an exception + connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState())); } void QmitkIGTLDeviceSourceManagementWidget::OnDeviceStateChanged() { - this->AdaptGUIToState(); + emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceSourceManagementWidget::AdaptGUIToState() { if (this->m_IGTLDeviceSource.IsNotNull()) { //check the state of the device mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDeviceSource->GetIGTLDevice()->GetState(); switch (state) { case mitk::IGTLDevice::Setup: this->m_Controls->editSend->setEnabled(false); this->m_Controls->butSend->setEnabled(false); break; case mitk::IGTLDevice::Ready: this->m_Controls->editSend->setEnabled(false); this->m_Controls->butSend->setEnabled(false); break; case mitk::IGTLDevice::Running: if ( this->m_IGTLDevice->GetNumberOfConnections() == 0 ) { //just a server can run and have 0 connections this->m_Controls->editSend->setEnabled(false); this->m_Controls->butSend->setEnabled(false); } else { this->m_Controls->editSend->setEnabled(true); this->m_Controls->butSend->setEnabled(true); } break; default: mitkThrow() << "Invalid Device State"; break; } m_Controls->selectedSourceLabel->setText( m_IGTLDeviceSource->GetName().c_str()); } else { this->DisableSourceControls(); } } void QmitkIGTLDeviceSourceManagementWidget::LoadSource( mitk::IGTLDeviceSource::Pointer sourceToLoad) { //reset the GUI DisableSourceControls(); //reset the observers if ( this->m_IGTLDevice.IsNotNull() ) { this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); } if(sourceToLoad.IsNotNull()) { this->m_IGTLDeviceSource = sourceToLoad; //get the device this->m_IGTLDevice = this->m_IGTLDeviceSource->GetIGTLDevice(); //initialize the other GUI elements this->m_Controls->connectionSetupWidget->Initialize(this->m_IGTLDevice); this->m_Controls->commandWidget->Initialize(this->m_IGTLDevice); //check if the device is a server or a client if ( dynamic_cast( this->m_IGTLDeviceSource->GetIGTLDevice()) == NULL ) { m_IsClient = false; } else { m_IsClient = true; } typedef itk::SimpleMemberCommand< QmitkIGTLDeviceSourceManagementWidget > CurCommandType; CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); messageReceivedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSourceManagementWidget::OnMessageReceived ); this->m_MessageReceivedObserverTag = this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); commandReceivedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSourceManagementWidget::OnCommandReceived ); this->m_CommandReceivedObserverTag = this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); connectionLostCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSourceManagementWidget::OnLostConnection ); this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::LostConnectionEvent(), connectionLostCommand); CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); newConnectionCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSourceManagementWidget::OnNewConnection ); this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::NewClientConnectionEvent(), newConnectionCommand); CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); stateModifiedCommand->SetCallbackFunction( this, &QmitkIGTLDeviceSourceManagementWidget::OnDeviceStateChanged ); this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( itk::ModifiedEvent(), stateModifiedCommand); } else { m_IGTLDeviceSource = NULL; } this->AdaptGUIToState(); } void QmitkIGTLDeviceSourceManagementWidget::DisableSourceControls() { m_Controls->selectedSourceLabel->setText(""); m_Controls->editSend->setEnabled(false); m_Controls->butSend->setEnabled(false); } void QmitkIGTLDeviceSourceManagementWidget::OnSendMessage() { std::string toBeSend = m_Controls->editSend->text().toStdString(); igtl::StringMessage::Pointer msg = igtl::StringMessage::New(); msg->SetString(toBeSend); this->m_IGTLDevice->SendMessage(msg.GetPointer()); } void QmitkIGTLDeviceSourceManagementWidget::OnMessageReceived() { -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - -// if ( this->m_Controls->logSendReceiveMsg->isChecked() ) -// { -// MITK_INFO("IGTLDeviceSourceManagementWidget") << "Received a message: " -// << dev->GetReceiveQueue()->GetLatestMsgInformationString(); -// } + } void QmitkIGTLDeviceSourceManagementWidget::OnCommandReceived() { -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - -// if ( this->m_Controls->logSendReceiveMsg->isChecked() ) -// { -// MITK_INFO("IGTLDeviceSourceManagementWidget") << "Received a command: " -// << dev->GetCommandQueue()->GetLatestMsgInformationString(); -// } + } void QmitkIGTLDeviceSourceManagementWidget::OnLostConnection() { - this->AdaptGUIToState(); -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - -// unsigned int numConnections = dev->GetNumberOfConnections(); - -// if ( numConnections == 0 ) -// { -// if ( this->m_IsClient ) -// { -// //Setup connection groupbox -// m_Controls->editIP->setEnabled(true); -// m_Controls->editPort->setEnabled(true); -// m_Controls->butConnect->setText("Connect"); -// m_Controls->logSendReceiveMsg->setEnabled(false); -// m_Controls->bufferMsgCheckBox->setEnabled(false); -// //send string messages groupbox -// m_Controls->editSend->setEnabled(false); -// m_Controls->butSend->setEnabled(false); -// //send command messages groupbox -// m_Controls->butSendCommand->setEnabled(false); -// m_Controls->fpsSpinBox->setEnabled(false); -// m_Controls->commandsComboBox->setEnabled(false); -// } -// else -// { -// //send string messages groupbox -// m_Controls->editSend->setEnabled(false); -// m_Controls->butSend->setEnabled(false); -// //send command messages groupbox -// m_Controls->butSendCommand->setEnabled(false); -// m_Controls->fpsSpinBox->setEnabled(false); -// m_Controls->commandsComboBox->setEnabled(false); -// } -// } + emit AdaptGUIToStateSignal(); } void QmitkIGTLDeviceSourceManagementWidget::OnNewConnection() { - this->AdaptGUIToState(); -// //get the IGTL device that invoked this event -// mitk::IGTLDevice* dev = (mitk::IGTLDevice*)caller; - -// unsigned int numConnections = dev->GetNumberOfConnections(); - -// if ( numConnections != 0 ) -// { -// //Setup connection groupbox -// m_Controls->editIP->setEnabled(false); -// m_Controls->editPort->setEnabled(false); -// m_Controls->butConnect->setText("Disconnect"); -// m_Controls->logSendReceiveMsg->setEnabled(true); -// m_Controls->bufferMsgCheckBox->setEnabled(true); -// //send string messages groupbox -// m_Controls->editSend->setEnabled(true); -// m_Controls->butSend->setEnabled(true); -// //send command messages groupbox -// m_Controls->butSendCommand->setEnabled(true); -//// m_Controls->fpsSpinBox->setEnabled(false); -// m_Controls->commandsComboBox->setEnabled(true); -// } + emit AdaptGUIToStateSignal(); } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h index 48693d33ad..58e33efa81 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLDeviceSourceManagementWidget.h @@ -1,126 +1,132 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKIGTLDeviceSourceMANAGEMENTWIDGET_H #define QMITKIGTLDeviceSourceMANAGEMENTWIDGET_H //QT headers #include #include //mitk headers #include "MitkOpenIGTLinkUIExports.h" #include "mitkIGTLDeviceSource.h" #include "mitkIGTLClient.h" #include "mitkDataStorage.h" //itk #include //ui header #include "ui_QmitkIGTLDeviceSourceManagementWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to manage OpenIGTLink Device * Sources and OpenIGTLink Devices. * * * \ingroup OpenIGTLinkUI */ class MITKOPENIGTLINKUI_EXPORT QmitkIGTLDeviceSourceManagementWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** Loads a source to the widget. The old source is dropped, so be careful, * if the source is not saved somewhere else it might be lost. You might * want to ask the user if he wants to save the changes before calling this * method. * @param sourceToLoad This source will be loaded and might be modified * by the user. */ void LoadSource(mitk::IGTLDeviceSource::Pointer sourceToLoad); QmitkIGTLDeviceSourceManagementWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkIGTLDeviceSourceManagementWidget(); - /** - * \brief Is called when the current device received a message - */ - void OnMessageReceived(); - /** + protected slots: + void OnSendMessage(); + + /** + * \brief Is called when the current device received a message + */ + void OnMessageReceived(); + + /** * \brief Is called when the current device received a command - */ - void OnCommandReceived(); + */ + void OnCommandReceived(); - /** + /** * \brief Is called when the current device lost a connection to one of its * sockets - */ - void OnLostConnection(); + */ + void OnLostConnection(); - /** + /** * \brief Is called when the current device connected to another device - */ - void OnNewConnection(); - - - protected slots: - void OnSendMessage(); - - protected: - /** + */ + void OnNewConnection(); + /** * \brief Adapts the GUI to the state of the device */ - void AdaptGUIToState(); + void AdaptGUIToState(); + signals: + /** + * \brief used for thread seperation, the worker thread must not call AdaptGUIToState directly + * QT signals are thread safe and seperate the threads + */ + void AdaptGUIToStateSignal(); + + protected: /** * \brief Calls AdaptGUIToState() */ void OnDeviceStateChanged(); /// \brief Fills the commands combo box with available commands void FillCommandsComboBox(); /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkIGTLDeviceSourceManagementWidgetControls* m_Controls; /** @brief holds the OpenIGTLink device */ mitk::IGTLDevice::Pointer m_IGTLDevice; /** @brief holds the IGTLDeviceSource we are working with. */ mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource; /** @brief flag to indicate if the IGTL device is a client or a server */ bool m_IsClient; unsigned long m_MessageReceivedObserverTag; unsigned long m_CommandReceivedObserverTag; unsigned long m_LostConnectionObserverTag; unsigned long m_NewConnectionObserverTag; unsigned long m_StateModifiedObserverTag; //############## private help methods ####################### void DisableSourceControls(); }; #endif diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp index f4608eb86f..ae47812c0b 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.cpp @@ -1,307 +1,320 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "QmitkIGTLStreamingManagementWidget.h" //mitk headers #include #include #include #include //qt headers #include #include #include #include //igtl #include #include #include #include //poco headers #include const std::string QmitkIGTLStreamingManagementWidget::VIEW_ID = "org.mitk.views.igtldevicesourcemanagementwidget"; QmitkIGTLStreamingManagementWidget::QmitkIGTLStreamingManagementWidget( QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f), m_IsClient(false) { m_Controls = NULL; this->m_IGTLDevice = NULL; CreateQtPartControl(this); } QmitkIGTLStreamingManagementWidget::~QmitkIGTLStreamingManagementWidget() { + this->RemoveObserver(); +} + +void QmitkIGTLStreamingManagementWidget::RemoveObserver() +{ + if (this->m_IGTLDevice.IsNotNull()) + { + this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); + this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); + } } void QmitkIGTLStreamingManagementWidget::CreateQtPartControl(QWidget *parent) { if (!m_Controls) { // create GUI widgets m_Controls = new Ui::QmitkIGTLStreamingManagementWidgetControls; // setup GUI widgets m_Controls->setupUi(parent); } //connect slots with signals CreateConnections(); } void QmitkIGTLStreamingManagementWidget::CreateConnections() { if (m_Controls) { connect( (QObject*)(m_Controls->messageSourceSelectionWidget), SIGNAL(IGTLMessageSourceSelected(mitk::IGTLMessageSource::Pointer)), this, SLOT(SourceSelected(mitk::IGTLMessageSource::Pointer)) ); connect( m_Controls->startStreamPushButton, SIGNAL(clicked()), this, SLOT(OnStartStreaming())); connect( m_Controls->stopStreamPushButton, SIGNAL(clicked()), this, SLOT(OnStopStreaming())); } + //this is used for thread seperation, otherwise the worker thread would change the ui elements + //which would cause an exception + connect(this, SIGNAL(AdaptGUIToStateSignal()), this, SLOT(AdaptGUIToState())); + connect(this, SIGNAL(SelectSourceAndAdaptGUISignal()), this, SLOT(SelectSourceAndAdaptGUI())); } void QmitkIGTLStreamingManagementWidget::AdaptGUIToState() { if (this->m_IGTLMsgProvider.IsNotNull()) { //get the state of the device mitk::IGTLDevice::IGTLDeviceState state = this->m_IGTLDevice->GetState(); switch (state) { case mitk::IGTLDevice::Setup: case mitk::IGTLDevice::Ready: m_Controls->messageSourceSelectionWidget->setEnabled(false); m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); break; case mitk::IGTLDevice::Running: //check the number of connections of the device, a server can be in //the running state even if there is no connected device, this part of //the GUI shall just be available when there is a connection if ( this->m_IGTLDevice->GetNumberOfConnections() == 0 ) { m_Controls->messageSourceSelectionWidget->setEnabled(false); m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); } else //there is a connection { //check if the user already selected a source to stream if ( this->m_IGTLMsgSource.IsNull() ) // he did not so far { m_Controls->messageSourceSelectionWidget->setEnabled(true); m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); } else //user already selected a source { QString nameOfSource = QString::fromStdString(m_IGTLMsgSource->GetName()); m_Controls->messageSourceSelectionWidget->setEnabled(true); m_Controls->selectedSourceLabel->setText(nameOfSource); m_Controls->selectedSourceLabel->setEnabled(true); m_Controls->label->setEnabled(true); //check if the streaming is already running if (this->m_IGTLMsgProvider->IsStreaming()) { m_Controls->startStreamPushButton->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(true); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); } else { m_Controls->startStreamPushButton->setEnabled(true); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(true); m_Controls->fpsSpinBox->setEnabled(true); } } } break; default: mitkThrow() << "Invalid Device State"; break; } } else { this->DisableSourceControls(); } } void QmitkIGTLStreamingManagementWidget::LoadSource( mitk::IGTLMessageProvider::Pointer provider) { //reset the GUI DisableSourceControls(); if ( provider.IsNull() ) return; //reset the observers - if ( this->m_IGTLDevice.IsNotNull() ) - { -// this->m_IGTLDevice->RemoveObserver(m_MessageReceivedObserverTag); -// this->m_IGTLDevice->RemoveObserver(m_CommandReceivedObserverTag); - this->m_IGTLDevice->RemoveObserver(m_LostConnectionObserverTag); - this->m_IGTLDevice->RemoveObserver(m_NewConnectionObserverTag); - this->m_IGTLDevice->RemoveObserver(m_StateModifiedObserverTag); - } + this->RemoveObserver(); this->m_IGTLMsgProvider = provider; //get the device this->m_IGTLDevice = this->m_IGTLMsgProvider->GetIGTLDevice(); //check if the device is a server or a client if ( dynamic_cast( this->m_IGTLDevice.GetPointer()) == NULL ) { m_IsClient = false; } else { m_IsClient = true; } typedef itk::SimpleMemberCommand< QmitkIGTLStreamingManagementWidget > CurCommandType; // CurCommandType::Pointer messageReceivedCommand = CurCommandType::New(); // messageReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLStreamingManagementWidget::OnMessageReceived ); // this->m_MessageReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::MessageReceivedEvent(), messageReceivedCommand); // CurCommandType::Pointer commandReceivedCommand = CurCommandType::New(); // commandReceivedCommand->SetCallbackFunction( // this, &QmitkIGTLStreamingManagementWidget::OnCommandReceived ); // this->m_CommandReceivedObserverTag = // this->m_IGTLDevice->AddObserver(mitk::CommandReceivedEvent(), commandReceivedCommand); CurCommandType::Pointer connectionLostCommand = CurCommandType::New(); connectionLostCommand->SetCallbackFunction( this, &QmitkIGTLStreamingManagementWidget::OnLostConnection ); this->m_LostConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::LostConnectionEvent(), connectionLostCommand); CurCommandType::Pointer newConnectionCommand = CurCommandType::New(); newConnectionCommand->SetCallbackFunction( this, &QmitkIGTLStreamingManagementWidget::OnNewConnection ); this->m_NewConnectionObserverTag = this->m_IGTLDevice->AddObserver( mitk::NewClientConnectionEvent(), newConnectionCommand); CurCommandType::Pointer stateModifiedCommand = CurCommandType::New(); stateModifiedCommand->SetCallbackFunction( this, &QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged ); this->m_StateModifiedObserverTag = this->m_IGTLDevice->AddObserver( itk::ModifiedEvent(), stateModifiedCommand); this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::DisableSourceControls() { m_Controls->selectedSourceLabel->setText(""); m_Controls->startStreamPushButton->setEnabled(false); m_Controls->stopStreamPushButton->setEnabled(false); m_Controls->fpsLabel->setEnabled(false); m_Controls->fpsSpinBox->setEnabled(false); m_Controls->selectedSourceLabel->setEnabled(false); m_Controls->label->setEnabled(false); m_Controls->messageSourceSelectionWidget->setEnabled(false); } void QmitkIGTLStreamingManagementWidget::SourceSelected( mitk::IGTLMessageSource::Pointer source) { //reset everything this->DisableSourceControls(); if (source.IsNotNull()) //no source selected { this->m_IGTLMsgSource = source; } this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::OnStartStreaming() { unsigned int fps = this->m_Controls->fpsSpinBox->value(); this->m_IGTLMsgProvider->StartStreamingOfSource(this->m_IGTLMsgSource, fps); this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::OnStopStreaming() { this->m_IGTLMsgProvider->StopStreamingOfSource(this->m_IGTLMsgSource); this->AdaptGUIToState(); } void QmitkIGTLStreamingManagementWidget::OnMessageReceived() { } void QmitkIGTLStreamingManagementWidget::OnCommandReceived() { } void QmitkIGTLStreamingManagementWidget::OnDeviceStateChanged() { - this->AdaptGUIToState(); + emit AdaptGUIToStateSignal(); } void QmitkIGTLStreamingManagementWidget::OnLostConnection() { - this->AdaptGUIToState(); + emit AdaptGUIToStateSignal(); } void QmitkIGTLStreamingManagementWidget::OnNewConnection() { - //get the current selection and call SourceSelected which will call AdaptGUI - mitk::IGTLMessageSource::Pointer curSelSrc = + emit SelectSourceAndAdaptGUISignal(); +} + +void QmitkIGTLStreamingManagementWidget::SelectSourceAndAdaptGUI() +{ + //get the current selection and call SourceSelected which will call AdaptGUI + mitk::IGTLMessageSource::Pointer curSelSrc = m_Controls->messageSourceSelectionWidget->GetSelectedIGTLMessageSource(); - SourceSelected(curSelSrc); + SourceSelected(curSelSrc); } diff --git a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h index c024a4ba02..dbea137773 100644 --- a/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h +++ b/Modules/OpenIGTLinkUI/Qmitk/QmitkIGTLStreamingManagementWidget.h @@ -1,135 +1,155 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QMITKIGTLStreamingMANAGEMENTWIDGET_H #define QMITKIGTLStreamingMANAGEMENTWIDGET_H //QT headers #include #include //mitk headers #include "MitkOpenIGTLinkUIExports.h" #include "mitkIGTLMessageProvider.h" #include "mitkIGTLClient.h" #include "mitkDataStorage.h" //itk #include //ui header #include "ui_QmitkIGTLStreamingManagementWidgetControls.h" /** Documentation: * \brief An object of this class offers an UI to manage the streaming of * message sources. * * * \ingroup OpenIGTLinkUI */ class MITKOPENIGTLINKUI_EXPORT QmitkIGTLStreamingManagementWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; /** Loads a provider to the widget. The old source is dropped, so be careful, * if the source is not saved somewhere else it might be lost. You might * want to ask the user if he wants to save the changes before calling this * method. * @param provider This provider will be loaded and might be modified * by the user. */ void LoadSource(mitk::IGTLMessageProvider::Pointer provider); QmitkIGTLStreamingManagementWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkIGTLStreamingManagementWidget(); /** * \brief Is called when the current device received a message */ void OnMessageReceived(); /** * \brief Is called when the current device received a command */ void OnCommandReceived(); /** * \brief Is called when the current device lost a connection to one of its * sockets */ void OnLostConnection(); /** * \brief Is called when the current device connected to another device */ void OnNewConnection(); protected slots: void OnStartStreaming(); void OnStopStreaming(); /** \brief Is called when a new source is selected. * @param source the newly selected source */ void SourceSelected(mitk::IGTLMessageSource::Pointer source); - protected: /** - * \brief Adapts the GUI to the state of the device - */ + * \brief Adapts the GUI to the state of the device + */ void AdaptGUIToState(); + /** + * \brief selects the current source and adapts the GUI according to the selection + */ + void SelectSourceAndAdaptGUI(); + + signals: + /** + * \brief used for thread seperation, the worker thread must not call AdaptGUIToState directly. + * QT signals are thread safe and seperate the threads + */ + void AdaptGUIToStateSignal(); + /** + * \brief used for thread seperation, the worker thread must not call SelectSourceAndAdaptGUI + * directly. + * QT signals are thread safe and seperate the threads + */ + void SelectSourceAndAdaptGUISignal(); + + protected: + /** * \brief Calls AdaptGUIToState() */ void OnDeviceStateChanged(); /// \brief Fills the commands combo box with available commands void FillCommandsComboBox(); /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkIGTLStreamingManagementWidgetControls* m_Controls; /** @brief holds the OpenIGTLink device */ mitk::IGTLDevice::Pointer m_IGTLDevice; /** @brief holds the IGTL Message Provider that will send the stream */ mitk::IGTLMessageProvider::Pointer m_IGTLMsgProvider; /** @brief holds the IGTLDeviceSource we are working with. */ mitk::IGTLMessageSource::Pointer m_IGTLMsgSource; /** @brief flag to indicate if the IGTL device is a client or a server */ bool m_IsClient; unsigned long m_MessageReceivedObserverTag; unsigned long m_CommandReceivedObserverTag; unsigned long m_LostConnectionObserverTag; unsigned long m_NewConnectionObserverTag; unsigned long m_StateModifiedObserverTag; //############## private help methods ####################### void DisableSourceControls(); + void RemoveObserver(); }; #endif diff --git a/Modules/RDF/CMakeLists.txt b/Modules/RDF/CMakeLists.txt index 56363dc4b6..3b9d5d05bd 100644 --- a/Modules/RDF/CMakeLists.txt +++ b/Modules/RDF/CMakeLists.txt @@ -1,6 +1,11 @@ -mitk_create_module(PACKAGE_DEPENDS Redland - WARNINGS_AS_ERRORS - ) +mitk_create_module( + DEPENDS MitkCore + PACKAGE_DEPENDS Redland + WARNINGS_AS_ERRORS +) add_subdirectory(Testing) +if(MSVC AND TARGET ${MODULE_TARGET}) + set_property(TARGET ${MODULE_TARGET} APPEND_STRING PROPERTY COMPILE_FLAGS " /wd4251") +endif() diff --git a/Modules/RDF/Testing/files.cmake b/Modules/RDF/Testing/files.cmake index 686370ac21..ce71323c63 100644 --- a/Modules/RDF/Testing/files.cmake +++ b/Modules/RDF/Testing/files.cmake @@ -1,7 +1,10 @@ # tests with no extra command line parameter set(MODULE_TESTS + mitkRdfUriTest.cpp mitkRdfNodeTest.cpp + mitkRdfTripleTest.cpp + mitkRdfStoreTest.cpp ) set(RESOURCE_FILES ) diff --git a/Modules/RDF/Testing/mitkRdfNodeTest.cpp b/Modules/RDF/Testing/mitkRdfNodeTest.cpp index 7032b0ba50..51021f0ad9 100644 --- a/Modules/RDF/Testing/mitkRdfNodeTest.cpp +++ b/Modules/RDF/Testing/mitkRdfNodeTest.cpp @@ -1,52 +1,110 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkTestingMacros.h" #include #include #include "mitkRdfNode.h" class mitkRdfNodeTestSuite : public mitk::TestFixture { - // List of Tests CPPUNIT_TEST_SUITE(mitkRdfNodeTestSuite); - MITK_TEST(TestDummy); + // List of Tests + MITK_TEST(TestInvalidNode); + MITK_TEST(TestUriNode); + MITK_TEST(TestLiteralNode); + MITK_TEST(TestLiteralNodeWithDataType); + MITK_TEST(TestValueOfNode); + MITK_TEST(TestTypeOfNode); + MITK_TEST(TestDatatypeOfNode); CPPUNIT_TEST_SUITE_END(); +private: + + mitk::RdfNode emptyNode; + mitk::RdfUri base; + public: void setUp() override { + emptyNode = mitk::RdfNode(); + base = mitk::RdfUri("http://mitk.org/wiki/MITK/data/BaseOntology.rdf#"); } void tearDown() override { } // Test functions - void TestDummy() + void TestInvalidNode() { - mitk::RdfNode node; - CPPUNIT_ASSERT(node.dummy() == true); + mitk::RdfNode anotherInvalidNode("", mitk::RdfUri()); + anotherInvalidNode.SetType(mitk::RdfNode::NOTHING); + CPPUNIT_ASSERT(emptyNode == anotherInvalidNode); } + void TestUriNode() + { + mitk::RdfNode uriNode = mitk::RdfNode(base); + emptyNode.SetValue(base.ToString()); + emptyNode.SetType(mitk::RdfNode::URI); + emptyNode.SetDatatype(mitk::RdfUri()); + CPPUNIT_ASSERT(uriNode == emptyNode); + } + + void TestLiteralNode() + { + mitk::RdfNode literalNode = mitk::RdfNode("Example"); + emptyNode.SetValue("Example"); + emptyNode.SetType(mitk::RdfNode::LITERAL); + emptyNode.SetDatatype(mitk::RdfUri()); + CPPUNIT_ASSERT(literalNode == emptyNode); + } + + void TestLiteralNodeWithDataType() + { + mitk::RdfNode literalNode = mitk::RdfNode("MyTest", mitk::RdfUri("xsd:string")); + emptyNode.SetValue("MyTest"); + emptyNode.SetType(mitk::RdfNode::LITERAL); + emptyNode.SetDatatype(mitk::RdfUri("xsd:string")); + CPPUNIT_ASSERT(literalNode == emptyNode); + } + + void TestValueOfNode() + { + mitk::RdfNode node(base); + CPPUNIT_ASSERT(base.ToString().compare(node.GetValue()) == 0); + } + + void TestTypeOfNode() + { + mitk::RdfNode node(base); + CPPUNIT_ASSERT(node.GetType() == mitk::RdfNode::URI); + } + + void TestDatatypeOfNode() + { + mitk::RdfNode literalNodeAgain = mitk::RdfNode("42", mitk::RdfUri("xsd:integer")); + CPPUNIT_ASSERT(literalNodeAgain.GetDatatype() == mitk::RdfUri("xsd:integer")); + } }; MITK_TEST_SUITE_REGISTRATION(mitkRdfNode) diff --git a/Modules/RDF/Testing/mitkRdfStoreTest.cpp b/Modules/RDF/Testing/mitkRdfStoreTest.cpp new file mode 100644 index 0000000000..8d79d5ccdd --- /dev/null +++ b/Modules/RDF/Testing/mitkRdfStoreTest.cpp @@ -0,0 +1,123 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestingMacros.h" +#include +#include + +#include "mitkRdfStore.h" +#include + +#include + +class mitkRdfStoreTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkRdfStoreTestSuite); + + // List of Tests + MITK_TEST(TestAddPrefix); + MITK_TEST(TestAddTriple); + MITK_TEST(TestRemoveTriple); + MITK_TEST(TestQueryTriple); + MITK_TEST(TestSaveStore); + MITK_TEST(TestImportStore); + + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::RdfStore store; + mitk::RdfTriple triple; + +public: + + void setUp() + { + store.CleanUp(); + store.SetBaseUri(mitk::RdfUri("http://mitk.org/wiki/MITK/data/instances.rdf#")); + store.AddPrefix("dcterms", mitk::RdfUri("http://purl.org/dc/terms/")); + store.AddPrefix("mitk", mitk::RdfUri("http://mitk.org/wiki/MITK/data/BaseOntology.rdf#")); + triple = mitk::RdfTriple(mitk::RdfNode(mitk::RdfUri("http://mitk.org/wiki/MITK/data/instances.rdf#i0012")), + mitk::RdfNode(mitk::RdfUri("dcterms:title")), mitk::RdfNode("TestImage")); + } + + void tearDown() + { + } + + // Test functions + + void TestAddPrefix() + { + mitk::RdfUri fma = mitk::RdfUri("http://www.bioontology.org/projects/ontologies/fma/"); + store.AddPrefix("fma", fma); + std::map testMap = store.GetPrefixes(); + CPPUNIT_ASSERT(testMap.find("fma") != testMap.end()); + } + + void TestAddTriple() + { + store.Add(triple); + CPPUNIT_ASSERT(store.Contains(triple)); + } + + void TestRemoveTriple() + { + store.Add(triple); + store.Remove(triple); + CPPUNIT_ASSERT(!store.Contains(triple)); + } + + void TestQueryTriple() + { + store.Add(triple); + std::string query = "SELECT ?x WHERE { ?x ?z ?y . }"; + mitk::RdfStore::ResultMap queryResult = store.Query(query); + std::list list = queryResult["x"]; + CPPUNIT_ASSERT(triple.GetTripleSubject() == list.back()); + } + + void TestSaveStore() + { + store.Add(triple); + + std::ofstream tmpStream; + const std::string tmpFileName = mitk::IOUtil::CreateTemporaryFile(tmpStream); + store.Save(tmpFileName); + std::ifstream in(tmpFileName); + std::string s((std::istreambuf_iterator(in)), std::istreambuf_iterator()); + in.close(); + MITK_INFO << s; + tmpStream.close(); + + std::size_t found = s.find(":i0012"); + CPPUNIT_ASSERT(found!=std::string::npos); + } + + void TestImportStore() + { + std::ofstream tmpStream; + const std::string tmpFileName = mitk::IOUtil::CreateTemporaryFile(tmpStream); + const std::string strRDF = "@base . @prefix rdf: . @prefix : <> . @prefix dcterms: . @prefix mitk: . @prefix owl: . @prefix rdfs: . @prefix xsd: . :i0012 'TestImage' ."; + tmpStream << strRDF; + tmpStream.close(); + + store.Import("file:"+tmpFileName); + CPPUNIT_ASSERT(store.Contains(triple)); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkRdfStore) diff --git a/Modules/RDF/Testing/mitkRdfTripleTest.cpp b/Modules/RDF/Testing/mitkRdfTripleTest.cpp new file mode 100644 index 0000000000..75f70deca2 --- /dev/null +++ b/Modules/RDF/Testing/mitkRdfTripleTest.cpp @@ -0,0 +1,120 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestingMacros.h" +#include +#include + +#include "mitkRdfTriple.h" + +class mitkRdfTripleTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkRdfTripleTestSuite); + + // List of Tests + MITK_TEST(TestEmptyTriple); + MITK_TEST(TestObjectTriple); + MITK_TEST(TestDataTriple); + MITK_TEST(TestSubjectOfTriple); + MITK_TEST(TestPredicateOfTriple); + MITK_TEST(TestObjectOfTripleAsObject); + MITK_TEST(TestObjectOfTripleAsData); + + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::RdfTriple emptyTriple; + mitk::RdfUri seg; + mitk::RdfUri title; + +public: + + void setUp() + { + emptyTriple = mitk::RdfTriple(); + title = mitk::RdfUri("dcterms:title"); + seg = mitk::RdfUri("http://mitk.org/wiki/MITK/data/instance.rdf#s0001"); + } + + void tearDown() + { + } + + // Test functions + + void TestEmptyTriple() + { + mitk::RdfTriple anotherTriple = mitk::RdfTriple( + mitk::RdfNode(), mitk::RdfNode(), mitk::RdfNode()); + CPPUNIT_ASSERT(emptyTriple == anotherTriple); + } + + void TestObjectTriple() + { + mitk::RdfUri src = mitk::RdfUri("dcterms:source"); + mitk::RdfUri image = mitk::RdfUri("http://mitk.org/wiki/MITK/data/instance.rdf#i0012"); + mitk::RdfTriple objectTriple = mitk::RdfTriple( + mitk::RdfNode(seg), mitk::RdfNode(src), mitk::RdfNode(image)); + emptyTriple.SetTripleSubject(seg); + emptyTriple.SetTriplePredicate(src); + emptyTriple.SetTripleObject(mitk::RdfNode(image)); + CPPUNIT_ASSERT(emptyTriple == objectTriple); + } + + void TestDataTriple() + { + mitk::RdfTriple dataTriple = mitk::RdfTriple( + mitk::RdfNode(seg), mitk::RdfNode(title), "TestLiver"); + emptyTriple.SetTripleSubject(seg); + emptyTriple.SetTriplePredicate(title); + emptyTriple.SetTripleObject("TestLiver"); + CPPUNIT_ASSERT(emptyTriple == dataTriple); + } + + void TestSubjectOfTriple() + { + mitk::RdfTriple triple = mitk::RdfTriple( + mitk::RdfNode(seg), mitk::RdfNode(title), "KidneyLeft"); + + CPPUNIT_ASSERT(triple.GetTripleSubject() == mitk::RdfNode(seg)); + } + + void TestPredicateOfTriple() + { + mitk::RdfTriple triple = mitk::RdfTriple( + mitk::RdfNode(seg), mitk::RdfNode(title), "KidneyRight"); + CPPUNIT_ASSERT(triple.GetTriplePredicate() == mitk::RdfNode(title)); + } + + void TestObjectOfTripleAsObject() + { + mitk::RdfNode image = mitk::RdfNode( + mitk::RdfUri("http://mitk.org/wiki/MITK/data/instance.rdf#i0012")); + mitk::RdfTriple triple = mitk::RdfTriple( + mitk::RdfNode(seg), mitk::RdfNode(mitk::RdfUri("dcterms:source")), image); + CPPUNIT_ASSERT(triple.GetTripleObject() == image); + } + + void TestObjectOfTripleAsData() + { + mitk::RdfTriple triple = mitk::RdfTriple( + mitk::RdfNode(seg), mitk::RdfNode(mitk::RdfUri("mitk:volumeInMl")), "450"); + CPPUNIT_ASSERT(triple.GetTripleObject() == mitk::RdfNode("450")); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkRdfTriple) diff --git a/Modules/RDF/Testing/mitkRdfUriTest.cpp b/Modules/RDF/Testing/mitkRdfUriTest.cpp new file mode 100644 index 0000000000..206dbaee51 --- /dev/null +++ b/Modules/RDF/Testing/mitkRdfUriTest.cpp @@ -0,0 +1,74 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkTestingMacros.h" +#include +#include + +#include "mitkRdfUri.h" + +class mitkRdfUriTestSuite : public mitk::TestFixture +{ + CPPUNIT_TEST_SUITE(mitkRdfUriTestSuite); + + // List of Tests + MITK_TEST(TestEmptyUri); + MITK_TEST(TestValueOfUri); + MITK_TEST(TestSetUri); + + CPPUNIT_TEST_SUITE_END(); + +private: + + mitk::RdfUri m_EmptyUri; + std::string m_UriText; + mitk::RdfUri m_Uri; + +public: + + void setUp() + { + // normal URI + m_UriText = "http://mitk.org/wiki/MITK/data/BaseOntology.rdf#"; + m_Uri = mitk::RdfUri(m_UriText); + } + + void tearDown() + { + } + + // Test functions + + void TestEmptyUri() + { + mitk::RdfUri anotherEmptyUri(""); + CPPUNIT_ASSERT(m_EmptyUri == anotherEmptyUri); + } + + void TestValueOfUri() + { + CPPUNIT_ASSERT(m_Uri.ToString().compare(m_UriText) == 0); + } + + void TestSetUri() + { + mitk::RdfUri newUri; + newUri.SetUri(m_UriText); + CPPUNIT_ASSERT(newUri == m_Uri); + } +}; + +MITK_TEST_SUITE_REGISTRATION(mitkRdfUri) diff --git a/Modules/RDF/files.cmake b/Modules/RDF/files.cmake index 4fd8b64962..e58ca81787 100644 --- a/Modules/RDF/files.cmake +++ b/Modules/RDF/files.cmake @@ -1,3 +1,13 @@ set(CPP_FILES mitkRdfNode.cpp + mitkRdfUri.cpp + mitkRdfTriple.cpp + mitkRdfStore.cpp +) + +SET(H_FILES + mitkRdfNode.h + mitkRdfUri.h + mitkRdfTriple.h + mitkRdfStore.h ) diff --git a/Modules/RDF/mitkRdfNode.cpp b/Modules/RDF/mitkRdfNode.cpp index 4c21c93248..4652a77682 100644 --- a/Modules/RDF/mitkRdfNode.cpp +++ b/Modules/RDF/mitkRdfNode.cpp @@ -1,68 +1,118 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkRdfNode.h" #include #include -#include #include #include namespace mitk { -bool RdfNode::dummy() -{ - librdf_world* world; - librdf_storage *storage; - librdf_model* model; - librdf_statement* statement; - raptor_world *raptor_world_ptr; - raptor_iostream* iostr; - - world=librdf_new_world(); - librdf_world_open(world); - raptor_world_ptr = librdf_world_get_raptor(world); - - model=librdf_new_model(world, storage=librdf_new_storage(world, "hashes", nullptr, "hash-type='memory'"), nullptr); - - librdf_model_add_statement(model, - statement=librdf_new_statement_from_nodes(world, librdf_new_node_from_uri_string(world, (const unsigned char*)"http://www.dajobe.org/"), - librdf_new_node_from_uri_string(world, (const unsigned char*)"http://purl.org/dc/elements/1.1/creator"), - librdf_new_node_from_literal(world, (const unsigned char*)"Dave Beckett", nullptr, 0) - ) - ); - - librdf_free_statement(statement); - - iostr = raptor_new_iostream_to_file_handle(raptor_world_ptr, stdout); - librdf_model_write(model, iostr); - raptor_free_iostream(iostr); - - librdf_free_model(model); - librdf_free_storage(storage); - - librdf_free_world(world); - -#ifdef LIBRDF_MEMORY_DEBUG - librdf_memory_report(stderr); -#endif - - return true; -} - + RdfNode::RdfNode() + : m_Type(NOTHING) + { + } + + RdfNode::RdfNode(RdfUri uri) + : m_Type(URI), m_Value(uri.ToString()) + { + } + + RdfNode::RdfNode(std::string text) + : m_Type(LITERAL), m_Value(text) + { + } + + RdfNode::RdfNode(std::string text, RdfUri dataType) + : m_Type(LITERAL), m_Value(text), m_Datatype(dataType) + { + } + + RdfNode::~RdfNode() + { + } + + void RdfNode::SetType(RdfNode::Type type) + { + m_Type = type; + } + + void RdfNode::SetDatatype(RdfUri dataType) + { + m_Datatype = dataType; + } + + void RdfNode::SetValue(std::string value) + { + m_Value = value; + } + + RdfNode::Type RdfNode::GetType() const + { + return m_Type; + } + + RdfUri RdfNode::GetDatatype() const + { + return m_Datatype; + } + + std::string RdfNode::GetValue() const + { + return m_Value; + } + + bool RdfNode::operator==(const RdfNode &u) const + { + if (this->m_Type != u.m_Type) return false; + if (this->m_Value.compare(u.m_Value) != 0) return false; + if (this->m_Datatype != u.m_Datatype) return false; + return true; + } + + bool RdfNode::operator!=(const RdfNode &u) const + { + return !operator==(u); + } + + // Define outstream of a Node + std::ostream & operator<<(std::ostream &out, const RdfNode &n) + { + switch (n.GetType()) { + case RdfNode::NOTHING: + out << "[]"; + break; + case RdfNode::URI: + if (n.GetValue() == "") { + out << "[empty-uri]"; + } else { + out << "<" << n.GetValue() << ">"; + } + break; + case RdfNode::LITERAL: + out << "\"" << n.GetValue() << "\""; + if (n.GetDatatype() != RdfUri()) out << "^^" << n.GetDatatype(); + break; + case RdfNode::BLANK: + out << "[blank " << n.GetValue() << "]"; + break; + } + return out; + } } diff --git a/Modules/RDF/mitkRdfNode.h b/Modules/RDF/mitkRdfNode.h index 9ade7dee04..b3ebbbdb6c 100644 --- a/Modules/RDF/mitkRdfNode.h +++ b/Modules/RDF/mitkRdfNode.h @@ -1,39 +1,114 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ - #ifndef MITKRDFNODE_H #define MITKRDFNODE_H #include +#include "mitkRdfUri.h" + +#include +#include + namespace mitk { + /** + * \ingroup MitkRDFModule + */ + class MITKRDF_EXPORT RdfNode + { + public: + + /** + * Enumeration for node types. + */ + enum Type { NOTHING, URI, LITERAL, BLANK }; + + /** + * Construct a empty invalid node. + */ + RdfNode(); + + /** + * Construct a node from type URI which represents a object of the real world. + * @param uri An RdfUri which represents a URI. + */ + RdfNode(RdfUri uri); + + /** + * Construct a node from type LITERAL. + * @param text A std::string which represents a literal. + */ + RdfNode(std::string text); + + /** + * Construct a node from type LITERAL with a specific data type. + * @param text A std::string which represents a literal. + * @param dataType An RdfUri which represents a specific data type. + */ + RdfNode(std::string text, RdfUri dataType); + + virtual ~RdfNode(); + + /** + * Set the type of a Node. + * @param type An RdfNode::Type which represents a type of a node. + */ + void SetType(Type type); + + /** + * Set the data type of a LITERAL Node. + * @param dataType An RdfUri which represents an URI of a specific data type. + */ + void SetDatatype(RdfUri dataType); + + /** + * Set the internal represantation of an URI or a text. + * @param value A std::string which represents an URI or a text. + */ + void SetValue(std::string value); + + /** + * Get the type of a node. + * @return The type of a node. + */ + Type GetType() const; -/** - * \ingroup MitkRDFModule - */ -class MITKRDF_EXPORT RdfNode -{ + /** + * Get the data type of the internal value of a node. + * @return The data type of the internal value of a node. + */ + RdfUri GetDatatype() const; -public: + /** + * Get the internal value of a node. + * @return The internal value of a node. + */ + std::string GetValue() const; - bool dummy(); + bool operator==(const RdfNode &u) const; + bool operator!=(const RdfNode &u) const; -}; + private: + Type m_Type; + RdfUri m_Datatype; + std::string m_Value; + }; + MITKRDF_EXPORT std::ostream & operator<<(std::ostream &out, const mitk::RdfNode &n); } #endif diff --git a/Modules/RDF/mitkRdfStore.cpp b/Modules/RDF/mitkRdfStore.cpp new file mode 100644 index 0000000000..4350f363db --- /dev/null +++ b/Modules/RDF/mitkRdfStore.cpp @@ -0,0 +1,536 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkRdfStore.h" + +#include +#include + +#include + +namespace mitk { + class RdfStorePrivate + { + public: + typedef std::map > ResultMap; + typedef std::map PrefixMap; + + RdfStorePrivate(); + ~RdfStorePrivate(); + + void SetBaseUri(RdfUri uri); + RdfUri GetBaseUri() const; + + void AddPrefix(std::string prefix, RdfUri uri); + PrefixMap GetPrefixes() const; + + void CleanUp(); + + bool Add(RdfTriple triple); + bool Remove(RdfTriple triple); + bool Contains(RdfTriple triple); + + ResultMap Query(std::string query) const; + + void Save(std::string filename, std::string format = ""); + void Import(std::string url, std::string format = ""); + + RdfUri m_BaseUri; + + PrefixMap m_Prefixes; + + librdf_model* m_Model; + librdf_storage* m_Storage; + librdf_world* m_World; + + librdf_statement* RdfTripleToStatement(RdfTriple triple) const; + librdf_node* RdfNodeToLibRdfNode(RdfNode node) const; + librdf_uri* RdfUriToLibRdfUri(RdfUri uri) const; + + RdfTriple StatementToRdfTriple(librdf_statement* statement) const; + RdfNode LibRdfNodeToRdfNode(librdf_node* node) const; + RdfUri LibRdfUriToRdfUri(librdf_uri* uri) const; + + bool CheckComplete(librdf_statement* statement); + }; + + /**************************************************************************** + **************************** mitkRdfStorePrivate **************************** + ****************************************************************************/ + + RdfStorePrivate::RdfStorePrivate() + : m_World(0), m_Storage(0), m_Model(0) + { + // SetUp base prefixes + m_Prefixes["rdf"] = RdfUri("http://www.w3.org/1999/02/22-rdf-syntax-ns#"); + m_Prefixes["rdfs"] = RdfUri("http://www.w3.org/2000/01/rdf-schema#"); + m_Prefixes["xsd"] = RdfUri("http://www.w3.org/2001/XMLSchema#"); + m_Prefixes["owl"] = RdfUri("http://www.w3.org/2002/07/owl#"); + + // SetUp new store + CleanUp(); + } + + RdfStorePrivate::~RdfStorePrivate() + { + if(m_Model) + librdf_free_model(m_Model); + if(m_Storage) + librdf_free_storage(m_Storage); + if(m_World) + librdf_free_world(m_World); + } + + void RdfStorePrivate::SetBaseUri(RdfUri uri) + { + m_BaseUri = uri; + m_Prefixes[""] = RdfUri(m_BaseUri.ToString()); + } + + RdfUri RdfStorePrivate::GetBaseUri() const + { + return m_BaseUri; + } + + void RdfStorePrivate::AddPrefix(std::string prefix, RdfUri uri) + { + m_Prefixes[prefix] = uri; + } + + RdfStorePrivate::PrefixMap RdfStorePrivate::GetPrefixes() const + { + return m_Prefixes; + } + + void RdfStorePrivate::CleanUp() + { + // CleanUp old Store if there is one + if(m_Model) + librdf_free_model(m_Model); + if(m_Storage) + librdf_free_storage(m_Storage); + if(m_World) + librdf_free_world(m_World); + + // SetUp new Store + m_World = librdf_new_world(); + librdf_world_open(m_World); + + m_Storage = librdf_new_storage(m_World, "memory", 0, 0); + + if(!m_Storage) + { + mitkThrow() << "RDF Library Error"; + } + + m_Model = librdf_new_model(m_World, m_Storage, 0); + + if(!m_Model) + { + mitkThrow() << "RDF Library Error"; + } + } + + bool RdfStorePrivate::Add(RdfTriple triple) + { + librdf_statement* statement = RdfTripleToStatement(triple); + + if (!CheckComplete(statement)) + { + librdf_free_statement(statement); + return false; + } + + // Store already contains statement + if (Contains(triple)) return true; + + if (librdf_model_add_statement(m_Model, statement) != 0) { + librdf_free_statement(statement); + return false; + } + else + { + librdf_free_statement(statement); + return true; + } + } + + bool RdfStorePrivate::Remove(RdfTriple triple) + { + librdf_statement* statement = RdfTripleToStatement(triple); + + if (!CheckComplete(statement)) + { + librdf_free_statement(statement); + return false; + } + + // Store does not contain statement + if (!Contains(triple)) return true; + + if (librdf_model_remove_statement(m_Model, statement) != 0) { + librdf_free_statement(statement); + return false; + } + else + { + librdf_free_statement(statement); + return true; + } + return false; + } + + bool RdfStorePrivate::Contains(RdfTriple triple) + { + librdf_statement* statement = RdfTripleToStatement(triple); + + // if 0 there is no triple + if (librdf_model_contains_statement(m_Model, statement) == 0) { + librdf_free_statement(statement); + return false; + } + else + { + librdf_free_statement(statement); + return true; + } + return false; + } + + RdfStorePrivate::ResultMap RdfStorePrivate::Query(std::string sparqlQuery) const + { + RdfStorePrivate::ResultMap resultMap; + std::string completeQuery; + + for (PrefixMap::const_iterator i = m_Prefixes.begin(); i != m_Prefixes.end(); i++) + { + completeQuery += "PREFIX " + i->first + ": " + "<" + i->second.ToString() + "> "; + } + completeQuery += sparqlQuery; + + librdf_query* rdfQuery = librdf_new_query(m_World, "sparql", 0, (const unsigned char*) completeQuery.c_str(), 0); + + if (!rdfQuery) return resultMap; + + librdf_query_results* results = librdf_query_execute(rdfQuery, m_Model); + + if (!results) + { + librdf_free_query(rdfQuery); + return resultMap; + } + + if (!librdf_query_results_is_bindings(results)) + { + librdf_free_query_results(results); + librdf_free_query(rdfQuery); + return resultMap; + } + + while (!librdf_query_results_finished(results)) + { + int count = librdf_query_results_get_bindings_count(results); + + for (int i = 0; i < count; ++i) + { + const char *name = librdf_query_results_get_binding_name(results, i); + + if (!name) continue; + + std::string key = name; + + std::list list; + + if(!resultMap[key].empty()) + { + list = resultMap[key]; + } + + librdf_node *node = librdf_query_results_get_binding_value(results, i); + + list.push_front(LibRdfNodeToRdfNode(node)); + + resultMap[key] = list; + } + + librdf_query_results_next(results); + } + + librdf_free_query_results(results); + librdf_free_query(rdfQuery); + + return resultMap; + } + + void RdfStorePrivate::Save(std::string filename, std::string format) + { + if (format == "") format = "turtle"; + + librdf_uri* baseUri = RdfUriToLibRdfUri(m_BaseUri); + + librdf_serializer* s = librdf_new_serializer(m_World, format.c_str(), 0, 0); + + if(!s) + { + mitkThrow() << "RDF Library Error"; + } + + for (PrefixMap::const_iterator i = m_Prefixes.begin(); i != m_Prefixes.end(); i++) + { + librdf_serializer_set_namespace(s, RdfUriToLibRdfUri(i->second), i->first.c_str()); + } + + FILE* f = fopen(filename.c_str(), "w+"); + + librdf_serializer_serialize_model_to_file_handle(s, f, baseUri, m_Model); + + librdf_free_serializer(s); + librdf_free_uri(baseUri); + fclose(f); + } + + void RdfStorePrivate::Import(std::string url, std::string format) + { + std::string baseUri = m_BaseUri.ToString(); + + if (baseUri.empty()) + { + baseUri = url; + SetBaseUri(RdfUri(baseUri)); + } + + if (format == "") format= "turtle"; + + // Redland uses file paths like file:YOURPATH ( Example: file:D:/home/readme.txt ) + librdf_uri* uri = librdf_new_uri(m_World, (const unsigned char*) url.c_str()); + + librdf_uri* libRdfBaseUri = librdf_new_uri(m_World, (const unsigned char*) baseUri.c_str()); + + librdf_parser* p = librdf_new_parser(m_World, format.c_str(), 0, 0); + + if(!p) + { + mitkThrow() << "RDF Library Error"; + } + + if (librdf_parser_parse_into_model(p, uri, libRdfBaseUri, m_Model) != 0 ) + { + librdf_free_parser(p); + MITK_ERROR << "Parsing into Model failed."; + return; + } + + int namespaces = librdf_parser_get_namespaces_seen_count(p); + + for (int i = 0; i < namespaces; i++) { + const char* prefixChar = librdf_parser_get_namespaces_seen_prefix(p, i); + + if ( !prefixChar ) continue; + + std::string prefix = prefixChar; + RdfUri uri = LibRdfUriToRdfUri(librdf_parser_get_namespaces_seen_uri(p, i)); + + if (uri == RdfUri()) return; + + RdfStorePrivate::PrefixMap::iterator it = m_Prefixes.find(prefix); + + // map iterator is equal to iterator-end so it is not already added + if (it == m_Prefixes.end()) { + AddPrefix(prefix, uri); + } + } + librdf_free_parser(p); + } + + bool RdfStorePrivate::CheckComplete(librdf_statement* statement) + { + if (librdf_statement_is_complete(statement) != 0) return true; + else return false; + } + + librdf_statement* RdfStorePrivate::RdfTripleToStatement(RdfTriple triple) const + { + librdf_node* subject = RdfNodeToLibRdfNode(triple.GetTripleSubject()); + librdf_node* predicate = RdfNodeToLibRdfNode(triple.GetTriplePredicate()); + librdf_node* object = RdfNodeToLibRdfNode(triple.GetTripleObject()); + + librdf_statement* statement = librdf_new_statement_from_nodes(m_World, subject, predicate, object); + if(!statement) return 0; + return statement; + } + + librdf_node* RdfStorePrivate::RdfNodeToLibRdfNode(RdfNode node) const + { + librdf_node* newNode = 0; + + switch (node.GetType()) + { + case RdfNode::NOTHING: + break; + case RdfNode::BLANK: + newNode = librdf_new_node_from_blank_identifier(m_World, (const unsigned char*) node.GetValue().c_str()); + break; + case RdfNode::LITERAL: + { + if (node.GetDatatype() != RdfUri()) + { + librdf_uri* typeUri = RdfUriToLibRdfUri(node.GetDatatype()); + newNode = librdf_new_node_from_typed_literal(m_World, (const unsigned char*) node.GetValue().c_str(), 0, typeUri); + } + else + { + newNode = librdf_new_node_from_literal(m_World, (const unsigned char*) node.GetValue().c_str(), 0, 0); + } + } + break; + case RdfNode::URI: + newNode = librdf_new_node_from_uri( m_World, librdf_new_uri(m_World, (const unsigned char*) node.GetValue().c_str()) ); + break; + default: + break; + } + return newNode; + } + + librdf_uri* RdfStorePrivate::RdfUriToLibRdfUri(RdfUri uri) const + { + librdf_uri* libUri = librdf_new_uri(m_World, (const unsigned char*) uri.ToString().c_str()); + if (!libUri) return 0; + return libUri; + } + + RdfTriple RdfStorePrivate::StatementToRdfTriple(librdf_statement* statement) const + { + librdf_node *subject = librdf_statement_get_subject(statement); + librdf_node *predicate = librdf_statement_get_predicate(statement); + librdf_node *object = librdf_statement_get_object(statement); + + RdfTriple triple(LibRdfNodeToRdfNode(subject), + LibRdfNodeToRdfNode(predicate), + LibRdfNodeToRdfNode(object)); + + return triple; + } + + RdfNode RdfStorePrivate::LibRdfNodeToRdfNode(librdf_node* node) const + { + RdfNode mitkNode; + + if (!node) return 0; + + if (librdf_node_is_resource(node)) + { + mitkNode.SetType(RdfNode::URI); + librdf_uri *uri = librdf_node_get_uri(node); + mitkNode.SetValue(LibRdfUriToRdfUri(uri).ToString()); + } + else if (librdf_node_is_literal(node)) + { + mitkNode.SetType(RdfNode::LITERAL); + std::string value = (const char*) librdf_node_get_literal_value(node); + if (!value.empty()) mitkNode.SetValue(value); + librdf_uri* typeUri = librdf_node_get_literal_value_datatype_uri(node); + if (typeUri) mitkNode.SetDatatype(LibRdfUriToRdfUri(typeUri)); + } + else if (librdf_node_is_blank(node)) + { + mitkNode.SetType(RdfNode::BLANK); + std::string str = (const char*) librdf_node_get_blank_identifier(node); + if (!str.empty()) mitkNode.SetValue(str); + } + return mitkNode; + } + + RdfUri RdfStorePrivate::LibRdfUriToRdfUri(librdf_uri* uri) const + { + std::string str = (const char*) librdf_uri_as_string(uri); + if (!str.empty()) return RdfUri(str); + + return RdfUri(); + } + + /**************************************************************************** + ******************************* mitkRdfStore ******************************** + ****************************************************************************/ + + typedef std::map > ResultMap; + typedef std::map PrefixMap; + + RdfStore::RdfStore() + :d(new RdfStorePrivate) + { + } + + RdfStore::~RdfStore() + { + delete d; + } + + void RdfStore::SetBaseUri(RdfUri uri) + { + d->SetBaseUri(uri); + } + + RdfUri RdfStore::GetBaseUri() const + { + return d->GetBaseUri(); + } + + void RdfStore::AddPrefix(std::string prefix, RdfUri uri) + { + d->AddPrefix(prefix, uri); + } + + PrefixMap RdfStore::GetPrefixes() const + { + return d->GetPrefixes(); + } + + void RdfStore::CleanUp() + { + d->CleanUp(); + } + + bool RdfStore::Add(RdfTriple triple) + { + return d->Add(triple); + } + + bool RdfStore::Remove(RdfTriple triple) + { + return d->Remove(triple); + } + + bool RdfStore::Contains(RdfTriple triple) + { + return d->Contains(triple); + } + + ResultMap RdfStore::Query(std::string query) const + { + return d->Query(query); + } + + void RdfStore::Save(std::string filename, std::string format) + { + d->Save(filename, format); + } + + void RdfStore::Import(std::string url, std::string format) + { + d->Import(url, format); + } +} // end of namespace mitk diff --git a/Modules/RDF/mitkRdfStore.h b/Modules/RDF/mitkRdfStore.h new file mode 100644 index 0000000000..e95eee9877 --- /dev/null +++ b/Modules/RDF/mitkRdfStore.h @@ -0,0 +1,127 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKRDFSTORE_H +#define MITKRDFSTORE_H + +#include +#include +#include + +#include "mitkRdfTriple.h" + +namespace mitk { + class RdfStorePrivate; + + /** + * \ingroup MitkRDFModule + */ + class MITKRDF_EXPORT RdfStore + { + public: + + typedef std::map > ResultMap; + typedef std::map PrefixMap; + + /** + * Construct a new triplestore. + */ + RdfStore(); + + /** + * Destruct a triplestore. + */ + ~RdfStore(); + + /** + * Set the base URI of the triplestore. + * @param uri An URI which is the base for the triplestore and for new nodes. + */ + void SetBaseUri(RdfUri uri); + + /** + * Get the base URI of the triplestore. + */ + RdfUri GetBaseUri() const; + + /** + * Add a new prefix which represents an URI as an abbreviation to the triplestore. + * @param prefix The short form of an URI. + * @param uri The full form of an URI. + */ + void AddPrefix(std::string prefix, RdfUri uri); + + /** + * Get a Map with all prefixes of the triplestore. + * @return A Map with all Prefixes of the RdfStore. + */ + PrefixMap GetPrefixes() const; + + /** + * Clean up the triplestore to the state of a new store. + */ + void CleanUp(); + + /** + * Add a new triple to the triplestore. + * Checks if the triplestore contains the triple. + * @param triple A triple. + * @return If the triple is successfully added or if the triplestore already contains the triple, true will be returned. If none of the previous options happen, false will be returned. + */ + bool Add(RdfTriple triple); + + /** + * Remove a triple from the triplestore. + * Checks if the triplestore contains the triple. + * @param triple A triple. + * @return If the triple is successfully removed or if the triplestore doesn't contain the triple, true will be returned. If none of the previous options happen, false will be returned. + */ + bool Remove(RdfTriple triple); + + /** + * Checks if the triplestore contains the triple. + * @param triple A triple. + * @return If the triplestore contains the triple, true will be returned. Otherwise, false will be returned. + */ + bool Contains(RdfTriple triple); + + /** + * Queries over the triplestore with the given SPARQL query. + * @param query A std:string which stands for a SPARQL query text. + * @return The result of the query will be returned as a map of keys with there values as lists of nodes. + */ + ResultMap Query(std::string query) const; + + /** + * Saves the current state of the triplestore in a file. The currently supported formats are: "ntriples", "turtle"(default), "nquads". + * @param filename A full filepath to the lokal storage. + * @param format One of the supported formats. Default: "turtle". + */ + void Save(std::string filename, std::string format = ""); + + /** + * Imports the state of the triplestore of an URL (URI). + * @param filename A full filepath to the lokal storage or http address as URL. A lokal file path has to look like "file:YOURPATH" ( Example: file:D:/home/readme.txt ). + * @param format The current supported formats are: "turtle" (default), "ntriples", "nquads". + */ + void Import(std::string url, std::string format = ""); + + private: + RdfStorePrivate* d; + }; +} + +#endif // MITKRDFSTORE_H diff --git a/Modules/RDF/mitkRdfTriple.cpp b/Modules/RDF/mitkRdfTriple.cpp new file mode 100644 index 0000000000..23ef8fcdbe --- /dev/null +++ b/Modules/RDF/mitkRdfTriple.cpp @@ -0,0 +1,92 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include "mitkRdfTriple.h" + +namespace mitk { + RdfTriple::RdfTriple() + { + } + + RdfTriple::RdfTriple(RdfNode subject, RdfNode predicate, RdfNode object) + : m_Subject(subject), m_Predicate(predicate), m_Object(object) + { + } + + RdfTriple::RdfTriple(RdfNode subject, RdfNode property, std::string value) + : m_Subject(subject), m_Predicate(property), m_Object(RdfNode(value)) + { + } + + RdfTriple::~RdfTriple() + { + } + + void RdfTriple::SetTripleSubject(RdfNode subject) + { + m_Subject = subject; + } + + void RdfTriple::SetTriplePredicate(RdfNode predicate) + { + m_Predicate = predicate; + } + + void RdfTriple::SetTripleObject(RdfNode object) + { + m_Object = object; + } + + void RdfTriple::SetTripleObject(std::string text) + { + mitk::RdfNode object = mitk::RdfNode(text); + m_Object = object; + } + + RdfNode RdfTriple::GetTripleSubject() const + { + return m_Subject; + } + + RdfNode RdfTriple::GetTriplePredicate() const + { + return m_Predicate; + } + + RdfNode RdfTriple::GetTripleObject() const + { + return m_Object; + } + + bool RdfTriple::operator==(const RdfTriple &u) const + { + if (this->m_Subject != u.m_Subject) return false; + if (this->m_Predicate != m_Predicate) return false; + if (this->m_Object != u.m_Object) return false; + return true; + } + + bool RdfTriple::operator!=(const RdfTriple &u) const + { + return !operator==(u); + } + + // Define outstream of a Triple + std::ostream & operator<<(std::ostream &out, const RdfTriple &t) + { + return out << "( " << t.GetTripleSubject() << " " << t.GetTriplePredicate() << " " << t.GetTripleObject() << " )"; + } +} // end of namespace mitk diff --git a/Modules/RDF/mitkRdfTriple.h b/Modules/RDF/mitkRdfTriple.h new file mode 100644 index 0000000000..ba52e14125 --- /dev/null +++ b/Modules/RDF/mitkRdfTriple.h @@ -0,0 +1,109 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKRDFTRIPLE_H +#define MITKRDFTRIPLE_H + +#include + +#include "mitkRdfNode.h" + +namespace mitk { + /** + * \ingroup MitkRDFModule + */ + class MITKRDF_EXPORT RdfTriple + { + public: + + /** + * Construct a empty invalid triple. + */ + RdfTriple(); + + /** + * Construct a normal triple with two nodes and an object property node between. + * @param subject A node. + * @param predicate A node which represents an object property. + * @param object A node. + */ + RdfTriple(RdfNode subject, RdfNode predicate, RdfNode object); + + /** + * Construct a normal triple with a node, a data property and a value. + * @param subject A node. + * @param predicate A node which represents a data property. + * @param value A text value. + */ + RdfTriple(RdfNode subject, RdfNode property, std::string value); + + virtual ~RdfTriple(); + + /** + * Set the subject of a triple. + * @param subject A node from type URI or BLANK. + */ + void SetTripleSubject(RdfNode subject); + + /** + * Set the predicate of a triple. + * @param predicate A node from type URI which can represent an object property or a data property. + */ + void SetTriplePredicate(RdfNode predicate); + + /** + * Set the object of a triple with an object property. + * @param object A node from type URI, BLANK or LITERAL. + */ + void SetTripleObject(RdfNode object); + + /** + * Set the object of a triple with a data property as text. + * @param text A literal value.. + */ + void SetTripleObject(std::string text); + + /** + * Get the subject of a triple. + * @return The subject of a triple. + */ + RdfNode GetTripleSubject() const; + + /** + * Get the predicate of a triple. + * @return The predicate of a triple. + */ + RdfNode GetTriplePredicate() const; + + /** + * Get the object of a triple. + * @return The object of a triple. + */ + RdfNode GetTripleObject() const; + + bool operator==(const RdfTriple &u) const; + bool operator!=(const RdfTriple &u) const; + + private: + RdfNode m_Subject; + RdfNode m_Predicate; + RdfNode m_Object; + }; + + MITKRDF_EXPORT std::ostream & operator<<(std::ostream &out, const RdfTriple &t); +} + +#endif // MITKRDFTRIPLE_H diff --git a/Modules/RDF/Testing/mitkRdfNodeTest.cpp b/Modules/RDF/mitkRdfUri.cpp similarity index 51% copy from Modules/RDF/Testing/mitkRdfNodeTest.cpp copy to Modules/RDF/mitkRdfUri.cpp index 7032b0ba50..55aebc512f 100644 --- a/Modules/RDF/Testing/mitkRdfNodeTest.cpp +++ b/Modules/RDF/mitkRdfUri.cpp @@ -1,52 +1,53 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ -#include "mitkTestingMacros.h" -#include -#include +#include "mitkRdfUri.h" -#include "mitkRdfNode.h" - -class mitkRdfNodeTestSuite : public mitk::TestFixture -{ - // List of Tests - CPPUNIT_TEST_SUITE(mitkRdfNodeTestSuite); - - MITK_TEST(TestDummy); - - CPPUNIT_TEST_SUITE_END(); - -public: +namespace mitk { + RdfUri::RdfUri() + { + } - void setUp() override + RdfUri::RdfUri(std::string uri) + : m_Uri(uri) { } - void tearDown() override + RdfUri::~RdfUri() { } - // Test functions + std::string RdfUri::ToString() const + { + return m_Uri; + } - void TestDummy() + void RdfUri::SetUri(std::string uri) { - mitk::RdfNode node; - CPPUNIT_ASSERT(node.dummy() == true); + m_Uri = uri; } -}; + bool RdfUri::operator==(const RdfUri &u) const + { + if (this->m_Uri.compare(u.m_Uri) != 0) return false; + return true; + } -MITK_TEST_SUITE_REGISTRATION(mitkRdfNode) + bool RdfUri::operator!=(const RdfUri &u) const + { + return !operator==(u); + } +} // end of namespace mitk diff --git a/Modules/RDF/mitkRdfUri.h b/Modules/RDF/mitkRdfUri.h new file mode 100644 index 0000000000..0c4ddcbf2d --- /dev/null +++ b/Modules/RDF/mitkRdfUri.h @@ -0,0 +1,65 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef MITKRDFURI_H +#define MITKRDFURI_H + +#include + +#include + +namespace mitk { + /** + * \ingroup MitkRDFModule + */ + class MITKRDF_EXPORT RdfUri + { + public: + + /** + * Construct a empty RdfUri. + */ + RdfUri(); + + /** + * Construct a RdfUri with a value. + * @param uri A std:string which represents the transfer parameter from a URI. + */ + explicit RdfUri(std::string uri); + + virtual ~RdfUri(); + + /** + * Returns the string value of an RdfUri. + * @return Value of RdfUri as std:string. + */ + std::string ToString() const; + + /** + * Set the value of an RdfUri. + * @param uri New value of an RdfUri. + */ + void SetUri(std::string uri); + + bool operator==(const RdfUri &u) const; + bool operator!=(const RdfUri &u) const; + + private: + std::string m_Uri; + }; +} + +#endif // MITKRDFURI_H diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp index e3767d44ff..1ca741921f 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.cpp @@ -1,174 +1,177 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkRenderWindow.h" // Qt #include // mitk #include #include #include #include #include // vtk #include // #include "OpenIGTLinkExample.h" //igtl #include "igtlStringMessage.h" #include "igtlTrackingDataMessage.h" const std::string OpenIGTLinkExample::VIEW_ID = "org.mitk.views.OpenIGTLinkExample"; void OpenIGTLinkExample::SetFocus() { } OpenIGTLinkExample::~OpenIGTLinkExample() { - this->GetDataStorage()->Remove(m_DemoNodeT1); - this->GetDataStorage()->Remove(m_DemoNodeT2); - this->GetDataStorage()->Remove(m_DemoNodeT3); + this->DestroyPipeline(); } void OpenIGTLinkExample::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); // connect the widget items with the methods connect( m_Controls.butStart, SIGNAL(clicked()), this, SLOT(Start()) ); connect( &m_Timer, SIGNAL(timeout()), this, SLOT(UpdatePipeline())); //Setup the pipeline this->CreatePipeline(); } void OpenIGTLinkExample::CreatePipeline() { //create a new OpenIGTLinkExample Client m_IGTLClient = mitk::IGTLClient::New(); m_IGTLClient->SetName("OIGTL Example Client Device"); //create a new OpenIGTLinkExample Device source m_IGTLDeviceSource = mitk::IGTLDeviceSource::New(); //set the client as the source for the device source m_IGTLDeviceSource->SetIGTLDevice(m_IGTLClient); m_IGTLDeviceSource->RegisterAsMicroservice(); //create a filter that converts OpenIGTLinkExample messages into navigation data m_IGTLMsgToNavDataFilter = mitk::IGTLMessageToNavigationDataFilter::New(); //create a visualization filter m_VisFilter = mitk::NavigationDataObjectVisualizationFilter::New(); //we expect a tracking data message with three tools. Since we cannot change //the outputs at runtime we have to set it manually. m_IGTLMsgToNavDataFilter->SetNumberOfExpectedOutputs(3); //connect the filters with each other //the OpenIGTLinkExample messages will be passed to the first filter that converts //it to navigation data, then it is passed to the visualization filter that //will visualize the transformation m_IGTLMsgToNavDataFilter->ConnectTo(m_IGTLDeviceSource); m_VisFilter->ConnectTo(m_IGTLMsgToNavDataFilter); //create an object that will be moved respectively to the navigation data - m_DemoNodeT1 = mitk::DataNode::New(); - m_DemoNodeT1->SetName("DemoNode IGTLExmpl T1"); - m_DemoNodeT2 = mitk::DataNode::New(); - m_DemoNodeT2->SetName("DemoNode IGTLExmpl T2"); - m_DemoNodeT3 = mitk::DataNode::New(); - m_DemoNodeT3->SetName("DemoNode IGTLExmpl T3"); - - //create small sphere and use it as surface - mitk::Surface::Pointer mySphere = mitk::Surface::New(); - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - mySphere->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - m_DemoNodeT1->SetData(mySphere); - - mitk::Surface::Pointer mySphere2 = mySphere->Clone(); - m_DemoNodeT2->SetData(mySphere2); - mitk::Surface::Pointer mySphere3 = mySphere->Clone(); - m_DemoNodeT3->SetData(mySphere3); - - // add node to DataStorage - this->GetDataStorage()->Add(m_DemoNodeT1); - this->GetDataStorage()->Add(m_DemoNodeT2); - this->GetDataStorage()->Add(m_DemoNodeT3); - - //use this sphere as representation object - m_VisFilter->SetRepresentationObject(0, mySphere); - m_VisFilter->SetRepresentationObject(1, mySphere2); - m_VisFilter->SetRepresentationObject(2, mySphere3); + for (size_t i = 0; i < m_IGTLMsgToNavDataFilter->GetNumberOfIndexedOutputs(); i++) + { + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + QString name("DemoNode IGTLProviderExmpl T"); + name.append(QString::number(i)); + newNode->SetName(name.toStdString()); + + //create small sphere and use it as surface + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(2.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + mySphere->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + newNode->SetData(mySphere); + + this->GetDataStorage()->Add(newNode); + + m_VisFilter->SetRepresentationObject(i, mySphere); + + m_DemoNodes.append(newNode); + } } void OpenIGTLinkExample::DestroyPipeline() { - m_VisFilter = NULL; - this->GetDataStorage()->Remove(m_DemoNodeT1); - this->GetDataStorage()->Remove(m_DemoNodeT2); - this->GetDataStorage()->Remove(m_DemoNodeT3); + m_VisFilter = nullptr; + foreach(mitk::DataNode::Pointer node, m_DemoNodes) + { + this->GetDataStorage()->Remove(node); + } + this->m_DemoNodes.clear(); } void OpenIGTLinkExample::Start() { if ( this->m_Controls.butStart->text().contains("Start Pipeline") ) { - m_Timer.setInterval(90); + m_Timer.setInterval(this->m_Controls.visualizationUpdateRateSpinBox->value()); m_Timer.start(); this->m_Controls.butStart->setText("Stop Pipeline"); + this->m_Controls.visualizationUpdateRateSpinBox->setEnabled(true); } else { m_Timer.stop(); igtl::StopTrackingDataMessage::Pointer stopStreaming = igtl::StopTrackingDataMessage::New(); this->m_IGTLClient->SendMessage(stopStreaming.GetPointer()); this->m_Controls.butStart->setText("Start Pipeline"); + this->m_Controls.visualizationUpdateRateSpinBox->setEnabled(false); } } void OpenIGTLinkExample::UpdatePipeline() { //update the pipeline m_VisFilter->Update(); //update the boundings mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); //Update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); + + //check if the timer interval changed + static int previousValue = 0; + int currentValue = this->m_Controls.visualizationUpdateRateSpinBox->value(); + if (previousValue != currentValue) + { + m_Timer.setInterval(currentValue); + previousValue = currentValue; + } } diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h index 828ca7580c..683dbca839 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExample.h @@ -1,84 +1,78 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef OpenIGTLinkExample_h #define OpenIGTLinkExample_h #include #include #include "ui_OpenIGTLinkExampleControls.h" #include "mitkIGTLClient.h" #include "mitkIGTLServer.h" #include "mitkIGTLDeviceSource.h" #include "mitkNavigationDataObjectVisualizationFilter.h" #include "mitkIGTLMessageToNavigationDataFilter.h" #include "qtimer.h" /** \brief OpenIGTLinkExample \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class OpenIGTLinkExample : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: ~OpenIGTLinkExample(); static const std::string VIEW_ID; protected slots: void Start(); void UpdatePipeline(); protected: virtual void CreateQtPartControl(QWidget *parent) override; virtual void SetFocus() override; void CreatePipeline(); void DestroyPipeline(); Ui::OpenIGTLinkExampleControls m_Controls; mitk::IGTLClient::Pointer m_IGTLClient; mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource; mitk::IGTLMessageToNavigationDataFilter::Pointer m_IGTLMsgToNavDataFilter; mitk::NavigationDataObjectVisualizationFilter::Pointer m_VisFilter; - mitk::DataNode::Pointer m_DemoNodeT1; - mitk::DataNode::Pointer m_DemoNodeT2; - mitk::DataNode::Pointer m_DemoNodeT3; - - //REMOVE LATER -// mitk::IGTLServer::Pointer m_IGTLServer; -// mitk::IGTLDeviceSource::Pointer m_IGTLDeviceSource2; + QList m_DemoNodes; QTimer m_Timer; }; #endif // OpenIGTLinkExample_h diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExampleControls.ui b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExampleControls.ui index 7151dd71b8..b883ea63d7 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExampleControls.ui +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkExampleControls.ui @@ -1,52 +1,79 @@ OpenIGTLinkExampleControls 0 0 668 392 0 0 QmitkTemplate Start Pipeline + + + + + + false + + + Visualization Update Rate: + + + + + + + false + + + 200 + + + 10 + + + + + Qt::Vertical 20 220 diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp index eb9a447021..e2f3a4e553 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.cpp @@ -1,239 +1,240 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkRenderWindow.h" // Qt #include #include // mitk #include #include #include -#include #include #include +#include // vtk #include // #include "OpenIGTLinkProviderExample.h" //igtl #include "igtlStringMessage.h" const std::string OpenIGTLinkProviderExample::VIEW_ID = "org.mitk.views.OpenIGTLinkProviderExample"; OpenIGTLinkProviderExample::~OpenIGTLinkProviderExample() { - this->GetDataStorage()->Remove(m_DemoNodeT1); - this->GetDataStorage()->Remove(m_DemoNodeT2); - this->GetDataStorage()->Remove(m_DemoNodeT3); + this->DestroyPipeline(); } void OpenIGTLinkProviderExample::SetFocus() { } void OpenIGTLinkProviderExample::CreateQtPartControl( QWidget *parent ) { // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); // connect the widget items with the methods connect( m_Controls.butStart, SIGNAL(clicked()), this, SLOT(Start()) ); connect( m_Controls.butOpenNavData, SIGNAL(clicked()), this, SLOT(OnOpenFile()) ); connect( &m_VisualizerTimer, SIGNAL(timeout()), this, SLOT(UpdateVisualization())); } void OpenIGTLinkProviderExample::CreatePipeline() { + //create a navigation data player object that will play nav data from a + //recorded file + m_NavDataPlayer = mitk::NavigationDataPlayer::New(); + + //set the currently read navigation data set + m_NavDataPlayer->SetNavigationDataSet(m_NavDataSet); + //create a new OpenIGTLink Client m_IGTLServer = mitk::IGTLServer::New(); m_IGTLServer->SetName("OIGTL Provider Example Device"); //create a new OpenIGTLink Device source m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); //set the OpenIGTLink server as the source for the device source m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); //register the provider so that it can be configured with the IGTL manager //plugin. This could be hardcoded but now I already have the fancy plugin. m_IGTLMessageProvider->RegisterAsMicroservice(); //create a filter that converts navigation data into IGTL messages m_NavDataToIGTLMsgFilter = mitk::NavigationDataToIGTLMessageFilter::New(); + //connect the filters with each other + //the navigation data player reads a file with recorded navigation data, + //passes this data to a filter that converts it into a IGTLMessage. + //The provider is not connected because it will search for fitting services. + //Once it found the filter it will automatically connect to it (this is not + // implemented so far, check m_StreamingConnector for more information). + m_NavDataToIGTLMsgFilter->ConnectTo(m_NavDataPlayer); + //define the operation mode for this filter, we want to send tracking data //messages m_NavDataToIGTLMsgFilter->SetOperationMode( mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg); // mitk::NavigationDataToIGTLMessageFilter::ModeSendTransMsg); //set the name of this filter to identify it easier m_NavDataToIGTLMsgFilter->SetName("Tracking Data Source From Example"); //register this filter as micro service. The message provider looks for //provided IGTLMessageSources, once it found this microservice and someone //requested this data type then the provider will connect with this filter //automatically (this is not implemented so far, check m_StreamingConnector //for more information) m_NavDataToIGTLMsgFilter->RegisterAsMicroservice(); - //create a navigation data player object that will play nav data from a - //recorded file - m_NavDataPlayer = mitk::NavigationDataPlayer::New(); - - //set the currently read navigation data set - m_NavDataPlayer->SetNavigationDataSet(m_NavDataSet); - - //connect the filters with each other - //the navigation data player reads a file with recorded navigation data, - //passes this data to a filter that converts it into a IGTLMessage. - //The provider is not connected because it will search for fitting services. - //Once it found the filter it will automatically connect to it (this is not - // implemented so far, check m_StreamingConnector for more information). - m_NavDataToIGTLMsgFilter->ConnectTo(m_NavDataPlayer); + //also create a visualize filter to visualize the data + m_NavDataVisualizer = mitk::NavigationDataObjectVisualizationFilter::New(); //create an object that will be moved respectively to the navigation data - m_DemoNodeT1 = mitk::DataNode::New(); - m_DemoNodeT1->SetName("DemoNode IGTLProviderExmpl T1"); - m_DemoNodeT2 = mitk::DataNode::New(); - m_DemoNodeT2->SetName("DemoNode IGTLProviderExmpl T2"); - m_DemoNodeT3 = mitk::DataNode::New(); - m_DemoNodeT3->SetName("DemoNode IGTLProviderExmpl T3"); - - //create small sphere and use it as surface - mitk::Surface::Pointer mySphere = mitk::Surface::New(); - vtkSphereSource *vtkData = vtkSphereSource::New(); - vtkData->SetRadius(2.0f); - vtkData->SetCenter(0.0, 0.0, 0.0); - vtkData->Update(); - mySphere->SetVtkPolyData(vtkData->GetOutput()); - vtkData->Delete(); - m_DemoNodeT1->SetData(mySphere); - - mitk::Surface::Pointer mySphere2 = mySphere->Clone(); - m_DemoNodeT2->SetData(mySphere2); - mitk::Surface::Pointer mySphere3 = mySphere->Clone(); - m_DemoNodeT3->SetData(mySphere3); - - // add node to DataStorage - this->GetDataStorage()->Add(m_DemoNodeT1); - this->GetDataStorage()->Add(m_DemoNodeT2); - this->GetDataStorage()->Add(m_DemoNodeT3); + for (size_t i = 0; i < m_NavDataPlayer->GetNumberOfIndexedOutputs(); i++) + { + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + QString name("DemoNode IGTLProviderExmpl T"); + name.append(QString::number(i)); + newNode->SetName(name.toStdString()); + + //create small sphere and use it as surface + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(2.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + mySphere->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + newNode->SetData(mySphere); + + this->GetDataStorage()->Add(newNode); + + m_NavDataVisualizer->SetRepresentationObject(i, mySphere); + + m_DemoNodes.append(newNode); + } //initialize the streaming connector //the streaming connector is checking if the data from the filter has to be //streamed. The message provider is used for sending the messages. // m_StreamingConnector.Initialize(m_NavDataToIGTLMsgFilter.GetPointer(), // m_IGTLMessageProvider); - //also create a visualize filter to visualize the data - m_NavDataVisualizer = mitk::NavigationDataObjectVisualizationFilter::New(); - m_NavDataVisualizer->SetRepresentationObject(0, mySphere); - m_NavDataVisualizer->SetRepresentationObject(1, mySphere2); - m_NavDataVisualizer->SetRepresentationObject(2, mySphere3); + + //connect the visualization with the navigation data player m_NavDataVisualizer->ConnectTo(m_NavDataPlayer); //start the player this->Start(); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); } void OpenIGTLinkProviderExample::DestroyPipeline() { - m_NavDataPlayer->StopPlaying(); - this->GetDataStorage()->Remove(m_DemoNodeT1); + if (m_NavDataPlayer.IsNotNull()) + { + m_NavDataPlayer->StopPlaying(); + } + foreach(mitk::DataNode::Pointer node, m_DemoNodes) + { + this->GetDataStorage()->Remove(node); + } + this->m_DemoNodes.clear(); } void OpenIGTLinkProviderExample::Start() { if ( this->m_Controls.butStart->text().contains("Start") ) { m_NavDataPlayer->SetRepeat(true); m_NavDataPlayer->StartPlaying(); this->m_Controls.butStart->setText("Stop Playing Recorded Navigation Data "); //start the visualization this->m_VisualizerTimer.start(100); } else { m_NavDataPlayer->StopPlaying(); this->m_Controls.butStart->setText("Start Playing Recorded Navigation Data "); //stop the visualization this->m_VisualizerTimer.stop(); } } void OpenIGTLinkProviderExample::OnOpenFile(){ - mitk::NavigationDataReaderXML::Pointer reader = mitk::NavigationDataReaderXML::New(); // FIXME Filter for correct files and use correct Reader QString fileName = QFileDialog::getOpenFileName(NULL, "Open Navigation Data Set", "", "XML files (*.xml)"); if ( fileName.isNull() ) { return; } // user pressed cancel try { - m_NavDataSet = reader->Read(fileName.toStdString()); + m_NavDataSet = dynamic_cast (mitk::IOUtil::LoadBaseData(fileName.toStdString()).GetPointer()); } catch ( const mitk::Exception &e ) { MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); QMessageBox::critical(0, "Error Reading File", "The file '" + fileName +"' could not be read.\n" + e.GetDescription() ); return; } this->m_Controls.butStart->setEnabled(true); //Setup the pipeline this->CreatePipeline(); // Update Labels // m_Controls->m_LblFilePath->setText(fileName); // m_Controls->m_LblTools->setText(QString::number(m_NavDataSet->GetNumberOfTools())); } void OpenIGTLinkProviderExample::UpdateVisualization() { //update the filter this->m_NavDataVisualizer->Update(); //update the bounds mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(this->GetDataStorage()); //update rendering mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } diff --git a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h index 5eec46d953..0fbf1e3809 100644 --- a/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h +++ b/Plugins/org.mitk.gui.qt.igtlplugin/src/internal/OpenIGTLinkProviderExample.h @@ -1,85 +1,83 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef OpenIGTLinkProviderExample_h #define OpenIGTLinkProviderExample_h #include #include #include #include "ui_OpenIGTLinkProviderExampleControls.h" #include "mitkIGTLServer.h" #include "mitkIGTLMessageProvider.h" #include "mitkNavigationDataToIGTLMessageFilter.h" #include "mitkNavigationDataPlayer.h" #include "mitkNavigationDataObjectVisualizationFilter.h" #include "qtimer.h" /** \brief OpenIGTLinkProviderExample \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. \sa QmitkAbstractView \ingroup ${plugin_target}_internal */ class OpenIGTLinkProviderExample : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: ~OpenIGTLinkProviderExample(); static const std::string VIEW_ID; protected slots: void Start(); void OnOpenFile(); void UpdateVisualization(); protected: virtual void CreateQtPartControl(QWidget *parent) override; virtual void SetFocus() override; void CreatePipeline(); void DestroyPipeline(); Ui::OpenIGTLinkProviderExampleControls m_Controls; mitk::IGTLServer::Pointer m_IGTLServer; mitk::IGTLMessageProvider::Pointer m_IGTLMessageProvider; mitk::NavigationDataToIGTLMessageFilter::Pointer m_NavDataToIGTLMsgFilter; mitk::NavigationDataPlayer::Pointer m_NavDataPlayer; mitk::NavigationDataObjectVisualizationFilter::Pointer m_NavDataVisualizer; - mitk::DataNode::Pointer m_DemoNodeT1; - mitk::DataNode::Pointer m_DemoNodeT2; - mitk::DataNode::Pointer m_DemoNodeT3; + QList m_DemoNodes; mitk::NavigationDataSet::Pointer m_NavDataSet; QmitkIGTLStreamingConnector m_StreamingConnector; QTimer m_VisualizerTimer; }; #endif // OpenIGTLinkProviderExample_h diff --git a/Plugins/org.mitk.gui.qt.igttracking/files.cmake b/Plugins/org.mitk.gui.qt.igttracking/files.cmake index 0d6a7d71e5..174752791c 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/files.cmake +++ b/Plugins/org.mitk.gui.qt.igttracking/files.cmake @@ -1,50 +1,54 @@ set(SRC_CPP_FILES ) set(INTERNAL_CPP_FILES mitkPluginActivator.cpp QmitkMITKIGTNavigationToolManagerView.cpp QmitkMITKIGTTrackingToolboxView.cpp QmitkNavigationDataPlayerView.cpp + IGTNavigationToolCalibration.cpp ) set(UI_FILES src/internal/QmitkMITKIGTNavigationToolManagerViewControls.ui src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui src/internal/QmitkNavigationDataPlayerViewControls.ui + src/internal/IGTNavigationToolCalibrationControls.ui ) set(MOC_H_FILES src/internal/mitkPluginActivator.h src/internal/QmitkMITKIGTNavigationToolManagerView.h src/internal/QmitkMITKIGTTrackingToolboxView.h src/internal/QmitkNavigationDataPlayerView.h + src/internal/IGTNavigationToolCalibration.h ) # list of resource files which can be used by the plug-in # system without loading the plug-ins shared library, # for example the icon used in the menu and tabs for the # plug-in views in the workbench set(CACHED_RESOURCE_FILES resources/iconNavigationDataPlayer.png resources/iconNavigationToolManager.xpm resources/iconTrackingToolBox.xpm + resources/iconNavigationToolCalibration.xpm plugin.xml ) # list of Qt .qrc files which contain additional resources # specific to this plugin set(QRC_FILES - + resources/IGTNavigationToolCalibration.qrc ) set(CPP_FILES ) foreach(file ${SRC_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/${file}) endforeach(file ${SRC_CPP_FILES}) foreach(file ${INTERNAL_CPP_FILES}) set(CPP_FILES ${CPP_FILES} src/internal/${file}) endforeach(file ${INTERNAL_CPP_FILES}) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/plugin.xml b/Plugins/org.mitk.gui.qt.igttracking/plugin.xml index 3c2f94738e..33b1096837 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/plugin.xml +++ b/Plugins/org.mitk.gui.qt.igttracking/plugin.xml @@ -1,19 +1,23 @@ + \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/resources/Description.jpg b/Plugins/org.mitk.gui.qt.igttracking/resources/Description.jpg new file mode 100644 index 0000000000..9edda7e362 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.igttracking/resources/Description.jpg differ diff --git a/Plugins/org.mitk.gui.qt.igttracking/resources/Description.svg b/Plugins/org.mitk.gui.qt.igttracking/resources/Description.svg new file mode 100644 index 0000000000..9d97e3cd29 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igttracking/resources/Description.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Tool to calibrate +Calibration pointer + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.igttracking/resources/IGTNavigationToolCalibration.qrc b/Plugins/org.mitk.gui.qt.igttracking/resources/IGTNavigationToolCalibration.qrc new file mode 100644 index 0000000000..c589033619 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igttracking/resources/IGTNavigationToolCalibration.qrc @@ -0,0 +1,5 @@ + + + Description.svg + + diff --git a/Plugins/org.mitk.gui.qt.igttracking/resources/iconNavigationToolCalibration.xpm b/Plugins/org.mitk.gui.qt.igttracking/resources/iconNavigationToolCalibration.xpm new file mode 100644 index 0000000000..92e83dbbeb --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igttracking/resources/iconNavigationToolCalibration.xpm @@ -0,0 +1,692 @@ +/* XPM */ +static char * icon_xpm[] = { +"563 551 138 2", +" c None", +". c #FFFFFF", +"+ c #E6EBF0", +"@ c #6481A4", +"# c #385D8A", +"$ c #456791", +"% c #7790AF", +"& c #AEBDCF", +"* c #E0E6ED", +"= c #899FBA", +"- c #517199", +"; c #839AB6", +"> c #BAC7D6", +", c #ECF0F4", +"' c #7D95B3", +") c #5E7CA0", +"! c #90A4BE", +"~ c #C7D1DE", +"{ c #F9FAFB", +"] c #C1CCDA", +"^ c #6A86A8", +"/ c #A1B3C8", +"( c #D3DBE5", +"_ c #A8B8CB", +": c #3B6292", +"< c #3E6697", +"[ c #4B6C95", +"} c #385E8C", +"| c #4D7EB8", +"1 c #4F80BB", +"2 c #4977AF", +"3 c #436DA1", +"4 c #3D6494", +"5 c #96A9C1", +"6 c #4F81BD", +"7 c #4774AB", +"8 c #416B9D", +"9 c #3B6191", +"0 c #708BAB", +"a c #DAE0E9", +"b c #4E7FBA", +"c c #4C7CB5", +"d c #4672A8", +"e c #40689A", +"f c #3A5F8D", +"g c #4571A6", +"h c #4A79B1", +"i c #4470A5", +"j c #F3F5F8", +"k c #3A608F", +"l c #3E628E", +"m c #CDD6E2", +"n c #4876AD", +"o c #3E6798", +"p c #4C7DB6", +"q c #9BAEC4", +"r c #436FA3", +"s c #4673AA", +"t c #4978B1", +"u c #B4C2D3", +"v c #57769C", +"w c #4B7AB3", +"x c #3D6596", +"y c #436EA2", +"z c #416C9F", +"A c #406A9C", +"B c #3E6595", +"C c #3D6493", +"D c #3C6391", +"E c #3B618F", +"F c #3A608E", +"G c #406898", +"H c #3F6595", +"I c #3A608D", +"J c #3F6796", +"K c #3E6493", +"L c #395E8B", +"M c #3C6291", +"N c #406897", +"O c #3E6594", +"P c #3B6190", +"Q c #395E8C", +"R c #385D8B", +"S c #406797", +"T c #3D6492", +"U c #3F6797", +"V c #3D6391", +"W c #4E7099", +"X c #4371A7", +"Y c #6C96C8", +"Z c #416FA4", +"` c #4A7DB9", +" . c #4A7EBB", +".. c #DDE7F2", +"+. c #3F699C", +"@. c #4573AB", +"#. c #83A7D1", +"$. c #3B6291", +"%. c #3D6697", +"&. c #3D6798", +"*. c #416EA2", +"=. c #4777B2", +"-. c #EEF3F9", +";. c #7DA3CE", +">. c #9AB7D9", +",. c #C6D6E9", +"'. c #5082BD", +"). c #F9FBFD", +"!. c #AFC6E1", +"~. c #5B8AC1", +"{. c #9FBBDB", +"]. c #8EAFD5", +"^. c #B5CAE3", +"/. c #A4BEDD", +"(. c #94B3D7", +"_. c #5586BF", +":. c #618EC4", +"<. c #729ACA", +"[. c #4676B0", +"}. c #517CAE", +"|. c #487AB5", +"1. c #3F689C", +"2. c #487BB6", +"3. c #416BA0", +"4. c #D3DFEC", +"5. c #4373A9", +"6. c #89ABD3", +"7. c #416CA1", +"8. c #497CB8", +"9. c #3E689A", +"0. c #4D74A4", +"a. c #BBCEE5", +"b. c #6692C6", +"c. c #AAC2DF", +"d. c #789FCC", +"e. c #CCDAEC", +"f. c #E8EFF6", +"g. c #E3EBF4", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + @ # $ % & * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # # # # - ; > , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # # # # # # # # ) ! ~ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # # # # # # # # # # # ^ / ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # # # # # # # # # # # # # # $ % & * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # : < # # # # # # # # # # # # # # - ; > , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # } | 1 2 3 4 # # # # # # # # # # # # # # ) 5 ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # 3 6 6 6 6 | 7 8 9 # # # # # # # # # # # # # # 0 / a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # } b 6 6 6 6 6 6 6 c d e f # # # # # # # # # # # # # $ ' & + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # g 6 6 6 6 6 6 6 6 6 6 6 h i < # # # # # # # # # # # # # # - = > j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # k 1 6 6 6 6 6 6 6 6 6 6 6 6 6 1 2 3 4 # # # # # # # # # # # # # # ) 5 ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | 7 8 9 # # # # # # # # # # # # # # 0 / a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # k 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c d e f # # # # # # # # # # # # # $ ' & , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h i < # # # # # # # # # # # # # $ m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # k 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 2 3 4 # # # # # # # # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | 7 8 9 # # # # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # : 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c g # # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + # # # # o 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # # j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ^ # # # # : 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 9 # # # @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ) # # # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p # # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ) # # # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ) # # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + - # # # # # s 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 f # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + - # # # # # s 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + - # # # # # s 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 r # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + - # # # # } 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # # } 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { @ # # # # } 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # } t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # l { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 k # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ l # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 i # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * $ # # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 < # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , - # # # # x 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 } # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ) # # # # 9 | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # f c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # # j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # } t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 9 # # # @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # # 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p # # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { v # # # # y 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # # x 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # } c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 f # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + $ # # # # s 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 r # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # 9 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # # t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # # x 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # l { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # } p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 k # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # 4 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 i # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , [ # # # # w 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 f # y 6 6 6 6 6 6 6 6 6 < # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # z 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # n 6 6 6 6 6 6 6 1 } # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # k | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # # 4 6 6 6 6 6 6 6 n # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ # # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d # # # # # # # h 6 6 6 6 6 6 3 # # # # j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # 4 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 r # # # # # # # # e 6 6 6 6 6 6 9 # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j [ # # # # w 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 r # # # # # # # # # # w 6 6 6 6 p # # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # z 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 r # # # # # ) m # # # # e 6 6 6 6 d # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , # # # # k | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # # # 0 { . @ # # # # w 6 6 6 e # # # $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # # # 0 { . . ] # # # # e 6 6 6 f # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # 4 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 y # # # # # 0 { . . . . ) # # # # w 6 t # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d # # # # # ; { . . . . . ] # # # # e 6 r # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # k 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # # ; . . . . . . . . ) # # # # c x # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h } # # # # % . . . . . . . . . ] # # # # 8 # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # k 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c f # # # # @ { . . . . . . . . . . ) # # # # # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | 9 # # # # - j . . . . . . . . . . . ] # # # # # # # l { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + ~ q q ; ^ ^ ^ % q q ] a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ; ^ ^ ^ ^ ^ ^ ^ ^ ; q q ~ m a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # k 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b 4 # # # # [ + . . . . . . . . . . . . . v # # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a q v # # # # # # # # # # # # # - = m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # # # # # # # # # # # # # @ ^ 5 q m ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 o # # # # l a . . . . . . . . . . . . . . _ # # # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j 5 - # # # # # # # # # # # # # # # # # # # $ ; , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # # # # # # # # # # # # # # # # # # $ ^ q > * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # k 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 z # # # # # ~ . . . . . . . . . . . . . . . { [ # # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { _ $ # # # # # # # # # # # # # # # # # # # # # # # l ! j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ^ ! u + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # # u . . . . . . . . . . . . . . . . . _ # # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > [ # # # # # # # # o r r n t t t 2 r r A } # # # # # # # $ q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # B B B B B B C D D E F F # # # # # # # # # # # # # # # # # # # - ; u + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # } | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c } # # # # q . . . . . . . . . . . . . . . . . . { [ # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { = # # # # # # } A s b 6 6 6 6 6 6 6 6 6 6 6 1 n 8 k # # # # # # ^ j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G H B D D F I # # # # # # # # # # # # # # # - ; ] { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 : # # # # ' . . . . . . . . . . . . . . . . . . . . ~ l # $ , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j @ # # # # # } y b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 g f # # # # # - a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G J K D F L # # # # # # # # # # # # l ' u j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # # c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # # v { . . . . . . . . . . . . . . . . . . . . . , m j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a - # # # # # 8 | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b r } # # # # l > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G J K M I # # # # # # # # # # # # 0 & j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j l # # # x 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # # l * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # # : c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | < # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N O M I # # # # # # # # # # l ; ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # s 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h } # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + - # # # # < b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # # l m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N K P L # # # # # # # # # v & j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # } 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b 9 # # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ) # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 } # # # $ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G H M Q # # # # # # # # l ; ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # z 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # # v { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # y 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # v j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G J D Q # # # # # # # # v / , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # # h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # # l * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 i # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G O E R # # # # # # # # ' ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { $ # # # : 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c } # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # 4 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 A # # # l a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G S T Q # # # # # # # # - u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 < # # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # f p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 4 # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B E R # # # # # # # ) ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # } | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d # # # # v { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 2 # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G S T Q # # # # # # # ) ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * # # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | f # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # 9 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B E R # # # # # # ^ m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 A # # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G U M R # # # # # # ^ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # f 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # [ j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # 9 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 A # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G U E # # # # # # # % a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j # # # # 8 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b k # # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # y 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G J E # # # # # # # ' + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 z # # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { $ # # # h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b } # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G H E # # # # # # # 5 { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # } 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # k 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 o # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B F # # # # # # v ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { $ # # # o 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 : # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # z 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G O I # # # # # # 5 { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # # @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G K Q # # # # # v ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 k # # # l a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N M # # # # # # ; j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # x 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 y # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B Q # # # # # [ ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + # # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | } # # # [ , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 } # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N M # # # # # # ; j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # w 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 f # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B Q # # # # # [ ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # 9 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | } # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 # # # l . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N D R # # # # # ; { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 z # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G J I # # # # # ) + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G D R # # # # $ m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # y 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G J I # # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # 9 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # x 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 z # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N P # # # # # = { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , # # # # | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 k # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G V # # # # # @ , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j # # # # i 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c # # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B L # # # # [ ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # < 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 y # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G J I # # # # l u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b } # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + # # # # c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 k # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G S E # # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # : 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 r # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G D # # # # # ^ j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # A 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 k # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | } # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # # # F F F D D T B B S G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G K L # # # # - + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # 4 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 z # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # # # # # # # # # # # # # # # # # I F M D B B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G H Q # # # # - + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 x # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # y 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # # # # # # # # # # # # # # # # # # # # # # I P V B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G S F # # # # - + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # s 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w } # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a ' # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Q E C J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # - + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # 4 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , [ # # # } t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | 9 # # # l a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * m m / q 5 ^ ^ l # # # # # # # # # # # # # # # # # Q E C J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # - + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | } # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # f h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | 4 # # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m ~ q ! ^ [ # # # # # # # # # # # # # # Q M H G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # - + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . $ # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 i # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # } 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h k # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ~ q 0 - # # # # # # # # # # # # L P O G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # - + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , # # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d } # # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ~ 5 @ # # # # # # # # # # # L E O G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # [ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( # # # # 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # # x t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p e # # # # # 0 { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { m q ^ # # # # # # # # # # Q D U G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # $ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # # c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 y # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > l # # # # # e w 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | z # # # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { > ; $ # # # # # # # # # E O G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # $ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 9 # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a - # # # # # # 8 n 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 2 z } # # # # # l > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m ! - # # # # # # # # Q D J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G D # # # # $ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # 9 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ^ # # # # # # # # e d t c 6 6 6 6 6 | t s A f # # # # # # # W a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a = $ # # # # # # # # F C G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G D # # # # - , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 # # # < 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 z # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ ) # # # # # # # # # # # # x # # # # # # # # # # # # k X Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { u @ # # # # # # # # L M J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G D # # # # @ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # 8 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 k # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u - # # # # # # # # # # # # # # # # # # # # # f Z ` . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * = $ # # # # # # # # E J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G M # # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # i 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 2 # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ ! v # # # # # # # # # # # # # # # k +.@.` . . . .#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { u @ # # # # # # # # P U G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + # # # # 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * _ % ^ ) # # # # # $.%.&.*.=. . . . . . . . . .-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * = $ # # # # # # R M S G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N I # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 } # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ;. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { u ) # # # # # # L D S G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G J L # # # l a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,. . . . . . . . . . . . . .'.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] - # # # # # # L V N G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B R # # # [ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # l { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u - # # # # # # L T G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G C # # # # ) { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 9 # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . !. . . . . . . . . . . . . .~.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { _ [ # # # # # # Q C G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G M # # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # } 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { _ $ # # # # # # I J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # 9 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . {. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j q $ # # # # # R D G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N I # # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # 9 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 A # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j 5 l # # # # # I J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G J L # # # l a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # < 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 f # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ]. . . . . . . . . . . . . .#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ; # # # # # R M N G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B R # # # v { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 # # # < 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . .-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ [ # # # # # Q B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G C # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ;. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ; # # # # # # M N G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G P # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # 8 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 < # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,. . . . . . . . . . . . . .'.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ [ # # # # # Q B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N Q # # # - j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # z 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 } # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ; # # # # # # M N G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B # # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . !. . . . . . . . . . . . . .~.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m v # # # # # Q H G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G M # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 i # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 5 # # # # # L K G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N Q # # # [ , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 A # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . {. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( v # # # # # D G G G G G G G G G G G G G G G G G G G G G G G G G G G G G H R # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . # # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 : # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { = # # # # # E S G G G G G G G G G G G G G G G G G G G G G G G G G G G G D # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ]. . . . . . . . . . . . . .#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & l # # # # I J G G G G G G G G G G G G G G G G G G G G G G G G G G G G I # # # l + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h # # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . .-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( [ # # # # L B G G G G G G G G G G G G G G G G G G G G G G G G G G G J R # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # # j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ;. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , @ # # # # # V G G G G G G G G G G G G G G G G G G G G G G G G G G G T # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # z 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,. . . . . . . . . . . . . .'.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ; # # # # # P N G G G G G G G G G G G G G G G G G G G G G G G G G G F # # # l + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # 8 6 6 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # I U G G G G G G G G G G G G G G G G G G G G G G G G G J L # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # 8 6 6 6 6 6 6 6 6 6 6 6 6 6 1 } # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . !. . . . . . . . . . . . . .~.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m $ # # # # L H G G G G G G G G G G G G G G G G G G G G G G G G G C # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ # # # 8 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + ) # # # # R O G G G G G G G G G G G G G G G G G G G G G G G G G I # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # 8 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . {. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ' # # # # R O G G G G G G G G G G G G G G G G G G G G G G G G B # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # R O G G G G G G G G G G G G G G G G G G G G G G G G E # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # < 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ]. . . . . . . . . . . . . .#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # R O G G G G G G G G G G G G G G G G G G G G G G G J R # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # < 6 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . .-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # R O G G G G G G G G G G G G G G G G G G G G G G G M # # # $ , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # x 6 6 6 6 6 6 6 6 6 6 6 6 6 f # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ;. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # R O G G G G G G G G G G G G G G G G G G G G G G U L # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # 9 6 6 6 6 6 6 6 6 6 6 6 6 b # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,. . . . . . . . . . . . . .'.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # R O G G G G G G G G G G G G G G G G G G G G G G V # # # l * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # 6 6 6 6 6 6 6 6 6 6 6 6 c # # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # # C G G G G G G G G G G G G G G G G G G G G G N Q # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # | 6 6 6 6 6 6 6 6 6 6 6 2 # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^. . . . . . . . . . . . . .~.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # # C G G G G G G G G G G G G G G G G G G G G G K # # # # ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # # w 6 6 6 6 6 6 6 6 6 6 6 d # # # # { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u l # # # # C G G G G G G G G G G G G G G G G G G G G G F # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * # # # # 2 6 6 6 6 6 6 6 6 6 6 6 y # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . /. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ l # # # # C G G G G G G G G G G G G G G G G G G G G H # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j # # # # d 6 6 6 6 6 6 6 6 6 6 6 A # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ l # # # R B G G G G G G G G G G G G G G G G G G G G P # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l # # # r 6 6 6 6 6 6 6 6 6 6 6 x # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (. . . . . . . . . . . . . .#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ l # # # L J G G G G G G G G G G G G G G G G G G G U R # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # 8 6 6 6 6 6 6 6 6 6 6 6 k # # # = . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # Q S G G G G G G G G G G G G G G G G G G G M # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # o 6 6 6 6 6 6 6 6 6 6 6 # # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # F G G G G G G G G G G G G G G G G G G G J # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # 4 6 6 6 6 6 6 6 6 6 6 1 # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,. . . . . . . . . . . . . ._.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # # M G G G G G G G G G G G G G G G G G G G E # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # k 6 6 6 6 6 6 6 6 6 6 p # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { @ # # # # T G G G G G G G G G G G G G G G G G G B # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # 6 6 6 6 6 6 6 6 6 6 p # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^. . . . . . . . . . . . . .:.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , - # # # R B G G G G G G G G G G G G G G G G G G I # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # c 6 6 6 6 6 6 6 6 6 w # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # L J G G G G G G G G G G G G G G G G G C # # # l { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # n 6 6 6 6 6 6 6 6 6 t # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . /. . . . . . . . . . . . . .<.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # Q S G G G G G G G G G G G G G G G G N L # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { # # # # y 6 6 6 6 6 6 6 6 6 t # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # F G G G G G G G G G G G G G G G G G V # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # e 6 6 6 6 6 6 6 6 6 s # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (. . . . . . . . . . . . . .#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # # M G G G G G G G G G G G G G G G G U R # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # 9 6 6 6 6 6 6 6 6 6 s # # # # , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { @ # # # # C G G G G G G G G G G G G G G G G M # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # b 6 6 6 6 6 6 6 6 d # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , - # # # L J G G G G G G G G G G G G G G G J # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # # t 6 6 6 6 6 6 6 6 r # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,. . . . . . . . . . . . . ._.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( l # # # F G G G G G G G G G G G G G G G G E # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , # # # # g 6 6 6 6 6 6 6 6 r # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # V G G G G G G G G G G G G G G G O # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [ # # # z 6 6 6 6 6 6 6 6 r # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^. . . . . . . . . . . . . .:.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # R J G G G G G G G G G G G G G G G I # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 # # # 4 6 6 6 6 6 6 6 6 r # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + $ # # # I N G G G G G G G G G G G G G G T # # # @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # } 6 6 6 6 6 6 6 6 r # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . /. . . . . . . . . . . . . .<.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # D G G G G G G G G G G G G G G U # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # # c 6 6 6 6 6 6 6 r # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # R B G G G G G G G G G G G G G G F # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # 7 6 6 6 6 6 6 6 r # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (. . . . . . . . . . . . . .#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j [ # # # Q N G G G G G G G G G G G G G T # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l # # # 3 6 6 6 6 6 6 6 g # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # M G G G G G G G G G G G G G U # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # 4 6 6 6 6 6 6 6 s # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # B G G G G G G G G G G G G G F # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # b 6 6 6 6 6 6 s # # # # { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,. . . . . . . . . . . . . ._.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { v # # # Q S G G G G G G G G G G G G T # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # s 6 6 6 6 6 6 s # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # E G G G G G G G G G G G G U # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # 8 6 6 6 6 6 6 s # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^. . . . . . . . . . . . . .:.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # O G G G G G G G G G G G G F # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # 9 6 6 6 6 6 6 2 # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # I G G G G G G G G G G G G T # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # p 6 6 6 6 6 t # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . /. . . . . . . . . . . . . .<.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * l # # # T G G G G G G G G G G G U # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # s 6 6 6 6 6 t # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # L N G G G G G G G G G G G F # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . $ # # # 8 6 6 6 6 6 c # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (. . . . . . . . . . . . . .#.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , $ # # # M G G G G G G G G G G G T # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # 9 6 6 6 6 6 | # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # R U G G G G G G G G G G U # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # w 6 6 6 6 6 # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { - # # # E G G G G G G G G G G G F # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + # # # # g 6 6 6 6 6 9 # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,. . . . . . . . . . . . . ._.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # H G G G G G G G G G G V # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # e 6 6 6 6 6 4 # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # I G G G G G G G G G G B # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # } 1 6 6 6 6 o # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^. . . . . . . . . . . . .[.}.q q ^ ^ ^ ^ ! q _ m { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # K G G G G G G G G G N R # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # # 7 6 6 6 6 8 # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . .@.+.k # # # # # # # # # # # # l % u j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # Q N G G G G G G G G G F # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # e 6 6 6 6 y # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . /. . . . . .|.1.f # # # # # # # # # # # # # # # # # # # % m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # V G G G G G G G G G D # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # } b 6 6 6 g # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . .2.3.# # # # # # # # # # # # # # # # # # # # # # # # 0 a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # L U G G G G G G G G B # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # s 6 6 6 s # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . (. .*.f # # # # # # # f 8 r g t t t t d r 3 9 # # # # # # # # ; j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j [ # # # M G G G G G G G G S # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { $ # # # o 6 6 6 t # # # # ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.%.# # # # # # k z t 6 6 6 6 6 6 6 6 6 6 6 6 c r : # # # # # # - a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # R U G G G G G G G G I # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # # | 6 6 c # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * v # # # # # k g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 2 4 # # # # # $ ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # D G G G G G G G G M # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # d 6 6 1 # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m $ # # # # } r b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s k # # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # L N G G G G G G G K # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [ # # # x 6 6 6 : # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # # # < | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 3 # # # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # C G G G G G G G S # # # # j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # # p 6 6 e # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * $ # # # # z 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d } # # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # I G G G G G G G G Q # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( # # # # i 6 6 y # # # l . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t f # # # l ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + # # # # O G G G G G G G E # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # 4 6 6 7 # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ^ # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h } # # # [ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # E G G G G G G G C # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # c 6 w # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # z 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 # # # # @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( # # # # J G G G G G G J # # # # { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * # # # # 3 6 1 # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # < 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 y # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # M G G G G G G G L # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # } b 6 : # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # } | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # R U G G G G G G F # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # g 6 e # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # V G G G G G G M # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # 9 6 y # # # # { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # k 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # L N G G G G G T # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # n 7 # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w } # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # K G G G G G B # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , # # # # < w # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # 9 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # I G G G G G S # # # l . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # h } # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # y 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # B G G G G G L # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( # # # # z < # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { $ # # # h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 } # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 # # # M G G G G G F # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # } z # # # # j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # k 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # Q G G G G G P # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # # o # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # z 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j l # # # B G G G G D # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # f # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 # # # M G G G G C # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # # # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # L G G G G B # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # # # # # # j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j l # # # B G G G J # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # # # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 } # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # P G G G G # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - # # # p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 f # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # L G G G G L # # # , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # # # @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 # # # l . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # B G G G I # # # ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # # # # l { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # P G G G E # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # L G G G E # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # # # # # = . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # y 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # B G G D # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # x 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 z # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # P G G V # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # # # # ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , # # # # | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 9 # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # L G G C # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # l { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # B G O # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # < 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 r # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # D G B # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + # # # # w 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 k # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # F G J # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # e 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # l j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # R N S # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # # # @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | } # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . $ # # # H G # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # 4 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # V G # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h } # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # E G # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p k # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # L G # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + $ # # # f c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 4 # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l # # # H # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # $ , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m l # # # 9 p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 o # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # C # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # f t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p 4 # # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # E # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # } d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h k # # # # @ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # Q # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j l # # # # # $ , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ' # # # # # e p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b y } # # # # ) j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # # 3 | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 g f # # # # # ' { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ # # # # # f 3 h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c g 9 # # # # # # *.... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # # # l + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a v # # # # # # # k 8 n t 1 6 6 6 6 6 t t 3 : # # # # # # # f 5. .6.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & [ # # # # # # # # # # # k 9 # # # # # # # # # # # } 7.8. . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { q $ # # # # # # # # # # # # # # # # # # # # # +.2. . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # # # # l + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j > ; $ # # # # # # # # # # # # # # # 9.X 2. . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # # # # ^ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m 5 ^ ^ [ # # # # l ^ ^ 0.5.` . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .b.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # # # # # l ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .d.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # # # # [ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # # # # # # @ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . . . . .6.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # # # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # # R # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # F # # # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . . . . . . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # I E # # # # $ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # V I # # # # v j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .b.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + l # # # L J L # # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # V B R # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .d.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # L U C # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # M G M # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . . . . .6.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # R U N F # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # E G S I # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # # H G S I # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . . . . . . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # E G G S I # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [ # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # # B G G S I # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .b.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # I G G G S I # # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # T G G G S I # # # # l ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .d.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # R J G G G S I # # # # l ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # F G G G G U Q # # # # l ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . . . . .6.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { - # # # # T G G G G J Q # # # # l > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . v # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # R J G G G G J Q # # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .>.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # F G G G G G J Q # # # # # ' { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . . . . . . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { v # # # # D G G G G G J I # # # # # ) , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( # # # # R J G G G G G S F # # # # # - a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .b.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # I G G G G G G G M # # # # # l ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [ # # # # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { v # # # # D G G G G G G G T # # # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .;.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + # # # f # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( l # # # R J G G G G G G G O L # # # # # ; { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # < # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # I N G G G G G G G J Q # # # # # ^ j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . . . . .].. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # r # # # # . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ) # # # # D G G G G G G G G S I # # # # # - * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # 7 # # # l . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # R B G G G G G G G G N E # # # # # $ u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .{.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l # # # w # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # Q U G G G G G G G G G D # # # # # # % j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . . . . . . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # 9 p # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ) # # # # I N G G G G G G G G G C R # # # # # [ ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # 8 c # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * $ # # # # P G G G G G G G G G G B L # # # # # # = { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # s t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # # V G G G G G G G G G G S E # # # # # # v ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j l # # # | t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # R B G G G G G G G G G G G C L # # # # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .;.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # x 6 2 # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # # L J G G G G G G G G G G G U F # # # # # # @ * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # r 6 s # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ) # # # # Q N G G G G G G G G G G G G D R # # # # # l u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . . . . .].. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . $ # # # h 6 s # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + [ # # # # E G G G G G G G G G G G G G J Q # # # # # # 0 , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # k 6 6 d # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( l # # # # D G G G G G G G G G G G G G N M # # # # # # $ / { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .{.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # 8 6 6 r # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # # K G G G G G G G G G G G G G G O L # # # # # # - ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . . . . . . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # 7 6 6 r # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # R J G G G G G G G G G G G G G G S E # # # # # # # ^ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + # # # } b 6 6 8 # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ^ # # # # Q S G G G G G G G G G G G G G G G C L # # # # # # # = , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # < 6 6 6 < # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # # I S G G G G G G G G G G G G G G G S M R # # # # # # $ / { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 # # # i 6 6 6 : # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * l # # # # I S G G G G G G G G G G G G G G G G U E # # # # # # # - ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .;.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , # # # # c 6 6 6 } # # # j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # # I N G G G G G G G G G G G G G G G G G B I # # # # # # # ^ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # : 6 6 6 b # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # # F N G G G G G G G G G G G G G G G G G G C L # # # # # # # ; a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . . . . .].. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # i 6 6 6 w # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # # F N G G G G G G G G G G G G G G G G G G N D L # # # # # # # ^ ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # | 6 6 6 2 # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # # F N G G G G G G G G G G G G G G G G G G G U P # # # # # # # # v u { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .{.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # < 6 6 6 6 d # # # = . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # # F N G G G G G G G G G G G G G G G G G G G G H F # # # # # # # # [ q , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ! $ # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . . . . . . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . [ # # # s 6 6 6 6 r # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # # F N G G G G G G G G G G G G G G G G G G G G G O F # # # # # # # # l ; * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a ; # # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # } 1 6 6 6 6 8 # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # # E G G G G G G G G G G G G G G G G G G G G G G G J E # # # # # # # # # 0 m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] ^ # # # # # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # A 6 6 6 6 6 < # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # # E G G G G G G G G G G G G G G G G G G G G G G G G U M L # # # # # # # # ) & , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j & v # # # # # # # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # 2 6 6 6 6 6 : # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # # E G G G G G G G G G G G G G G G G G G G G G G G G G S V Q # # # # # # # # # ^ & , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( ; l # # # # # # # # # # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .;.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # k 6 6 6 6 6 6 } # # # { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # # E N G G G G G G G G G G G G G G G G G G G G G G G G G G C I # # # # # # # # # # % u j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j & v # # # # # # # # # I C M # # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ^ # # # 3 6 6 6 6 6 p # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # # # I U G G G G G G G G G G G G G G G G G G G G G G G G G G G B E # # # # # # # # # # # % u j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + & 0 # # # # # # # # # # E B G G U R # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . . . . .].. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a # # # # w 6 6 6 6 6 n # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # # # L H G G G G G G G G G G G G G G G G G G G G G G G G G G G G J P L # # # # # # # # # # # % u j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * / ) # # # # # # # # # # L P J G G G G G M # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # 4 6 6 6 6 6 6 y # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # # # R K G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B P L # # # # # # # # # # # 0 q m { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ] = - # # # # # # # # # # # F C G G G G G G G G U R # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .{.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # 7 6 6 6 6 6 6 o # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # # D G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G K E L # # # # # # # # # # # # @ ! ] , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( q @ # # # # # # # # # # # # Q D J G G G G G G G G G G G E # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . . . . . . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # k 1 6 6 6 6 6 6 f # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] $ # # # # # E N G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G K E L # # # # # # # # # # # # # v ; u * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ~ q ^ l # # # # # # # # # # # # Q P B G G G G G G G G G G G G G G H # # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { l # # # g 6 6 6 6 6 6 p # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a - # # # # # I S G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G K E L # # # # # # # # # # # # # # $ % q m + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + m q % [ # # # # # # # # # # # # # # Q M H G G G G G G G G G G G G G G G G G G E # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # } 1 6 6 6 6 6 6 n # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ) # # # # # Q J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G C M I # # # # # # # # # # # # # # # # # @ % q > m + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j m > q % @ # # # # # # # # # # # # # # # # # I D J G G G G G G G G G G G G G G G G G G G G G H # # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # 3 6 6 6 6 6 6 6 y # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ' # # # # # L O G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N O D F # # # # # # # # # # # # # # # # # # # # # ^ ^ = q q q ~ m m m , . . . . . . . . m m m m ~ q q 5 ^ ^ [ # # # # # # # # # # # # # # # # # # # # I M K N G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .;.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > # # # } | 6 6 6 6 6 6 6 o # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # # # T G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B D E L # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # I M C U G G G G G G G G G G G G G G G G G G G G G G G G G G G G G H # # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # A 6 6 6 6 6 6 6 6 f # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > l # # # # # E S G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G J T E Q # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Q E D B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G E # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . . . . .].. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # w 6 6 6 6 6 6 6 p # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( $ # # # # # L B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B C D F Q # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Q F D V B U G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G H # # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # e 6 6 6 6 6 6 6 6 n # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + v # # # # # # M N G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B B C D D F F Q # # # # # # # # # # # # # # # # # # # # # # # Q F F D D C B J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G I # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .{.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # n 6 6 6 6 6 6 6 6 y # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j % # # # # # # I J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N B B B B B B B B B B B B B B B H G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G K # # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . . . . . . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # 4 6 6 6 6 6 6 6 6 6 x # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ l # # # # # R T G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G I # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # 2 6 6 6 6 6 6 6 6 b # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * @ # # # # # # F U G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G K # # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # e 6 6 6 6 6 6 6 6 6 n # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # # # L O G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G I # # # # , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # w 6 6 6 6 6 6 6 6 6 8 # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( v # # # # # # E N G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G K # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .;.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { [ # # # 8 6 6 6 6 6 6 6 6 6 6 9 # # # m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { = # # # # # # Q B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G I # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .... . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # } | 6 6 6 6 6 6 6 6 6 p # # # l { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ [ # # # # # # E U G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G K # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . . . . .].. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , $ # # # 3 6 6 6 6 6 6 6 6 6 6 g # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j % # # # # # # R D N G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N L # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . .'.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # k b 6 6 6 6 6 6 6 6 6 6 e # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u $ # # # # # # L C G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G V # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . . . . . . . . . .{.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , l # # # g 6 6 6 6 6 6 6 6 6 6 1 } # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ^ # # # # # # # I B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N L # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . . . . . . . . . . . .~.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # 9 1 6 6 6 6 6 6 6 6 6 6 t # # # - . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ v # # # # # # # E J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G V # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y . . . . . . . . . . . . .!.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # n 6 6 6 6 6 6 6 6 6 6 6 r # # # = . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ $ # # # # # # R M S G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N L # # # $ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a. . . . . . . . . . . . . .Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j [ # # # < 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ! # # # # # # # L V G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G V # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ).~. . . . . . . . . . . . . .,.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # } c 6 6 6 6 6 6 6 6 6 6 6 | # # # l j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * 0 # # # # # # # Q C N G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G N L # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . c. . . . . . . . . . . . . .;.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m # # # # i 6 6 6 6 6 6 6 6 6 6 6 6 d # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m ) # # # # # # # L D S G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G V # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . -.'. . . . . . . . . . . . . .f.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { v # # # 4 1 6 6 6 6 6 6 6 6 6 6 6 6 x # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & [ # # # # # # # R P J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G U R # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . >. . . . . . . . . . .'.].g.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # h 6 6 6 6 6 6 6 6 6 6 6 6 c # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j 5 l # # # # # # # # E B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G M # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . .~./.-.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 r # # # 0 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + = l # # # # # # # # I C G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G C I # # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . #. . . . . .b.a.).. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # 9 1 6 6 6 6 6 6 6 6 6 6 6 6 6 9 # # # > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j / [ # # # # # # # # Q V S G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G S D L # # # # # # $ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . e. . . .;.e.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # 2 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # l { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { u v # # # # # # # # L M H G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G H P R # # # # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . <.(.f.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( l # # # 8 6 6 6 6 6 6 6 6 6 6 6 6 6 6 z # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ 0 # # # # # # # # # Q M H G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G S T Q # # # # # # # # # 0 m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # k | 6 6 6 6 6 6 6 6 6 6 6 6 6 1 f # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * ; l # # # # # # # # # Q D J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G O E R # # # # # # # # l ; * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 # # # [ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , q [ # # # # # # # # # # Q D J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B M Q # # # # # # # # # [ q , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { u ) # # # # # # # # # # # Q V J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G B P L # # # # # # # # # # @ u { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( l # # # x 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | } # # # ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + _ ) # # # # # # # # # # # I M K U G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G U C E L # # # # # # # # # # $ = * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # f p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + / v # # # # # # # # # # # # Q E C J G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G S K M Q # # # # # # # # # # # # @ u { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * q v # # # # # # # # # # # # # L E D B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G J C M I # # # # # # # # # # # # # ) / * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * 5 - # # # # # # # # # # # # # # # F D K B G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G U O D F L # # # # # # # # # # # # # # ^ & + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( l # # # x 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 o # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a 5 ^ # # # # # # # # # # # # # # # # # Q F D T B H G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G G S B C D E I # # # # # # # # # # # # # # # # $ ' u j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # f p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m q 0 l # # # # # # # # # # # # # # # # # # # # F F M D D C B B B H G G G G G G G G G G J B B B B T D M F F L # # # # # # # # # # # # # # # # # # # # ^ / a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { @ # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a _ ' [ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ^ ! ] { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * u ; v # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ) = & a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # o 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # v . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m > q % ^ # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # ) 0 q > m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | } # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , m ~ q q % ^ - # # # # # # # # # # # # # # # # # # # # # # # # $ ^ ^ ! q _ m * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m l # # # k p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 i # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * m m m > q q q q q q q q u m m m m * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * $ # # # } w 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 k # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # # 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { @ # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 0 # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 0 # # # # o 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 k # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 0 # # # # 4 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # l a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 0 # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | f # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 0 # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # l , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 0 # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p } # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 0 # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 e # # # [ { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 0 # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w # # # # _ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ) # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 < # # # ) { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a - # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ $ # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 4 # # # ) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # # e 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # # a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p } # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ' # # # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 < # # # l + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j @ # # # # f 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a - # # # # 9 c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p } # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ l # # # # x b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 o # # # l + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j 0 # # # # # A 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ [ # # # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | f # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 5 # # # # # k 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 o # # # l + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * @ # # # # # o | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u $ # # # # } i 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | f # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j / > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , 0 # # # # # : h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 < # # # l + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + [ # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ $ # # # # # 8 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # # & . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j v # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a @ # # # # # } s 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n # # # # % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ^ # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 5 # # # # # # x c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c f # # # - j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ [ # # # # # f g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 : # # # l a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , % # # # # # # A | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 A # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . j q $ # # # # # 9 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . { _ $ # # # # # # y 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h } # # # ) { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # } y # # # ^ . . . . . . . . . . . . . . . . . . . . . . . { _ [ # # # # # # x c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | k # # # $ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + $ # # # # s t # # # ^ . . . . . . . . . . . . . . . . . . . . . . u [ # # # # # # f d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 < # # # # ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # # r 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . u - # # # # # # f r b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 8 # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { @ # # # # 8 6 6 t # # # ^ . . . . . . . . . . . . . . . . . { u - # # # # # # f r b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 y # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . % # # # # o 1 6 6 t # # # ^ . . . . . . . . . . . . . . . + ! $ # # # # # # } 3 | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 i # # # # - , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # 4 b 6 6 6 t # # # ^ . . . . . . . . . . . . . > 0 # # # # # # # } 3 | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # [ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # 9 | 6 6 6 6 t # # # ^ . . . . . . . . . . , / - # # # # # # # # 8 p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 2 } # # # $ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # f c 6 6 6 6 6 t # # # ^ . . . . . . . . m ' # # # # # # # # k y p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h } # # # l m . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m l # # # } t 6 6 6 6 6 6 t # # # ^ . . . . . m = [ # # # # # # # # x s 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w f # # # # ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * $ # # # # 7 6 6 6 6 6 6 6 t # # # ^ . . ] = [ # # # # # # # # } z c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p 9 # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , - # # # # i 6 6 6 6 6 6 6 6 t # # # - ; $ # # # # # # # # # : d b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b 9 # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ) # # # # z 6 6 6 6 6 6 6 6 6 t # # # # # # # # # # # # f 8 h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b 4 # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 0 # # # # o 6 6 6 6 6 6 6 6 6 6 t # # # # # # # # # f 8 n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p 9 # # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # # x 1 6 6 6 6 6 6 6 6 6 6 p # # # # # # k z n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w 9 # # # # 0 { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # 9 b 6 6 6 6 6 6 6 6 6 6 6 6 o # # k z t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w f # # # # ' { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # f p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 2 } # # # # ; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ l # # # } h 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 } # # # # 5 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a $ # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s # # # # # / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + - # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 r # # # # # u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ) # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 3 # # # # l > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { 0 # # # # A 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b < # # # # l ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # # < 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w 9 # # # # $ a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . q # # # # : b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d } # # # # - a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # k p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 z # # # # # ^ j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ # # # # } w 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | x # # # # # ! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a l # # # # 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t f # # # # $ > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + [ # # # # d 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 g # # # # # v * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j v # # # # r 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | o # # # # # % j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ^ # # # # 8 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s f # # # # # q . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ' # # # # o 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | o # # # # # $ ~ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # 4 b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s f # # # # # @ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # 9 p 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | o # # # # # l / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] # # # # f w 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 s f # # # # # @ * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( l # # # } 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 | o # # # # # l / . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + $ # # # # s 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 g f # # # # # ^ * . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j - # # # # i 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 d k # # # # # $ u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # z 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 n 9 # # # # # # 0 , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ) # # # # n 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t 4 # # # # # # [ u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # g 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w < # # # # # # l q j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # # 3 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c e # # # # # # # ! , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u # # # # # e 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 h 8 # # # # # # # % + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ $ # # # # 4 | 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 7 x # # # # # # # ^ ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a - # # # # 9 w 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 b i 9 # # # # # # # ) ] . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ) # # # # f 2 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 p z } # # # # # # # - u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { % # # # # # s 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 2 o # # # # # # # # ^ > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # # y 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c r : # # # # # # # l ; a . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _ # # # # # A 1 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 c r : # # # # # # # # [ q , . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ] l # # # # x b 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w 3 : # # # # # # # # # ) u . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a [ # # # # 9 c 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 w 3 9 # # # # # # # # # # ' ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + ) # # # # f t 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 2 9 # # # # # # # # # # % u j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j 0 # # # # } 7 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 1 } # # # # # # # # % u j . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ; # # # # # i 6 6 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # # # l ' > { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . / # # # # # 8 1 6 6 6 6 6 6 6 6 6 6 6 6 6 t # # # - > { . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > l # # # # < b 6 6 6 6 6 6 6 6 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ( $ # # # # : p 6 6 6 6 6 6 6 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + v # # # # f w 6 6 6 6 6 6 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j ^ # # # # } n 6 6 6 6 6 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { ' # # # # # g 6 6 6 6 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5 # # # # # z 6 6 6 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . u l # # # # o b 6 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . m $ # # # # 4 p 6 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . * - # # # # 9 w 6 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j @ # # # # f 2 6 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . { % # # # # # d 6 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ! # # # # # 3 t # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & # # # # # : # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ $ # # # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . a - # # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . , ) # # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . j 0 # # # # ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . = # # # ' . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . & [ ^ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "}; diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp new file mode 100644 index 0000000000..7849f7008b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.cpp @@ -0,0 +1,558 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#include + +// Blueberry +#include +#include + +// Qmitk +#include "IGTNavigationToolCalibration.h" + +// mitk +#include +#include +#include +#include +#include + +// Qt +#include +#include + +//vtk +#include + + +const std::string IGTNavigationToolCalibration::VIEW_ID = "org.mitk.views.igtnavigationtoolcalibration"; + +IGTNavigationToolCalibration::IGTNavigationToolCalibration() +{} + +IGTNavigationToolCalibration::~IGTNavigationToolCalibration() +{ +//The following code is required due to a bug in the point list widget. +//If this is removed, MITK crashes when closing the view: +m_Controls.m_RegistrationLandmarkWidget->SetPointSetNode(NULL); +m_Controls.m_CalibrationLandmarkWidget->SetPointSetNode(NULL); +} + +void IGTNavigationToolCalibration::SetFocus() +{ + +} + +void IGTNavigationToolCalibration::OnToolCalibrationMethodChanged(int index) +{ + UpdateManualToolTipCalibrationView(); + m_Controls.m_CalibrationMethodsWidget->setCurrentIndex(index); + m_IndexCurrentCalibrationMethod = index; +} + +void IGTNavigationToolCalibration::CreateQtPartControl( QWidget *parent ) +{ + //initialize manual tool editing widget + m_ManualToolTipEditWidget = new QmitkNavigationToolCreationAdvancedWidget(parent); + m_ManualToolTipEditWidget->setWindowFlags(Qt::Tool | Qt::WindowStaysOnTopHint); + m_ManualToolTipEditWidget->setWindowTitle("Edit Tool Tip Manually"); + m_ManualToolTipEditWidget->setModal(false); + m_ManualToolTipEditWidget->SetDataStorage(this->GetDataStorage()); + + m_TrackingTimer = new QTimer(this); + + // create GUI widgets from the Qt Designer's .ui file + m_Controls.setupUi( parent ); + connect( m_Controls.m_SetToolToCalibrate, SIGNAL(clicked()), this, SLOT(SetToolToCalibrate()) ); + connect( m_Controls.m_SetPointer, SIGNAL(clicked()), this, SLOT(SetCalibrationPointer()) ); + connect( m_TrackingTimer, SIGNAL(timeout()), this, SLOT(UpdateTrackingTimer())); + connect( m_Controls.m_AddLandmark, SIGNAL(clicked()), this, SLOT(AddLandmark())); + connect( m_Controls.m_SaveCalibratedTool, SIGNAL(clicked()), this, SLOT(SaveCalibratedTool())); + connect( m_Controls.m_AddPivotPose, SIGNAL(clicked()), this, SLOT(OnAddPivotPose())); + connect( m_Controls.m_ComputePivot, SIGNAL(clicked()), this, SLOT(OnComutePivot())); + connect( m_Controls.m_UseComputedPivotPoint, SIGNAL(clicked()), this, SLOT(OnUseComutedPivotPoint())); + connect( m_Controls.m_StartEditTooltipManually, SIGNAL(clicked()), this, SLOT(OnStartManualToolTipCalibration())); + connect( (QObject*)(m_ManualToolTipEditWidget), SIGNAL(RetrieveDataForManualToolTipManipulation()), this, SLOT(OnRetrieveDataForManualTooltipManipulation()) ); + connect( (QObject*)(m_ManualToolTipEditWidget), SIGNAL(DialogCloseRequested()), this, SLOT(OnProcessManualTooltipEditDialogCloseRequest()) ); + connect( m_Controls.m_CalibrationMethodComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(OnToolCalibrationMethodChanged(int))); + + connect( (QObject*)(m_Controls.m_RunCalibrationButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnRunSingleRefToolCalibrationClicked())); + connect( (QObject*)(m_Controls.m_CollectNavigationDataButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnLoginSingleRefToolNavigationDataClicked())); + connect( (QObject*)(m_Controls.m_SetNewToolTipPosButton), SIGNAL(clicked()),(QObject*) this, SLOT(OnSetNewToolTipPosButtonClicked())); + + m_IDToolToCalibrate = -1; + m_IDCalibrationPointer = -1; + m_IndexCurrentCalibrationMethod = -1; + m_OnLoginSingleRefToolNavigationDataClicked = false; + m_NumberOfNavigationDataCounter = 0; + m_NumberOfNavigationData = -1; + + m_CalibrationLandmarks = mitk::PointSet::New(); + m_CalibrationLandmarksNode = mitk::DataNode::New(); + m_CalibrationLandmarksNode->SetData(m_CalibrationLandmarks); + m_Controls.m_CalibrationLandmarkWidget->SetPointSetNode(m_CalibrationLandmarksNode); + + m_RegistrationLandmarks = mitk::PointSet::New(); + m_RegistrationLandmarksNode = mitk::DataNode::New(); + m_RegistrationLandmarksNode->SetData(m_RegistrationLandmarks); + m_Controls.m_RegistrationLandmarkWidget->SetPointSetNode(m_RegistrationLandmarksNode); + + m_ToolSurfaceInToolCoordinatesDataNode = mitk::DataNode::New(); + m_ToolSurfaceInToolCoordinatesDataNode->SetName("ToolSurface(ToolCoordinates)"); + + m_PivotPoses = std::vector(); + + m_LoggedNavigationDataDifferences = std::vector< mitk::NavigationData::Pointer >(); +} + + +void IGTNavigationToolCalibration::OnRunSingleRefToolCalibrationClicked() +{ + if (!CheckInitialization()) {return;} + + //1: Compute mean translational offset + m_ResultOffset.Fill(0); + for(std::vector::iterator vecIter = m_LoggedNavigationDataOffsets.begin(); vecIter != m_LoggedNavigationDataOffsets.end(); vecIter++) + { + m_ResultOffset[0] = m_ResultOffset[0] + (*vecIter)[0]; + m_ResultOffset[1] = m_ResultOffset[1] + (*vecIter)[1]; + m_ResultOffset[2] = m_ResultOffset[2] + (*vecIter)[2]; + for(std::vector::iterator innerVec = vecIter+1; innerVec != m_LoggedNavigationDataOffsets.end(); innerVec++) + { + m_ComputedDistances.push_back((*vecIter).SquaredEuclideanDistanceTo(*innerVec)); + } + } + m_ResultOffset[0] = m_ResultOffset[0] / m_LoggedNavigationDataOffsets.size(); + m_ResultOffset[1] = m_ResultOffset[1] / m_LoggedNavigationDataOffsets.size(); + m_ResultOffset[2] = m_ResultOffset[2] / m_LoggedNavigationDataOffsets.size(); + + double sum = std::accumulate( m_ComputedDistances.begin(), m_ComputedDistances.end(), 0); + double meanDistance = sum / m_ComputedDistances.size(); + + this->m_Controls.m_ResultOfCalibration->setText( + QString("x: ") + QString(QString::number(m_ResultOffset[0],103,3)) + + QString("; y: ") + (QString::number(m_ResultOffset[1],103,3)) + + QString("; z: ") + (QString::number(m_ResultOffset[2],103,3))); + + //2: Compute mean orientation + mitk::Quaternion meanOrientation; + std::vector allOrientations = std::vector (); + for (int i=0; iGetOrientation());} + meanOrientation = mitk::QuaternionAveraging::CalcAverage(allOrientations); + this->m_Controls.m_ResultOfCalibrationOrientation->setText( + QString("qx: ") + QString(QString::number(meanOrientation.x(),103,3)) + + QString("; qy: ") + (QString::number(meanOrientation.y(),103,3)) + + QString("; qz: ") + (QString::number(meanOrientation.z(),103,3)) + + QString("; qr: ") + (QString::number(meanOrientation.r(),103,3))); + + //3: write everything into the final tool tip transform and save it as member (it will be written to the tool later on) + mitk::NavigationData::Pointer ToolTipTransform = mitk::NavigationData::New(); + ToolTipTransform->SetPosition(m_ResultOffset); + ToolTipTransform->SetOrientation(meanOrientation); + mitk::NavigationData::Pointer ToolTipInTrackingCoordinates = mitk::NavigationData::New(); + ToolTipInTrackingCoordinates->Compose(ToolTipTransform); + ToolTipInTrackingCoordinates->Compose(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)); + ShowToolTipPreview(ToolTipInTrackingCoordinates); + m_Controls.m_SetNewToolTipPosButton->setEnabled(true); + m_ComputedToolTipTransformation = ToolTipTransform; +} + +void IGTNavigationToolCalibration::OnLoginSingleRefToolNavigationDataClicked() +{ + if (!CheckInitialization()) {return;} + m_OnLoginSingleRefToolNavigationDataClicked = true; + m_Controls.m_CollectNavigationDataButton->setEnabled(false); + m_NumberOfNavigationData = m_Controls.m_NumberOfNavigationDataToCollect->value(); + MITK_INFO << "Collecting " << m_NumberOfNavigationData << " NavigationData ... "<setText(labelText); + + mitk::NavigationData::Pointer referenceTool = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer); + mitk::NavigationData::Pointer toolToCalibrate = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate); + + //compute difference: + // differenceND = toolToCalibrate^-1 * referenceTool + mitk::NavigationData::Pointer differenceND = mitk::NavigationData::New(); + differenceND->Compose(referenceTool); + differenceND->Compose(toolToCalibrate->GetInverse()); + + //inverse mode... + if (m_Controls.m_InvertQuaternions->isChecked()) + { + // negate identity matrix to directly show parameters that will set up in NDI 6D Software Architect + differenceND = differenceND->GetInverse(); + } + + //save difference in member + m_LoggedNavigationDataOffsets.push_back(differenceND->GetPosition()); + m_LoggedNavigationDataDifferences.push_back(differenceND); + m_NumberOfNavigationDataCounter++; + } + + if( m_NumberOfNavigationDataCounter == m_NumberOfNavigationData) + { + m_NumberOfNavigationDataCounter = 0; + m_OnLoginSingleRefToolNavigationDataClicked = false; + m_Controls.m_CollectNavigationDataButton->setEnabled(true); + m_Controls.m_RunCalibrationButton->setEnabled(true); + MITK_INFO << "Collecting " << m_NumberOfNavigationData << " NavigationData ... Finished"<setText(labelText); + } +} + +void IGTNavigationToolCalibration::OnSetNewToolTipPosButtonClicked() +{ + ApplyToolTipTransform(m_ComputedToolTipTransformation); + RemoveToolTipPreview(); +} + +void IGTNavigationToolCalibration::OnAddPivotPose() +{ + if (!CheckInitialization()) {return;} + mitk::NavigationData::Pointer currentPose = mitk::NavigationData::New(); + currentPose->Graft(m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource()->GetOutput(m_IDToolToCalibrate)); + m_PivotPoses.push_back(currentPose); + m_Controls.m_PoseNumber->setText(QString::number(m_PivotPoses.size())); +} + +void IGTNavigationToolCalibration::OnComutePivot() +{ + MITK_WARN << "Not implemented yet!"; + /* + mitk::PivotCalibration::Pointer myPivotCalibration = mitk::PivotCalibration::New(); + for (int i=0; im_PivotPoses.size(); i++) + { + myPivotCalibration->AddNavigationData(m_PivotPoses.at(i)); + } + QString resultString; + if (myPivotCalibration->ComputePivotResult()) + { + //Get first marker transformation (TODO: compute for each pivot pose and average laster... this would be more accurate!) + mitk::NavigationData::Pointer markerTransformationTrackingCoordinates = m_PivotPoses.at(0); + + //Get computed pivot transfromation in tool coordinates + mitk::NavigationData::Pointer pivotPointToolCoordinates = mitk::NavigationData::New(); + pivotPointToolCoordinates->SetPosition(myPivotCalibration->GetResultPivotPoint()); + pivotPointToolCoordinates->SetOrientation(myPivotCalibration->GetResultPivotRotation()); + mitk::NavigationData::Pointer toolRotation = mitk::NavigationData::New(); + toolRotation->SetOrientation(markerTransformationTrackingCoordinates->GetOrientation()); + pivotPointToolCoordinates->Compose(toolRotation); + + //Compute pivot point in relation to marker transformation for preview + mitk::NavigationData::Pointer pivotInTrackingCoordinates = mitk::NavigationData::New(); + pivotInTrackingCoordinates->Compose(pivotPointToolCoordinates); + pivotInTrackingCoordinates->Compose(markerTransformationTrackingCoordinates); + + //add the preview node to the data storage + ShowToolTipPreview(pivotInTrackingCoordinates); + + //parse result string + resultString = QString("Pivot comutation succeeded!\n") + + QString("RMS Error: ") + QString::number(myPivotCalibration->GetResultRMSError()) + QString("\n") + + QString("Pivot Point: ") + QString::number(myPivotCalibration->GetResultPivotPoint()[0]) + ";" + QString::number(myPivotCalibration->GetResultPivotPoint()[1]) + ";" + QString::number(myPivotCalibration->GetResultPivotPoint()[2]) + QString("\n") + + QString("Pivot Rotation: ") + QString::number(myPivotCalibration->GetResultPivotRotation()[0]) + ";" + QString::number(myPivotCalibration->GetResultPivotRotation()[1]) + ";" + QString::number(myPivotCalibration->GetResultPivotRotation()[2]) + ";" + QString::number(myPivotCalibration->GetResultPivotRotation()[3]) + QString("\n"); + + //finally: save results to member variable + m_ComputedToolTipTransformation = pivotPointToolCoordinates; + + //enable button to use the computed point with the tool + m_Controls.m_UseComputedPivotPoint->setEnabled(true); + } + else + { + resultString = "Pivot comutation failed!"; + } + MITK_INFO << resultString.toStdString().c_str(); + m_Controls.m_ResultText->setText(resultString); + */ +} + +void IGTNavigationToolCalibration::OnUseComutedPivotPoint() +{ + if (!CheckInitialization(false)) {return;} + RemoveToolTipPreview(); + QString resultString = QString("Pivoted tool tip transformation was written to the tool ") + m_ToolToCalibrate->GetToolName().c_str(); + ApplyToolTipTransform(m_ComputedToolTipTransformation,resultString.toStdString()); + m_Controls.m_ResultText->setText(resultString); +} + +void IGTNavigationToolCalibration::ApplyToolTipTransform(mitk::NavigationData::Pointer ToolTipTransformInToolCoordinates, std::string message) +{ + if (!CheckInitialization(false)) {return;} + + //Update tool in tool storage + m_ToolToCalibrate->SetToolTipPosition(ToolTipTransformInToolCoordinates->GetPosition()); + m_ToolToCalibrate->SetToolTipOrientation(ToolTipTransformInToolCoordinates->GetOrientation()); + + //And also update tracking device, so the transform is directly used + mitk::TrackingDeviceSource::Pointer trackingDeviceSource; + try + { + trackingDeviceSource = dynamic_cast(m_NavigationDataSourceOfToolToCalibrate.GetPointer()); + mitk::TrackingTool::Pointer TrackingToolToCalibrate = trackingDeviceSource->GetTrackingDevice()->GetTool(m_IDToolToCalibrate); + TrackingToolToCalibrate->SetToolTip(ToolTipTransformInToolCoordinates->GetPosition(),ToolTipTransformInToolCoordinates->GetOrientation()); + } + catch (std::exception& e) + { + MITK_ERROR << "Error while trying to set the tool tip to the running tracking device. Aborting! (" << e.what() << ")"; + } + MITK_INFO << message; +} + +void IGTNavigationToolCalibration::ShowToolTipPreview(mitk::NavigationData::Pointer ToolTipInTrackingCoordinates) +{ + mitk::DataNode::Pointer m_ToolTipPointPreview = mitk::DataNode::New(); + m_ToolTipPointPreview->SetName("Modified Tool Tip Preview"); + mitk::Color red; + red.SetRed(1); + m_ToolTipPointPreview->SetColor(red); + mitk::Surface::Pointer mySphere = mitk::Surface::New(); + vtkSphereSource *vtkData = vtkSphereSource::New(); + vtkData->SetRadius(3.0f); + vtkData->SetCenter(0.0, 0.0, 0.0); + vtkData->Update(); + mySphere->SetVtkPolyData(vtkData->GetOutput()); + vtkData->Delete(); + m_ToolTipPointPreview->SetData(mySphere); + m_ToolTipPointPreview->GetData()->GetGeometry()->SetIndexToWorldTransform(ToolTipInTrackingCoordinates->GetAffineTransform3D()); + this->GetDataStorage()->Add(m_ToolTipPointPreview); +} + +void IGTNavigationToolCalibration::RemoveToolTipPreview() +{ + this->GetDataStorage()->Remove(m_ToolTipPointPreview.GetPointer()); +} +void IGTNavigationToolCalibration::UpdateManualToolTipCalibrationView() +{ + if (m_ToolToCalibrate.IsNull()) {return;} + //parse human readable transformation data and display it + std::stringstream translation; + std::stringstream orientation; + translation<GetToolTipPosition(); + orientation<<"Quaternion: [" << m_ToolToCalibrate->GetToolTipOrientation() <<"]"<GetToolTipOrientation().rotation_euler_angles() <<"]"< rotMatrix =m_ToolToCalibrate->GetToolTipOrientation().rotation_matrix_transpose(); + orientation<setText(translation.str().c_str()); + m_Controls.m_ManualCurrentOrientation->setPlainText(orientation.str().c_str()); +} + +void IGTNavigationToolCalibration::OnStartManualToolTipCalibration() +{ + if (!CheckInitialization(false)) {return;} + m_ManualToolTipEditWidget->SetToolTipSurface(false,m_ToolToCalibrate->GetDataNode()); + m_ManualToolTipEditWidget->show(); + m_ManualToolTipEditWidget->SetDefaultTooltip(m_ToolToCalibrate->GetToolTipTransform()); + m_ManualToolTipEditWidget->ReInitialize(); +} + +void IGTNavigationToolCalibration::OnRetrieveDataForManualTooltipManipulation() +{ + this->GetDataStorage()->Add(m_ToolSurfaceInToolCoordinatesDataNode); + m_ManualToolTipEditWidget->SetToolTipSurface(false,m_ToolSurfaceInToolCoordinatesDataNode); +} + +void IGTNavigationToolCalibration::OnProcessManualTooltipEditDialogCloseRequest() +{ + mitk::NavigationData::Pointer tempND = mitk::NavigationData::New(m_ManualToolTipEditWidget->GetManipulatedToolTip()); + this->ApplyToolTipTransform(tempND); + UpdateManualToolTipCalibrationView(); + m_ManualToolTipEditWidget->hide(); + this->GetDataStorage()->Remove(m_ToolSurfaceInToolCoordinatesDataNode); +} + +void IGTNavigationToolCalibration::SetToolToCalibrate() +{ + m_IDToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedToolID(); + m_ToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationTool(); + if (m_IDToolToCalibrate==-1) //no valid tool to calibrate + { + m_Controls.m_CalToolLabel->setText(""); + m_Controls.m_StatusWidgetToolToCalibrate->RemoveStatusLabels(); + m_TrackingTimer->stop(); + } + else + { + m_NavigationDataSourceOfToolToCalibrate = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource(); + m_Controls.m_CalToolLabel->setText(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)->GetName()); + //initialize widget + m_Controls.m_StatusWidgetToolToCalibrate->RemoveStatusLabels(); + m_Controls.m_StatusWidgetToolToCalibrate->SetShowPositions(true); + m_Controls.m_StatusWidgetToolToCalibrate->SetTextAlignment(Qt::AlignLeft); + m_Controls.m_StatusWidgetToolToCalibrate->AddNavigationData(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)); + m_Controls.m_StatusWidgetToolToCalibrate->ShowStatusLabels(); + //initialize manual tool tip calibration view + UpdateManualToolTipCalibrationView(); + //save tool surface in tool coordinates for further editing + mitk::Surface::Pointer ToolSurface = dynamic_cast(m_ToolToCalibrate->GetDataNode()->GetData())->Clone(); + m_ToolSurfaceInToolCoordinatesDataNode->SetData(ToolSurface); + m_ToolSurfaceInToolCoordinatesDataNode->GetData()->GetGeometry()->SetIdentity(); + //start updating timer for status widgets, etc. + if (!m_TrackingTimer->isActive()) m_TrackingTimer->start(100); + } +} + +void IGTNavigationToolCalibration::SetCalibrationPointer() +{ + m_IDCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedToolID(); + m_NavigationDataSourceOfCalibrationPointer = m_Controls.m_SelectionWidget->GetSelectedNavigationDataSource(); + if (m_IDCalibrationPointer==-1) + { + m_Controls.m_PointerLabel->setText(""); + m_Controls.m_StatusWidgetCalibrationPointer->RemoveStatusLabels(); + m_TrackingTimer->stop(); + } + else + { + m_Controls.m_PointerLabel->setText(m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)->GetName()); + //initialize widget + m_Controls.m_StatusWidgetCalibrationPointer->RemoveStatusLabels(); + m_Controls.m_StatusWidgetCalibrationPointer->SetShowPositions(true); + m_Controls.m_StatusWidgetCalibrationPointer->SetTextAlignment(Qt::AlignLeft); + m_Controls.m_StatusWidgetCalibrationPointer->AddNavigationData(m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)); + m_Controls.m_StatusWidgetCalibrationPointer->ShowStatusLabels(); + if (!m_TrackingTimer->isActive()) m_TrackingTimer->start(100); + } +} + +void IGTNavigationToolCalibration::UpdateOffsetCoordinates() +{ + mitk::NavigationData::Pointer referenceToolND = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer); + mitk::NavigationData::Pointer toolToCalibrateND = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate); + + if(referenceToolND->IsDataValid() && toolToCalibrateND->IsDataValid()) + { + //computation: difference between both tools (in tool coordinates) + //differenceND = toolToCalibrateND^-1 * referenceToolND + mitk::NavigationData::Pointer differenceND = mitk::NavigationData::New(); + differenceND->Compose(referenceToolND); + differenceND->Compose(toolToCalibrateND->GetInverse()); + + //display this orientation in the UI + m_Controls.m_OffsetCoordinates->setText( + QString("x: ") + QString(QString::number(differenceND->GetPosition()[0],103,3)) + + QString("; y: ") + (QString::number(differenceND->GetPosition()[1],103,3)) + + QString("; z: ") + (QString::number(differenceND->GetPosition()[2],103,3))); + + m_Controls.m_OrientationOffsetCoordinates->setText( + QString("qx: ") + QString(QString::number(differenceND->GetOrientation().x(),103,3)) + + QString("; qy: ") + (QString::number(differenceND->GetOrientation().y(),103,3)) + + QString("; qz: ") + (QString::number(differenceND->GetOrientation().z(),103,3)) + + QString("; qr: ") + (QString::number(differenceND->GetOrientation().r(),103,3))); + + //also update preview if active + if (m_ToolTipPointPreview.IsNotNull()) //NOT WORKING! TODO: fix or remove! + { + mitk::NavigationData::Pointer ToolTipTransform = mitk::NavigationData::New(); + ToolTipTransform->SetPosition(m_ResultOffset); + mitk::NavigationData::Pointer ToolTipInTrackingCoordinates = mitk::NavigationData::New(); //maybe store as for better peformance... + ToolTipInTrackingCoordinates->Compose(m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate)); + ToolTipInTrackingCoordinates->Compose(ToolTipTransform); + m_ToolTipPointPreview->GetData()->GetGeometry()->SetIndexToWorldTransform(ToolTipInTrackingCoordinates->GetAffineTransform3D()); + } + } +} + +void IGTNavigationToolCalibration::UpdateTrackingTimer() +{ + m_Controls.m_StatusWidgetToolToCalibrate->Refresh(); + m_Controls.m_StatusWidgetCalibrationPointer->Refresh(); + + if(m_OnLoginSingleRefToolNavigationDataClicked) LoginSingleRefToolNavigationData(); + + // 1 == Single Reference Calibration Method + if(m_IndexCurrentCalibrationMethod == 1 ) UpdateOffsetCoordinates(); + +} + +void IGTNavigationToolCalibration::AddLandmark() +{ + if (!CheckInitialization()) {return;} + mitk::NavigationData::Pointer navDataTool = m_NavigationDataSourceOfToolToCalibrate->GetOutput(m_IDToolToCalibrate); + mitk::Point3D landmark = m_NavigationDataSourceOfCalibrationPointer->GetOutput(m_IDCalibrationPointer)->GetPosition(); + + //convert to itk transform + itk::Vector translation; + for(int k=0; k<3;k++) translation[k] = navDataTool->GetPosition()[k]; + itk::Matrix rotation; + for(int k=0; k<3; k++) for(int l=0; l<3; l++) rotation[k][l] = navDataTool->GetOrientation().rotation_matrix_transpose()[k][l]; + rotation = rotation.GetTranspose(); + itk::Vector landmarkItk; + landmarkItk[0] = landmark[0]; + landmarkItk[1] = landmark[1]; + landmarkItk[2] = landmark[2]; + + //compute landmark in tool coordinates + itk::Matrix rotationInverse; + for(int k=0; k<3; k++) for(int l=0; l<3; l++) rotationInverse[k][l] = rotation.GetInverse()[k][l]; + landmarkItk = rotationInverse * (landmarkItk - translation) ; + + //convert back and add landmark to pointset + landmark[0] = landmarkItk[0]; + landmark[1] = landmarkItk[1]; + landmark[2] = landmarkItk[2]; + m_RegistrationLandmarks->InsertPoint(m_RegistrationLandmarks->GetSize(),landmark); +} + +void IGTNavigationToolCalibration::SaveCalibratedTool() +{ + if (m_ToolToCalibrate.IsNotNull()) + { + mitk::NavigationTool::Pointer calibratedTool = m_ToolToCalibrate; + calibratedTool->SetToolCalibrationLandmarks(this->m_CalibrationLandmarks); + calibratedTool->SetToolRegistrationLandmarks(this->m_RegistrationLandmarks); + mitk::NavigationToolWriter::Pointer myWriter = mitk::NavigationToolWriter::New(); + std::string filename = QFileDialog::getSaveFileName(NULL,tr("Save Navigation Tool"), "/", "*.IGTTool").toUtf8().data(); + if (filename == "") return; + if (myWriter->DoWrite(filename,calibratedTool)) MITK_INFO << "Saved calibrated tool to file " << filename; + else MITK_WARN << "Can't write tool to file " << filename; + } + else + { + MITK_ERROR << "Did not find navigation tool storage of calibrated tool, aborting!"; + } +} + +bool IGTNavigationToolCalibration::CheckInitialization(bool CalibrationPointerRequired) +{ +if ( (m_IDToolToCalibrate == -1) || + ( (CalibrationPointerRequired) && + (m_IDCalibrationPointer == -1) + ) + ) + { + QMessageBox msgBox; + msgBox.setText("Tool to calibrate and/or calibration pointer not initialized, cannot proceed!"); + msgBox.exec(); + return false; + } +else {return true;} +} diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h new file mode 100644 index 0000000000..31894c3f46 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibration.h @@ -0,0 +1,129 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef IGTNavigationToolCalibration_h +#define IGTNavigationToolCalibration_h + +#include + +#include + +#include +#include + +#include "ui_IGTNavigationToolCalibrationControls.h" + +//QT headers +#include + + +/*! + \brief IGTNavigationToolCalibration + + \warning This class is not yet documented. Use "git blame" and ask the author to provide basic documentation. + + \sa QmitkFunctionality + \ingroup ${plugin_target}_internal +*/ +class IGTNavigationToolCalibration : public QmitkAbstractView +{ + // this is needed for all Qt objects that should have a Qt meta-object + // (everything that derives from QObject and wants to have signal/slots) + Q_OBJECT + + public: + + IGTNavigationToolCalibration(); + + virtual ~IGTNavigationToolCalibration(); + + static const std::string VIEW_ID; + + virtual void CreateQtPartControl(QWidget *parent); + + protected slots: + + void OnAddPivotPose(); + void OnComutePivot(); + void OnUseComutedPivotPoint(); + void SetToolToCalibrate(); + void SetCalibrationPointer(); + void UpdateTrackingTimer(); + void AddLandmark(); + void SaveCalibratedTool(); + void OnToolCalibrationMethodChanged(int index); + void OnStartManualToolTipCalibration(); + void OnRetrieveDataForManualTooltipManipulation(); + void OnProcessManualTooltipEditDialogCloseRequest(); + void OnRunSingleRefToolCalibrationClicked(); + void OnLoginSingleRefToolNavigationDataClicked(); + void OnSetNewToolTipPosButtonClicked(); + + + protected: + + virtual void SetFocus(); + + void UpdateOffsetCoordinates(); + + int m_IndexCurrentCalibrationMethod; + + Ui::IGTNavigationToolCalibrationControls m_Controls; + + //some general members + mitk::NavigationTool::Pointer m_ToolToCalibrate; //<<< tool that will be calibrated + int m_IDToolToCalibrate; //<<< id of tool that will be calibrated (of the navigation data source) + mitk::NavigationDataSource::Pointer m_NavigationDataSourceOfToolToCalibrate; //<<< navigation data source of the tool that will be calibrated + mitk::NavigationDataSource::Pointer m_NavigationDataSourceOfCalibrationPointer; //<<< navigation data source of the calibration pointer + mitk::DataNode::Pointer m_ToolSurfaceInToolCoordinatesDataNode; //<<< holds the tool surface in tool coordinates (for preview purposes) + int m_IDCalibrationPointer; //<<< id of the calibration pointer (of the corresponding navigation data source) + QTimer* m_TrackingTimer; //<<< tracking timer that updates the status widgets + void ApplyToolTipTransform(mitk::NavigationData::Pointer ToolTipTransformInToolCoordinates, std::string message = "Tool was updated with the calibrated tool tip!"); //<<< applys the given tool tip transform to the tool to calibrate + bool CheckInitialization(bool CalibrationPointerRequired = true); //<<< checks if the tool to calibrate and (if required) the calibration pointer is initialized. Displays a warning and returns false if not. + mitk::NavigationData::Pointer m_ComputedToolTipTransformation; //<<< holds the new tooltip transformation after it was computed to write it into the tool later + + // members and helper methods for pivot tool calibration + std::vector m_PivotPoses; + + // members and helper methods for manual tool calibration + void UpdateManualToolTipCalibrationView(); + QmitkNavigationToolCreationAdvancedWidget* m_ManualToolTipEditWidget; + + // members and helper methods for single reference tool calibration + void LoginSingleRefToolNavigationData(); + std::vector< mitk::Point3D > m_LoggedNavigationDataOffsets; + std::vector< mitk::NavigationData::Pointer > m_LoggedNavigationDataDifferences; + std::vector m_ComputedDistances; + bool m_OnLoginSingleRefToolNavigationDataClicked; + int m_NumberOfNavigationData; + int m_NumberOfNavigationDataCounter; + mitk::Point3D m_ResultOffset; + + // members and helper methods for tool tip preview + mitk::DataNode::Pointer m_ToolTipPointPreview; //<<< Data node of the tool tip preview + void ShowToolTipPreview(mitk::NavigationData::Pointer ToolTipInTrackingCoordinates); //<<< Adds a preview of the tool tip into the data storage + void RemoveToolTipPreview(); //<<< Removes the preview + + // members for the tool landmark calibration + mitk::PointSet::Pointer m_CalibrationLandmarks; + mitk::DataNode::Pointer m_CalibrationLandmarksNode; + mitk::PointSet::Pointer m_RegistrationLandmarks; + mitk::DataNode::Pointer m_RegistrationLandmarksNode; + +}; + +#endif // IGTNavigationToolCalibration_h diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui new file mode 100644 index 0000000000..32bb1f876b --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/IGTNavigationToolCalibrationControls.ui @@ -0,0 +1,952 @@ + + + IGTNavigationToolCalibrationControls + + + + 0 + 0 + 379 + 829 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Navigation Tool Calibration</span></p></body></html> + + + + + + + Tool to calibrate + + + + + + + 0 + 50 + + + + + 16777215 + 50 + + + + + + + + + + + Calibration pointer + + + + + + + 0 + 30 + + + + + + + + + + + true + + + 0 + + + + Initialization + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline;">Choose Tracking Device and Tools</span></p></body></html> + + + + + + + + + + Qt::Horizontal + + + + + + + + + + 120 + 0 + + + + Tool to Calibrate: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + <none> + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 150 + 0 + + + + Use as Tool to Calibrate + + + + + + + + + Qt::Horizontal + + + + + + + + + + 120 + 0 + + + + Calibration Pointer: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + <none> + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 150 + 0 + + + + Use as Calibration Pointer + + + + + + + + + Qt::Horizontal + + + + + + + Qt::Vertical + + + + 20 + 586 + + + + + + + + + Tool Tip Calibration + + + + + + + + + 50 + false + + + + Calibration Method: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + Manual + + + + + Single Reference Tool + + + + + Multiple Tools Reference + + + + + Pivoting + + + + + + + + + + Qt::Horizontal + + + + + + + 0 + + + + + + + Current Tool Tip Translation: + + + + + + + true + + + true + + + + + + + Current Tool Tip Orientation: + + + + + + + true + + + true + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Start Edit Tooltip + + + + + + + + + + + + + + 0 + 0 + + + + + 319 + 160 + + + + + 319 + 160 + + + + + QFrame { + border-image: url(:/IGTNavigationToolCalibration/Description.svg); + } + + + + QFrame::Box + + + QFrame::Plain + + + 1 + + + + + + + + 0 + 0 + + + + Current Offset between Tool to calibrate and Calibration pointer: + + + + + + + + + Pos: + + + + + + + + 8 + + + + + + + Qt::AlignCenter + + + + + + + + + + + Rot: + + + + + + + + 8 + + + + + + + Qt::AlignCenter + + + + + + + + + Qt::Horizontal + + + + + + + + + + 0 + 0 + + + + Number of tracking data to collect: + + + + + + + + 0 + 0 + + + + 10000 + + + 100 + + + + + + + + + + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + 1: Collect Navigation Data + + + + + + + Qt::Horizontal + + + + + + + Invert calibration transformation + + + + + + + false + + + 2: Run Calibration + + + + + + + Qt::Horizontal + + + + + + + + 0 + 0 + + + + New Tool Tip Position of Tool to calibrate: + + + + + + + + + Pos: + + + + + + + + 8 + + + + Qt::AlignCenter + + + + + + + + + + + Rot: + + + + + + + + 8 + + + + Qt::AlignCenter + + + + + + + + + false + + + 3: Set New Tool Tip Position + + + + + + + Qt::Vertical + + + + 20 + 203 + + + + + + + + + + + + + + + Number of saved poses: + + + + + + + 0 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Add Current Pose + + + + + + + + + Calibration Result: + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 175 + 0 + + + + Comute Pivot Point + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + + 0 + 0 + + + + + 175 + 0 + + + + Use Computed Pivot Point + + + + + + + + + Qt::Vertical + + + + 20 + 99 + + + + + + + + + + + + + Tool Landmark Calibration + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; text-decoration: underline;">Calibrate tool by marking the landmarks with the pointer</span></p></body></html> + + + + + + + Registration Landmarks + + + + + + + 0 + 170 + + + + + + + + Add Pointer Position + + + + + + + + + + Calibration Landmarks + + + + + + + + + + + + Qt::Vertical + + + + 20 + 259 + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Save Calibrated Navigation Tool + + + + + + + + + + + QmitkNavigationDataSourceSelectionWidget + QWidget +
QmitkNavigationDataSourceSelectionWidget.h
+ 1 +
+ + QmitkToolTrackingStatusWidget + QWidget +
QmitkToolTrackingStatusWidget.h
+ 1 +
+ + QmitkPointListWidget + QWidget +
QmitkPointListWidget.h
+ 1 +
+
+ + +
diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp index 1d816d6a5a..2178577c62 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.cpp @@ -1,1453 +1,1480 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include // Qmitk #include "QmitkMITKIGTTrackingToolboxView.h" #include "QmitkTrackingDeviceConfigurationWidget.h" #include "QmitkStdMultiWidget.h" // Qt #include #include #include // MITK #include #include #include #include #include #include #include #include -#include -#include #include #include // vtk #include //for exceptions #include #include const std::string QmitkMITKIGTTrackingToolboxView::VIEW_ID = "org.mitk.views.mitkigttrackingtoolbox"; QmitkMITKIGTTrackingToolboxView::QmitkMITKIGTTrackingToolboxView() : QmitkFunctionality() , m_Controls( 0 ) , m_MultiWidget( NULL ) { m_TrackingLoggingTimer = new QTimer(this); m_TrackingRenderTimer = new QTimer(this); m_TimeoutTimer = new QTimer(this); m_tracking = false; m_connected = false; m_logging = false; m_loggedFrames = 0; //create filename for autosaving of tool storage QString loggingPathWithoutFilename = QString(mitk::LoggingBackend::GetLogFile().c_str()); if (!loggingPathWithoutFilename.isEmpty()) //if there already is a path for the MITK logging file use this one { //extract path from path+filename (if someone knows a better way to do this feel free to change it) int lengthOfFilename = QFileInfo(QString::fromStdString(mitk::LoggingBackend::GetLogFile())).fileName().size(); loggingPathWithoutFilename.resize(loggingPathWithoutFilename.size()-lengthOfFilename); m_AutoSaveFilename = loggingPathWithoutFilename + "TrackingToolboxAutoSave.IGTToolStorage"; } else //if not: use a temporary path from IOUtil { m_AutoSaveFilename = QString(mitk::IOUtil::GetTempPath().c_str()) + "TrackingToolboxAutoSave.IGTToolStorage"; } MITK_INFO("IGT Tracking Toolbox") << "Filename for auto saving of IGT ToolStorages: " << m_AutoSaveFilename.toStdString(); //initialize worker thread m_WorkerThread = new QThread(); m_Worker = new QmitkMITKIGTTrackingToolboxViewWorker(); } QmitkMITKIGTTrackingToolboxView::~QmitkMITKIGTTrackingToolboxView() { this->StoreUISettings(); m_TrackingLoggingTimer->stop(); m_TrackingRenderTimer->stop(); m_TimeoutTimer->stop(); delete m_TrackingLoggingTimer; delete m_TrackingRenderTimer; delete m_TimeoutTimer; try { // wait for thread to finish m_WorkerThread->terminate(); m_WorkerThread->wait(); //clean up worker thread if(m_WorkerThread) {delete m_WorkerThread;} if(m_Worker) {delete m_Worker;} //remove the tracking volume this->GetDataStorage()->Remove(m_TrackingVolumeNode); //remove the tool storage if(m_toolStorage) {m_toolStorage->UnRegisterMicroservice();} if(m_TrackingDeviceSource) {m_TrackingDeviceSource->UnRegisterMicroservice();} } catch(std::exception& e) {MITK_WARN << "Unexpected exception during clean up of tracking toolbox view: " << e.what();} catch(...) {MITK_WARN << "Unexpected unknown error during clean up of tracking toolbox view!";} //store tool storage and UI settings for persistence this->AutoSaveToolStorage(); this->StoreUISettings(); } void QmitkMITKIGTTrackingToolboxView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkMITKIGTTrackingToolboxViewControls; m_Controls->setupUi( parent ); //create connections connect( m_Controls->m_LoadTools, SIGNAL(clicked()), this, SLOT(OnLoadTools()) ); connect( m_Controls->m_ConnectDisconnectButton, SIGNAL(clicked()), this, SLOT(OnConnectDisconnect()) ); connect( m_Controls->m_StartStopTrackingButton, SIGNAL(clicked()), this, SLOT(OnStartStopTracking()) ); connect( m_Controls->m_FreezeUnfreezeTrackingButton, SIGNAL(clicked()), this, SLOT(OnFreezeUnfreezeTracking()) ); connect( m_TrackingLoggingTimer, SIGNAL(timeout()), this, SLOT(UpdateLoggingTrackingTimer())); connect( m_TrackingRenderTimer, SIGNAL(timeout()), this, SLOT(UpdateRenderTrackingTimer())); connect( m_TimeoutTimer, SIGNAL(timeout()), this, SLOT(OnTimeOut())); connect( m_Controls->m_ChooseFile, SIGNAL(clicked()), this, SLOT(OnChooseFileClicked())); connect( m_Controls->m_StartLogging, SIGNAL(clicked()), this, SLOT(StartLogging())); connect( m_Controls->m_StopLogging, SIGNAL(clicked()), this, SLOT(StopLogging())); connect( m_Controls->m_VolumeSelectionBox, SIGNAL(currentIndexChanged(QString)), this, SLOT(OnTrackingVolumeChanged(QString))); connect( m_Controls->m_ShowTrackingVolume, SIGNAL(clicked()), this, SLOT(OnShowTrackingVolumeChanged())); connect( m_Controls->m_AutoDetectTools, SIGNAL(clicked()), this, SLOT(OnAutoDetectTools())); connect( m_Controls->m_ResetTools, SIGNAL(clicked()), this, SLOT(OnResetTools())); connect( m_Controls->m_AddSingleTool, SIGNAL(clicked()), this, SLOT(OnAddSingleTool())); connect( m_Controls->m_NavigationToolCreationWidget, SIGNAL(NavigationToolFinished()), this, SLOT(OnAddSingleToolFinished())); connect( m_Controls->m_NavigationToolCreationWidget, SIGNAL(Canceled()), this, SLOT(OnAddSingleToolCanceled())); connect( m_Controls->m_csvFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); connect( m_Controls->m_xmlFormat, SIGNAL(clicked()), this, SLOT(OnToggleFileExtension())); connect( m_Controls->m_UseDifferentUpdateRates, SIGNAL(clicked()), this, SLOT(OnToggleDifferentUpdateRates())); connect( m_Controls->m_RenderUpdateRate, SIGNAL(valueChanged(int)), this, SLOT(OnChangeRenderUpdateRate())); + connect( m_Controls->m_DisableAllTimers, SIGNAL(stateChanged(int)), this, SLOT(EnableDisableTimerButtons(int))); //connections for the tracking device configuration widget connect( m_Controls->m_configurationWidget, SIGNAL(TrackingDeviceSelectionChanged()), this, SLOT(OnTrackingDeviceChanged())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressStarted()), this, SLOT(DisableOptionsButtons())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressStarted()), this, SLOT(DisableTrackingConfigurationButtons())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressStarted()), this, SLOT(DisableTrackingControls())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressFinished()), this, SLOT(EnableOptionsButtons())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressFinished()), this, SLOT(EnableTrackingConfigurationButtons())); connect( m_Controls->m_configurationWidget, SIGNAL(ProgressFinished()), this, SLOT(EnableTrackingControls())); //connect worker thread connect(m_Worker, SIGNAL(AutoDetectToolsFinished(bool,QString)), this, SLOT(OnAutoDetectToolsFinished(bool,QString)) ); connect(m_Worker, SIGNAL(ConnectDeviceFinished(bool,QString)), this, SLOT(OnConnectFinished(bool,QString)) ); connect(m_Worker, SIGNAL(StartTrackingFinished(bool,QString)), this, SLOT(OnStartTrackingFinished(bool,QString)) ); connect(m_Worker, SIGNAL(StopTrackingFinished(bool,QString)), this, SLOT(OnStopTrackingFinished(bool,QString)) ); connect(m_Worker, SIGNAL(DisconnectDeviceFinished(bool,QString)), this, SLOT(OnDisconnectFinished(bool,QString)) ); connect(m_WorkerThread,SIGNAL(started()), m_Worker, SLOT(ThreadFunc()) ); //move the worker to the thread m_Worker->moveToThread(m_WorkerThread); //initialize widgets m_Controls->m_configurationWidget->EnableAdvancedUserControl(false); m_Controls->m_TrackingToolsStatusWidget->SetShowPositions(true); m_Controls->m_TrackingToolsStatusWidget->SetTextAlignment(Qt::AlignLeft); //initialize tracking volume node m_TrackingVolumeNode = mitk::DataNode::New(); m_TrackingVolumeNode->SetName("TrackingVolume"); m_TrackingVolumeNode->SetBoolProperty("Backface Culling",true); mitk::Color red; red.SetRed(1); m_TrackingVolumeNode->SetColor(red); //initialize buttons m_Controls->m_AutoDetectTools->setVisible(false); //only visible if tracking device is Aurora m_Controls->m_StartStopTrackingButton->setEnabled(false); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false); //initialize warning labels m_Controls->m_renderWarningLabel->setVisible(false); m_Controls->m_TrackingFrozenLabel->setVisible(false); //Update List of available models for selected tool. std::vector Compatibles; if ( (m_Controls == NULL) || //check all these stuff for NULL, latterly this causes crashes from time to time (m_Controls->m_configurationWidget == NULL) || (m_Controls->m_configurationWidget->GetTrackingDevice().IsNull())) { MITK_ERROR << "Couldn't get current tracking device or an object is NULL, something went wrong!"; return; } else { Compatibles = mitk::GetDeviceDataForLine( m_Controls->m_configurationWidget->GetTrackingDevice()->GetType()); } m_Controls->m_VolumeSelectionBox->clear(); for(std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } //initialize tool storage m_toolStorage = mitk::NavigationToolStorage::New(GetDataStorage()); m_toolStorage->SetName("TrackingToolbox Default Storage"); m_toolStorage->RegisterAsMicroservice("no tracking device"); //set home directory as default path for logfile m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(QDir::homePath()) + QDir::separator() + "logfile.csv"); //tracking device may be changed already by the persistence of the //QmitkTrackingDeciveConfigurationWidget this->OnTrackingDeviceChanged(); this->LoadUISettings(); //add tracking volume node only to data storage this->GetDataStorage()->Add(m_TrackingVolumeNode); if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0); else m_TrackingVolumeNode->SetOpacity(0.25); //Update List of available models for selected tool. m_Controls->m_VolumeSelectionBox->clear(); for(std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } } void QmitkMITKIGTTrackingToolboxView::StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) { m_MultiWidget = &stdMultiWidget; } void QmitkMITKIGTTrackingToolboxView::StdMultiWidgetNotAvailable() { m_MultiWidget = NULL; } void QmitkMITKIGTTrackingToolboxView::OnLoadTools() { //read in filename QString filename = QFileDialog::getOpenFileName(NULL,tr("Open Tool Storage"), "/", tr("Tool Storage Files (*.IGTToolStorage)")); if (filename.isNull()) return; //read tool storage from disk std::string errorMessage = ""; mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); // try-catch block for exceptions try { this->ReplaceCurrentToolStorage(myDeserializer->Deserialize(filename.toStdString()),filename.toStdString()); } catch(mitk::IGTException) { std::string errormessage = "Error during loading the tool storage file. Please only load tool storage files created with the NavigationToolManager view."; QMessageBox::warning(NULL, "Tool Storage Loading Error", errormessage.c_str()); return; } if(m_toolStorage->isEmpty()) { errorMessage = myDeserializer->GetErrorMessage(); MessageBox(errorMessage); return; } //update label UpdateToolStorageLabel(filename); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); //save filename for persistent storage m_ToolStorageFilename = filename; } void QmitkMITKIGTTrackingToolboxView::OnResetTools() { this->ReplaceCurrentToolStorage(mitk::NavigationToolStorage::New(GetDataStorage()),"TrackingToolbox Default Storage"); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); QString toolLabel = QString(""); m_Controls->m_toolLabel->setText(toolLabel); m_ToolStorageFilename = ""; } void QmitkMITKIGTTrackingToolboxView::OnStartStopTracking() { if(!m_connected) { MITK_WARN << "Can't start tracking if no device is connected. Aborting"; return; } if(m_tracking) {OnStopTracking();} else {OnStartTracking();} } void QmitkMITKIGTTrackingToolboxView::OnFreezeUnfreezeTracking() { if( m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Freeze Tracking" ) { m_TrackingDeviceSource->Freeze(); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Unfreeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(true); } else if( m_Controls->m_FreezeUnfreezeTrackingButton->text() == "Unfreeze Tracking" ) { m_TrackingDeviceSource->UnFreeze(); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(false); } } void QmitkMITKIGTTrackingToolboxView::OnConnectDisconnect() { if(m_connected) {OnDisconnect();} else {OnConnect();} } void QmitkMITKIGTTrackingToolboxView::OnConnect() { MITK_INFO << "Connect Clicked"; //check if everything is ready to start tracking if (this->m_toolStorage.IsNull()) { MessageBox("Error: No Tools Loaded Yet!"); return; } else if (this->m_toolStorage->GetToolCount() == 0) { MessageBox("Error: No Way To Track Without Tools!"); return; } //parse tracking device data mitk::TrackingDeviceData data = mitk::DeviceDataUnspecified; QString qstr = m_Controls->m_VolumeSelectionBox->currentText(); if ( (! qstr.isNull()) || (! qstr.isEmpty()) ) { std::string str = qstr.toStdString(); data = mitk::GetDeviceDataByName(str); //Data will be set later, after device generation } //initialize worker thread m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eConnectDevice); m_Worker->SetTrackingDevice(this->m_Controls->m_configurationWidget->GetTrackingDevice()); m_Worker->SetInverseMode(m_Controls->m_InverseMode->isChecked()); m_Worker->SetNavigationToolStorage(this->m_toolStorage); m_Worker->SetTrackingDeviceData(data); //start worker thread m_WorkerThread->start(); //disable buttons this->m_Controls->m_MainWidget->setEnabled(false); } +void QmitkMITKIGTTrackingToolboxView::EnableDisableTimerButtons(int enable) +{ + bool enableBool = enable; + m_Controls->m_UpdateRateOptionsGroupBox->setEnabled(!enableBool); + m_Controls->m_renderWarningLabel->setVisible(enableBool); +} + void QmitkMITKIGTTrackingToolboxView::OnConnectFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); //enable buttons this->m_Controls->m_MainWidget->setEnabled(true); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; } //get data from worker thread m_TrackingDeviceSource = m_Worker->GetTrackingDeviceSource(); m_TrackingDeviceData = m_Worker->GetTrackingDeviceData(); m_ToolVisualizationFilter = m_Worker->GetToolVisualizationFilter(); //enable/disable Buttons DisableOptionsButtons(); DisableTrackingConfigurationButtons(); m_Controls->m_configurationWidget->ConfigurationFinished(); m_Controls->m_TrackingControlLabel->setText("Status: connected"); m_Controls->m_ConnectDisconnectButton->setText("Disconnect"); m_Controls->m_StartStopTrackingButton->setEnabled(true); m_connected = true; } void QmitkMITKIGTTrackingToolboxView::OnDisconnect() { m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eDisconnectDevice); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnDisconnectFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); m_Controls->m_MainWidget->setEnabled(true); if (!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); return; } //enable/disable Buttons m_Controls->m_StartStopTrackingButton->setEnabled(false); EnableOptionsButtons(); EnableTrackingConfigurationButtons(); m_Controls->m_configurationWidget->Reset(); m_Controls->m_TrackingControlLabel->setText("Status: disconnected"); m_Controls->m_ConnectDisconnectButton->setText("Connect"); m_Controls->m_FreezeUnfreezeTrackingButton->setText("Freeze Tracking"); m_Controls->m_TrackingFrozenLabel->setVisible(false); m_connected = false; } void QmitkMITKIGTTrackingToolboxView::OnStartTracking() { m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStartTracking); m_WorkerThread->start(); this->m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStartTrackingFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); this->m_Controls->m_MainWidget->setEnabled(true); if(!success) { MessageBox(errorMessage.toStdString()); MITK_WARN << errorMessage.toStdString(); return; } if(!(m_Controls->m_DisableAllTimers->isChecked())) { if(m_Controls->m_UseDifferentUpdateRates->isChecked()) { if(m_Controls->m_RenderUpdateRate->value() != 0) m_TrackingRenderTimer->start(1000/(m_Controls->m_RenderUpdateRate->value())); m_TrackingLoggingTimer->start(1000/(m_Controls->m_LogUpdateRate->value())); } else { m_TrackingRenderTimer->start(1000/(m_Controls->m_UpdateRate->value())); m_TrackingLoggingTimer->start(1000/(m_Controls->m_UpdateRate->value())); } } m_Controls->m_TrackingControlLabel->setText("Status: tracking"); //connect the tool visualization widget for(std::size_t i=0; iGetNumberOfOutputs(); i++) { m_Controls->m_TrackingToolsStatusWidget->AddNavigationData(m_TrackingDeviceSource->GetOutput(i)); } m_Controls->m_TrackingToolsStatusWidget->ShowStatusLabels(); if (m_Controls->m_ShowToolQuaternions->isChecked()) {m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(true);} else {m_Controls->m_TrackingToolsStatusWidget->SetShowQuaternions(false);} + //if activated enable open IGT link microservice + if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked()) + { + //create convertion filter + m_IGTLConversionFilter = mitk::NavigationDataToIGTLMessageFilter::New(); + m_IGTLConversionFilter->SetName("IGT Tracking Toolbox"); + m_IGTLConversionFilter->ConnectTo(m_ToolVisualizationFilter); + m_IGTLConversionFilter->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg); + m_IGTLConversionFilter->RegisterAsMicroservice(); + + //create server and message provider + m_IGTLServer = mitk::IGTLServer::New(); + m_IGTLServer->SetName("Tracking Toolbox IGTL Server"); + m_IGTLMessageProvider = mitk::IGTLMessageProvider::New(); + m_IGTLMessageProvider->SetIGTLDevice(m_IGTLServer); + m_IGTLMessageProvider->RegisterAsMicroservice(); + } + //show tracking volume this->OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); m_tracking = true; m_Controls->m_ConnectDisconnectButton->setEnabled(false); m_Controls->m_StartStopTrackingButton->setText("Stop Tracking"); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(true); this->GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnStopTracking() { if (!m_tracking) return; m_TrackingRenderTimer->stop(); m_TrackingLoggingTimer->stop(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eStopTracking); m_WorkerThread->start(); m_Controls->m_MainWidget->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::OnStopTrackingFinished(bool success, QString errorMessage) { m_WorkerThread->quit(); m_WorkerThread->wait(); m_Controls->m_MainWidget->setEnabled(true); if(!success) { MessageBox(errorMessage.toStdString()); MITK_WARN << errorMessage.toStdString(); return; } m_Controls->m_TrackingControlLabel->setText("Status: connected"); if (m_logging) StopLogging(); m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); m_tracking = false; m_Controls->m_StartStopTrackingButton->setText("Start Tracking"); m_Controls->m_ConnectDisconnectButton->setEnabled(true); m_Controls->m_FreezeUnfreezeTrackingButton->setEnabled(false); + //unregister open IGT link micro service + if (m_Controls->m_EnableOpenIGTLinkMicroService->isChecked()) + { + m_IGTLConversionFilter->UnRegisterMicroservice(); + m_IGTLMessageProvider->UnRegisterMicroservice(); + } + this->GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnTrackingDeviceChanged() { mitk::TrackingDeviceType Type; if (m_Controls->m_configurationWidget->GetTrackingDevice().IsNotNull()) { Type = m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(); //enable controls because device is valid m_Controls->m_TrackingToolsGoupBox->setEnabled(true); m_Controls->m_TrackingControlsGroupBox->setEnabled(true); } else { Type = mitk::TrackingSystemNotSpecified; MessageBox("Error: This tracking device is not included in this project. Please make sure that the device is installed and activated in your MITK build."); m_Controls->m_TrackingToolsGoupBox->setEnabled(false); m_Controls->m_TrackingControlsGroupBox->setEnabled(false); return; } // Code to enable/disable device specific buttons if (Type == mitk::NDIAurora) //Aurora { m_Controls->m_AutoDetectTools->setVisible(true); m_Controls->m_AddSingleTool->setEnabled(false); } else //Polaris or Microntracker { m_Controls->m_AutoDetectTools->setVisible(false); m_Controls->m_AddSingleTool->setEnabled(true); } // Code to select appropriate tracking volume for current type std::vector Compatibles = mitk::GetDeviceDataForLine(Type); m_Controls->m_VolumeSelectionBox->clear(); for(std::size_t i = 0; i < Compatibles.size(); i++) { m_Controls->m_VolumeSelectionBox->addItem(Compatibles[i].Model.c_str()); } } void QmitkMITKIGTTrackingToolboxView::OnTrackingVolumeChanged(QString qstr) { if (qstr.isNull()) return; if (qstr.isEmpty()) return; mitk::TrackingVolumeGenerator::Pointer volumeGenerator = mitk::TrackingVolumeGenerator::New(); std::string str = qstr.toStdString(); mitk::TrackingDeviceData data = mitk::GetDeviceDataByName(str); m_TrackingDeviceData = data; volumeGenerator->SetTrackingDeviceData(data); volumeGenerator->Update(); mitk::Surface::Pointer volumeSurface = volumeGenerator->GetOutput(); m_TrackingVolumeNode->SetData(volumeSurface); if (!m_Controls->m_ShowTrackingVolume->isChecked()) m_TrackingVolumeNode->SetOpacity(0.0); else m_TrackingVolumeNode->SetOpacity(0.25); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnShowTrackingVolumeChanged() { if (m_Controls->m_ShowTrackingVolume->isChecked()) { OnTrackingVolumeChanged(m_Controls->m_VolumeSelectionBox->currentText()); m_TrackingVolumeNode->SetOpacity(0.25); } else { m_TrackingVolumeNode->SetOpacity(0.0); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectTools() { if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() == mitk::NDIAurora) { DisableTrackingConfigurationButtons(); m_Worker->SetWorkerMethod(QmitkMITKIGTTrackingToolboxViewWorker::eAutoDetectTools); m_Worker->SetTrackingDevice(m_Controls->m_configurationWidget->GetTrackingDevice().GetPointer()); m_Worker->SetDataStorage(this->GetDataStorage()); m_WorkerThread->start(); m_TimeoutTimer->start(5000); MITK_INFO << "Timeout Timer started"; //disable controls until worker thread is finished this->m_Controls->m_MainWidget->setEnabled(false); } } void QmitkMITKIGTTrackingToolboxView::OnAutoDetectToolsFinished(bool success, QString errorMessage) { m_TimeoutTimer->stop(); m_WorkerThread->quit(); m_WorkerThread->wait(); //enable controls again this->m_Controls->m_MainWidget->setEnabled(true); EnableTrackingConfigurationButtons(); if(!success) { MITK_WARN << errorMessage.toStdString(); MessageBox(errorMessage.toStdString()); EnableTrackingConfigurationButtons(); return; } mitk::NavigationToolStorage::Pointer autoDetectedStorage = m_Worker->GetNavigationToolStorage(); //save detected tools this->ReplaceCurrentToolStorage(autoDetectedStorage,"Autodetected NDI Aurora Storage"); //auto save the new storage to hard disc (for persistence) AutoSaveToolStorage(); //update label QString toolLabel = QString("Loaded Tools: ") + QString::number(m_toolStorage->GetToolCount()) + " Tools (Auto Detected)"; m_Controls->m_toolLabel->setText(toolLabel); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); EnableTrackingConfigurationButtons(); if (m_toolStorage->GetToolCount()>0) { //ask the user if he wants to save the detected tools QMessageBox msgBox; switch(m_toolStorage->GetToolCount()) { case 1: msgBox.setText("Found one tool!"); break; default: msgBox.setText("Found " + QString::number(m_toolStorage->GetToolCount()) + " tools!"); } msgBox.setInformativeText("Do you want to save this tools as tool storage, so you can load them again?"); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::No); int ret = msgBox.exec(); if (ret == 16384) //yes { //ask the user for a filename QString fileName = QFileDialog::getSaveFileName(NULL, tr("Save File"),"/",tr("*.IGTToolStorage")); //check for empty filename if(fileName == "") {return;} mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); //when Serialize method is used exceptions are thrown, need to be adapted //try-catch block for exception handling in Serializer try { mySerializer->Serialize(fileName.toStdString(),m_toolStorage); } catch(mitk::IGTException) { std::string errormessage = "Error during serialization. Please check the Zip file."; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); } return; } else if (ret == 65536) //no { return; } } //print a logging message about the detected tools switch(m_toolStorage->GetToolCount()) { case 0: MITK_INFO("IGT Tracking Toolbox") << "Found no tools. Empty ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); break; case 1: MITK_INFO("IGT Tracking Toolbox") << "Found one tool. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); break; default: MITK_INFO("IGT Tracking Toolbox") << "Found " << m_toolStorage->GetToolCount() << " tools. ToolStorage was autosaved to " << m_ToolStorageFilename.toStdString(); } } void QmitkMITKIGTTrackingToolboxView::MessageBox(std::string s) { QMessageBox msgBox; msgBox.setText(s.c_str()); msgBox.exec(); } void QmitkMITKIGTTrackingToolboxView::UpdateRenderTrackingTimer() { //update filter m_ToolVisualizationFilter->Update(); MITK_DEBUG << "Number of outputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedOutputs(); MITK_DEBUG << "Number of inputs ToolVisualizationFilter: " << m_ToolVisualizationFilter->GetNumberOfIndexedInputs(); //update tool colors to show tool status for(unsigned int i=0; iGetNumberOfIndexedOutputs(); i++) { mitk::NavigationData::Pointer currentTool = m_ToolVisualizationFilter->GetOutput(i); if(currentTool->IsDataValid()) {this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_VALID);} else {this->m_toolStorage->GetTool(i)->GetDataNode()->SetColor(mitk::IGTColor_WARNING);} } //refresh view and status widget mitk::RenderingManager::GetInstance()->RequestUpdateAll(); m_Controls->m_TrackingToolsStatusWidget->Refresh(); //code to better isolate bug 17713, could be removed when bug 17713 is fixed static int i = 0; static mitk::Point3D lastPositionTool1 = m_ToolVisualizationFilter->GetOutput(0)->GetPosition(); static itk::TimeStamp lastTimeStamp = m_ToolVisualizationFilter->GetOutput(0)->GetTimeStamp(); i++; //every 20 frames: check if tracking is frozen if(i>20) { i = 0; if (m_ToolVisualizationFilter->GetOutput(0)->IsDataValid()) { if (mitk::Equal(lastPositionTool1,m_ToolVisualizationFilter->GetOutput(0)->GetPosition(),0.000000001,false)) { MITK_WARN << "Seems as tracking (of at least tool 1) is frozen which means that bug 17713 occurred. Restart tracking might help."; //display further information to find the bug MITK_WARN << "Timestamp of current navigation data: " << m_ToolVisualizationFilter->GetOutput(0)->GetTimeStamp(); MITK_WARN << "Timestamp of last navigation data (which holds the same values): " << lastTimeStamp; } lastPositionTool1 = m_ToolVisualizationFilter->GetOutput(0)->GetPosition(); lastTimeStamp = m_ToolVisualizationFilter->GetOutput(0)->GetTimeStamp(); } } } void QmitkMITKIGTTrackingToolboxView::UpdateLoggingTrackingTimer() { //update logging if (m_logging) { this->m_loggingFilter->Update(); m_loggedFrames = this->m_loggingFilter->GetNumberOfRecordedSteps(); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: "+QString::number(m_loggedFrames)); //check if logging stopped automatically if((m_loggedFrames>1)&&(!m_loggingFilter->GetRecording())){StopLogging();} } //refresh status widget m_Controls->m_TrackingToolsStatusWidget->Refresh(); } void QmitkMITKIGTTrackingToolboxView::OnChooseFileClicked() { QDir currentPath = QFileInfo(m_Controls->m_LoggingFileName->text()).dir(); // if no path was selected (QDir would select current working dir then) or the // selected path does not exist -> use home directory if ( currentPath == QDir() || ! currentPath.exists() ) { currentPath = QDir(QDir::homePath()); } QString filename = QFileDialog::getSaveFileName(NULL,tr("Choose Logging File"), currentPath.absolutePath(), "*.*"); if (filename == "") return; this->m_Controls->m_LoggingFileName->setText(filename); this->OnToggleFileExtension(); } // bug-16470: toggle file extension after clicking on radio button void QmitkMITKIGTTrackingToolboxView::OnToggleFileExtension() { QString currentInputText = this->m_Controls->m_LoggingFileName->text(); QString currentFile = QFileInfo(currentInputText).baseName(); QDir currentPath = QFileInfo(currentInputText).dir(); if(currentFile.isEmpty()) { currentFile = "logfile"; } // Setting currentPath to default home path when currentPath is empty or it does not exist if(currentPath == QDir() || !currentPath.exists()) { currentPath = QDir::homePath(); } // check if csv radio button is clicked if(this->m_Controls->m_csvFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if(currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".csv"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".csv"); } } // check if xml radio button is clicked else if(this->m_Controls->m_xmlFormat->isChecked()) { // you needn't add a seperator to the input text when currentpath is the rootpath if(currentPath.isRoot()) { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + currentFile + ".xml"); } else { this->m_Controls->m_LoggingFileName->setText(QDir::toNativeSeparators(currentPath.absolutePath()) + QDir::separator() + currentFile + ".xml"); } } } void QmitkMITKIGTTrackingToolboxView::OnToggleDifferentUpdateRates() { if(m_Controls->m_UseDifferentUpdateRates->isChecked()) { if(m_Controls->m_RenderUpdateRate->value() == 0) m_Controls->m_renderWarningLabel->setVisible(true); else m_Controls->m_renderWarningLabel->setVisible(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); m_Controls->m_RenderUpdateRate->setEnabled(true); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(true); m_Controls->m_LogUpdateRate->setEnabled(true); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(true); } else { m_Controls->m_renderWarningLabel->setVisible(false); m_Controls->m_UpdateRate->setEnabled(true); m_Controls->m_OptionsUpdateRateLabel->setEnabled(true); m_Controls->m_RenderUpdateRate->setEnabled(false); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false); m_Controls->m_LogUpdateRate->setEnabled(false); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false); } } void QmitkMITKIGTTrackingToolboxView::OnChangeRenderUpdateRate() { if(m_Controls->m_RenderUpdateRate->value() == 0) m_Controls->m_renderWarningLabel->setVisible(true); else m_Controls->m_renderWarningLabel->setVisible(false); } void QmitkMITKIGTTrackingToolboxView::StartLogging() { if (m_ToolVisualizationFilter.IsNull()) { MessageBox("Cannot activate logging without a connected device. Configure and connect a tracking device first."); return; } if (!m_logging) { //initialize logging filter m_loggingFilter = mitk::NavigationDataRecorder::New(); m_loggingFilter->ConnectTo(m_ToolVisualizationFilter); if (m_Controls->m_LoggingLimit->isChecked()){m_loggingFilter->SetRecordCountLimit(m_Controls->m_LoggedFramesLimit->value());} //start filter with try-catch block for exceptions try { m_loggingFilter->StartRecording(); } catch(mitk::IGTException) { std::string errormessage = "Error during start recording. Recorder already started recording?"; QMessageBox::warning(NULL, "IGTPlayer: Error", errormessage.c_str()); m_loggingFilter->StopRecording(); return; } //update labels / logging variables this->m_Controls->m_LoggingLabel->setText("Logging ON"); this->m_Controls->m_LoggedFramesLabel->setText("Logged Frames: 0"); m_loggedFrames = 0; m_logging = true; DisableLoggingButtons(); } } void QmitkMITKIGTTrackingToolboxView::StopLogging() { if (m_logging) { //stop logging m_loggingFilter->StopRecording(); m_logging = false; //update GUI this->m_Controls->m_LoggingLabel->setText("Logging OFF"); EnableLoggingButtons(); //write the results to a file if(m_Controls->m_csvFormat->isChecked()) { - mitk::NavigationDataSetWriterCSV* writer = new mitk::NavigationDataSetWriterCSV(); - writer->Write(this->m_Controls->m_LoggingFileName->text().toStdString(),m_loggingFilter->GetNavigationDataSet()); - delete writer; + mitk::IOUtil::SaveBaseData(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString()); } else if (m_Controls->m_xmlFormat->isChecked()) { - mitk::NavigationDataSetWriterXML* writer = new mitk::NavigationDataSetWriterXML(); - writer->Write(this->m_Controls->m_LoggingFileName->text().toStdString(),m_loggingFilter->GetNavigationDataSet()); - delete writer; + mitk::IOUtil::SaveBaseData(m_loggingFilter->GetNavigationDataSet(), this->m_Controls->m_LoggingFileName->text().toStdString()); } } } void QmitkMITKIGTTrackingToolboxView::OnAddSingleTool() { QString Identifier = "Tool#"; QString Name = "NewTool"; if (m_toolStorage.IsNotNull()) { Identifier += QString::number(m_toolStorage->GetToolCount()); Name += QString::number(m_toolStorage->GetToolCount()); } else { Identifier += "0"; Name += "0"; } m_Controls->m_NavigationToolCreationWidget->Initialize(GetDataStorage(),Identifier.toStdString(),Name.toStdString()); m_Controls->m_NavigationToolCreationWidget->SetTrackingDeviceType(m_Controls->m_configurationWidget->GetTrackingDevice()->GetType(),false); m_Controls->m_TrackingToolsWidget->setCurrentIndex(1); //disable tracking volume during tool editing lastTrackingVolumeState = m_Controls->m_ShowTrackingVolume->isChecked(); if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolFinished() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); if (this->m_toolStorage.IsNull()) { //this shouldn't happen! MITK_WARN << "No ToolStorage available, cannot add tool, aborting!"; return; } m_toolStorage->AddTool(m_Controls->m_NavigationToolCreationWidget->GetCreatedTool()); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); m_Controls->m_toolLabel->setText(""); //auto save current storage for persistence MITK_INFO << "Auto saving manually added tools for persistence."; AutoSaveToolStorage(); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnAddSingleToolCanceled() { m_Controls->m_TrackingToolsWidget->setCurrentIndex(0); //enable tracking volume again if (lastTrackingVolumeState) m_Controls->m_ShowTrackingVolume->click(); GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::GlobalReinit() { // get all nodes that have not set "includeInBoundingBox" to false mitk::NodePredicateNot::Pointer pred = mitk::NodePredicateNot::New(mitk::NodePredicateProperty::New("includeInBoundingBox", mitk::BoolProperty::New(false))); mitk::DataStorage::SetOfObjects::ConstPointer rs = this->GetDataStorage()->GetSubset(pred); // calculate bounding geometry of these nodes mitk::TimeGeometry::Pointer bounds = this->GetDataStorage()->ComputeBoundingGeometry3D(rs, "visible"); // initialize the views to the bounding geometry mitk::RenderingManager::GetInstance()->InitializeViews(bounds); } void QmitkMITKIGTTrackingToolboxView::DisableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(false); m_Controls->m_LoggingFileName->setEnabled(false); m_Controls->m_ChooseFile->setEnabled(false); m_Controls->m_LoggingLimit->setEnabled(false); m_Controls->m_LoggedFramesLimit->setEnabled(false); m_Controls->m_csvFormat->setEnabled(false); m_Controls->m_xmlFormat->setEnabled(false); m_Controls->m_StopLogging->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::EnableLoggingButtons() { m_Controls->m_StartLogging->setEnabled(true); m_Controls->m_LoggingFileName->setEnabled(true); m_Controls->m_ChooseFile->setEnabled(true); m_Controls->m_LoggingLimit->setEnabled(true); m_Controls->m_LoggedFramesLimit->setEnabled(true); m_Controls->m_csvFormat->setEnabled(true); m_Controls->m_xmlFormat->setEnabled(true); m_Controls->m_StopLogging->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::DisableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(false); - m_Controls->m_ShowToolQuaternions->setEnabled(false); m_Controls->m_UseDifferentUpdateRates->setEnabled(false); m_Controls->m_UpdateRate->setEnabled(false); m_Controls->m_OptionsUpdateRateLabel->setEnabled(false); m_Controls->m_RenderUpdateRate->setEnabled(false); m_Controls->m_OptionsRenderUpdateRateLabel->setEnabled(false); m_Controls->m_LogUpdateRate->setEnabled(false); m_Controls->m_OptionsLogUpdateRateLabel->setEnabled(false); m_Controls->m_DisableAllTimers->setEnabled(false); + m_Controls->m_OtherOptionsGroupBox->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(true); - m_Controls->m_ShowToolQuaternions->setEnabled(true); m_Controls->m_UseDifferentUpdateRates->setEnabled(true); m_Controls->m_DisableAllTimers->setEnabled(true); + m_Controls->m_OtherOptionsGroupBox->setEnabled(true); OnToggleDifferentUpdateRates(); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingControls() { m_Controls->m_TrackingControlsGroupBox->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingControls() { m_Controls->m_TrackingControlsGroupBox->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::EnableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(true); if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAurora) m_Controls->m_AddSingleTool->setEnabled(true); m_Controls->m_LoadTools->setEnabled(true); m_Controls->m_ResetTools->setEnabled(true); } void QmitkMITKIGTTrackingToolboxView::DisableTrackingConfigurationButtons() { m_Controls->m_AutoDetectTools->setEnabled(false); if (m_Controls->m_configurationWidget->GetTrackingDevice()->GetType() != mitk::NDIAurora) m_Controls->m_AddSingleTool->setEnabled(false); m_Controls->m_LoadTools->setEnabled(false); m_Controls->m_ResetTools->setEnabled(false); } void QmitkMITKIGTTrackingToolboxView::ReplaceCurrentToolStorage(mitk::NavigationToolStorage::Pointer newStorage, std::string newStorageName) { //first: get rid of the old one //don't reset if there is no tool storage. BugFix #17793 if ( m_toolStorage.IsNotNull() ){ m_toolStorage->UnLockStorage(); //only to be sure... m_toolStorage->UnRegisterMicroservice(); m_toolStorage = NULL; } //now: replace by the new one m_toolStorage = newStorage; m_toolStorage->SetName(newStorageName); m_toolStorage->RegisterAsMicroservice("no tracking device"); } void QmitkMITKIGTTrackingToolboxView::OnTimeOut() { MITK_INFO << "Time Out"; m_WorkerThread->terminate(); m_WorkerThread->wait(); m_TimeoutTimer->stop(); } void QmitkMITKIGTTrackingToolboxView::StoreUISettings() { // persistence service does not directly work in plugins for now // -> using QSettings QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); // set the values of some widgets and attrbutes to the QSettings settings.setValue("ShowTrackingVolume", QVariant(m_Controls->m_ShowTrackingVolume->isChecked())); settings.setValue("toolStorageFilename", QVariant(m_ToolStorageFilename)); settings.setValue("VolumeSelectionBox", QVariant(m_Controls->m_VolumeSelectionBox->currentIndex())); settings.endGroup(); } void QmitkMITKIGTTrackingToolboxView::LoadUISettings() { // persistence service does not directly work in plugins for now // -> using QSettings QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); // set some widgets and attributes by the values from the QSettings m_Controls->m_ShowTrackingVolume->setChecked(settings.value("ShowTrackingVolume", true).toBool()); m_Controls->m_VolumeSelectionBox->setCurrentIndex(settings.value("VolumeSelectionBox", 0).toInt()); m_ToolStorageFilename = settings.value("toolStorageFilename", QVariant("")).toString(); settings.endGroup(); // try to deserialize the tool storage from the given tool storage file name if ( ! m_ToolStorageFilename.isEmpty() ) { // try-catch block for exceptions try { mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); m_toolStorage->UnRegisterMicroservice(); m_toolStorage = myDeserializer->Deserialize(m_ToolStorageFilename.toStdString()); m_toolStorage->RegisterAsMicroservice("no tracking device"); //update label UpdateToolStorageLabel(m_ToolStorageFilename); //update tool preview m_Controls->m_TrackingToolsStatusWidget->RemoveStatusLabels(); m_Controls->m_TrackingToolsStatusWidget->PreShowTools(m_toolStorage); } catch(mitk::IGTException) { MITK_WARN("QmitkMITKIGTTrackingToolBoxView") << "Error during restoring tools. Problems with file ("<OnResetTools(); //if there where errors reset the tool storage to avoid problems later on } } } void QmitkMITKIGTTrackingToolboxView::UpdateToolStorageLabel(QString pathOfLoadedStorage) { QFileInfo myPath(pathOfLoadedStorage); //use this to seperate filename from path QString toolLabel = myPath.fileName(); if (toolLabel.size() > 45) //if the tool storage name is to long trimm the string { toolLabel.resize(40); toolLabel+="[...]"; } m_Controls->m_toolLabel->setText(toolLabel); } void QmitkMITKIGTTrackingToolboxView::AutoSaveToolStorage() { m_ToolStorageFilename = m_AutoSaveFilename; mitk::NavigationToolStorageSerializer::Pointer mySerializer = mitk::NavigationToolStorageSerializer::New(); mySerializer->Serialize(m_ToolStorageFilename.toStdString(),m_toolStorage); } void QmitkMITKIGTTrackingToolboxViewWorker::SetWorkerMethod(WorkerMethod w) { m_WorkerMethod = w; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDevice(mitk::TrackingDevice::Pointer t) { m_TrackingDevice = t; } void QmitkMITKIGTTrackingToolboxViewWorker::SetDataStorage(mitk::DataStorage::Pointer d) { m_DataStorage = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetInverseMode(bool mode) { m_InverseMode = mode; } void QmitkMITKIGTTrackingToolboxViewWorker::SetTrackingDeviceData(mitk::TrackingDeviceData d) { m_TrackingDeviceData = d; } void QmitkMITKIGTTrackingToolboxViewWorker::SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n) { m_NavigationToolStorage = n; } void QmitkMITKIGTTrackingToolboxViewWorker::ThreadFunc() { switch(m_WorkerMethod) { case eAutoDetectTools: this->AutoDetectTools(); break; case eConnectDevice: this->ConnectDevice(); break; case eStartTracking: this->StartTracking(); break; case eStopTracking: this->StopTracking(); break; case eDisconnectDevice: this->DisconnectDevice(); break; default: MITK_WARN << "Undefined worker method was set ... something went wrong!"; break; } } void QmitkMITKIGTTrackingToolboxViewWorker::AutoDetectTools() { mitk::ProgressBar::GetInstance()->AddStepsToDo(4); mitk::NavigationToolStorage::Pointer autoDetectedStorage = mitk::NavigationToolStorage::New(m_DataStorage); mitk::NDITrackingDevice::Pointer currentDevice = dynamic_cast(m_TrackingDevice.GetPointer()); try { currentDevice->OpenConnection(); mitk::ProgressBar::GetInstance()->Progress(); currentDevice->StartTracking(); } catch(mitk::Exception& e) { QString message = QString("Warning, can not auto-detect tools! (") + QString(e.GetDescription()) + QString(")"); //MessageBox(message.toStdString()); //TODO: give message to the user here! MITK_WARN << message.toStdString(); mitk::ProgressBar::GetInstance()->Progress(4); emit AutoDetectToolsFinished(false,message.toStdString().c_str()); return; } for (unsigned int i=0; iGetToolCount(); i++) { //create a navigation tool with sphere as surface std::stringstream toolname; toolname << "AutoDetectedTool" << i; mitk::NavigationTool::Pointer newTool = mitk::NavigationTool::New(); newTool->SetSerialNumber(dynamic_cast(currentDevice->GetTool(i))->GetSerialNumber()); newTool->SetIdentifier(toolname.str()); newTool->SetTrackingDeviceType(mitk::NDIAurora); mitk::DataNode::Pointer newNode = mitk::DataNode::New(); mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(3.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); newNode->SetData(mySphere); newNode->SetName(toolname.str()); newTool->SetDataNode(newNode); autoDetectedStorage->AddTool(newTool); } m_NavigationToolStorage = autoDetectedStorage; currentDevice->StopTracking(); mitk::ProgressBar::GetInstance()->Progress(); currentDevice->CloseConnection(); emit AutoDetectToolsFinished(true,""); mitk::ProgressBar::GetInstance()->Progress(4); } void QmitkMITKIGTTrackingToolboxViewWorker::ConnectDevice() { std::string message = ""; mitk::ProgressBar::GetInstance()->AddStepsToDo(10); //build the IGT pipeline mitk::TrackingDevice::Pointer trackingDevice = m_TrackingDevice; trackingDevice->SetData(m_TrackingDeviceData); //set device to rotation mode transposed becaus we are working with VNL style quaternions if(m_InverseMode) {trackingDevice->SetRotationMode(mitk::TrackingDevice::RotationTransposed);} //Get Tracking Volume Data mitk::TrackingDeviceData data = m_TrackingDeviceData; mitk::ProgressBar::GetInstance()->Progress(); //Create Navigation Data Source with the factory class mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory = mitk::TrackingDeviceSourceConfigurator::New(m_NavigationToolStorage,trackingDevice); m_TrackingDeviceSource = myTrackingDeviceSourceFactory->CreateTrackingDeviceSource(m_ToolVisualizationFilter); mitk::ProgressBar::GetInstance()->Progress(); if ( m_TrackingDeviceSource.IsNull() ) { message = std::string("Cannot connect to device: ") + myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false,QString(message.c_str())); return; } //set filter to rotation mode transposed becaus we are working with VNL style quaternions if(m_InverseMode) m_ToolVisualizationFilter->SetRotationMode(mitk::NavigationDataObjectVisualizationFilter::RotationTransposed); //First check if the created object is valid if (m_TrackingDeviceSource.IsNull()) { message = myTrackingDeviceSourceFactory->GetErrorMessage(); emit ConnectDeviceFinished(false,QString(message.c_str())); return; } MITK_INFO << "Number of tools: " << m_TrackingDeviceSource->GetNumberOfOutputs(); mitk::ProgressBar::GetInstance()->Progress(); //The tools are maybe reordered after initialization, e.g. in case of auto-detected tools of NDI Aurora mitk::NavigationToolStorage::Pointer toolsInNewOrder = myTrackingDeviceSourceFactory->GetUpdatedNavigationToolStorage(); if ((toolsInNewOrder.IsNotNull()) && (toolsInNewOrder->GetToolCount() > 0)) { //so delete the old tools in wrong order and add them in the right order //we cannot simply replace the tool storage because the new storage is //not correctly initialized with the right data storage /* m_NavigationToolStorage->DeleteAllTools(); for (int i=0; i < toolsInNewOrder->GetToolCount(); i++) {m_NavigationToolStorage->AddTool(toolsInNewOrder->GetTool(i));} This was replaced and thereby fixed Bug 18318 DeleteAllTools() is not Threadsafe! */ for(int i = 0; i < toolsInNewOrder->GetToolCount(); i++ ) { m_NavigationToolStorage->AssignToolNumber(toolsInNewOrder->GetTool(i)->GetIdentifier(),i); } } mitk::ProgressBar::GetInstance()->Progress(); //connect to device try { m_TrackingDeviceSource->Connect(); mitk::ProgressBar::GetInstance()->Progress(); //Microservice registration: m_TrackingDeviceSource->RegisterAsMicroservice(); m_NavigationToolStorage->UnRegisterMicroservice(); m_NavigationToolStorage->RegisterAsMicroservice(m_TrackingDeviceSource->GetMicroserviceID()); m_NavigationToolStorage->LockStorage(); } catch (...) //todo: change to mitk::IGTException { message = "Error on connecting the tracking device."; emit ConnectDeviceFinished(false,QString(message.c_str())); return; } emit ConnectDeviceFinished(true,QString(message.c_str())); mitk::ProgressBar::GetInstance()->Progress(10); } void QmitkMITKIGTTrackingToolboxViewWorker::StartTracking() { QString errorMessage = ""; try { m_TrackingDeviceSource->StartTracking(); } catch (...) //todo: change to mitk::IGTException { errorMessage += "Error while starting the tracking device!"; emit StartTrackingFinished(false,errorMessage); return; } //remember the original colors of the tools m_OriginalColors = std::map(); for(int i=0; im_NavigationToolStorage->GetToolCount(); i++) { mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); float c[3]; currentToolNode->GetColor(c); mitk::Color color; color.SetRed(c[0]); color.SetGreen(c[1]); color.SetBlue(c[2]); m_OriginalColors[currentToolNode] = color; } emit StartTrackingFinished(true,errorMessage); } void QmitkMITKIGTTrackingToolboxViewWorker::StopTracking() { //stop tracking try { m_TrackingDeviceSource->StopTracking(); } catch(mitk::Exception& e) { emit StopTrackingFinished(false, e.GetDescription()); } //restore the original colors of the tools for(int i=0; im_NavigationToolStorage->GetToolCount(); i++) { mitk::DataNode::Pointer currentToolNode = m_NavigationToolStorage->GetTool(i)->GetDataNode(); if (m_OriginalColors.find(currentToolNode) == m_OriginalColors.end()) {MITK_WARN << "Cannot restore original color of tool " << m_NavigationToolStorage->GetTool(i)->GetToolName();} else {currentToolNode->SetColor(m_OriginalColors[currentToolNode]);} } //emit signal emit StopTrackingFinished(true, ""); } void QmitkMITKIGTTrackingToolboxViewWorker::DisconnectDevice() { try { if (m_TrackingDeviceSource->IsTracking()) {m_TrackingDeviceSource->StopTracking();} m_TrackingDeviceSource->Disconnect(); m_TrackingDeviceSource->UnRegisterMicroservice(); m_NavigationToolStorage->UnLockStorage(); } catch(mitk::Exception& e) { emit DisconnectDeviceFinished(false, e.GetDescription()); } emit DisconnectDeviceFinished(true, ""); } diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h index 239915ae8b..ab784ff442 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h @@ -1,293 +1,302 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef QmitkMITKIGTTrackingToolboxView_h #define QmitkMITKIGTTrackingToolboxView_h #include #include #include "ui_QmitkMITKIGTTrackingToolboxViewControls.h" //mitk headers #include #include #include #include +#include +#include +#include //QT headers #include class QmitkMITKIGTTrackingToolboxViewWorker; /*! \brief QmitkMITKIGTTrackingToolboxView This is the view of the bundle IGT Tracking Toolbox. The IGT Tracking Toolbox can be used to access tracking devices with MITK-IGT. The Tracking Toolbox can be used to log tracking data in XML or CSV format for measurement purposes. The Tracking Toolbox further allows for visualization of tools with given surfaces in combination with the NaviagtionToolManager. \sa QmitkFunctionality \ingroup Functionalities */ class QmitkMITKIGTTrackingToolboxView : public QmitkFunctionality { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: static const std::string VIEW_ID; QmitkMITKIGTTrackingToolboxView(); virtual ~QmitkMITKIGTTrackingToolboxView(); virtual void CreateQtPartControl(QWidget *parent) override; virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget) override; virtual void StdMultiWidgetNotAvailable() override; protected slots: /** @brief changes name of the filename when switching fileextension by radio button */ void OnToggleFileExtension(); /** @brief This slot is called if the user wants to load a new tool file. A new window opens where the user can choose a file. If the chosen file is corrupt or not valid the user gets an error message. If the file was loaded successfully the tools are show in the tool status widget. */ void OnLoadTools(); /** Starts tracking if tracking is stopped / stops tracking if tracking is started. */ void OnStartStopTracking(); /** Connects the device if it is disconnected / disconnects the device if it is connected. */ void OnConnectDisconnect(); /** Freezes the device if it is not frozen / unfreezes the device if it is frozen. */ void OnFreezeUnfreezeTracking(); /** @brief This slot connects to the device. In status "connected" configuration of the device is disabled. */ void OnConnect(); /** @brief This slot disconnects from the device. */ void OnDisconnect(); /** @brief This slot tries to start tracking with the current device. If start tracking fails the user gets an error message and tracking stays off.*/ void OnStartTracking(); /** @brief This slot stops tracking. If tracking is not strated it does nothing.*/ void OnStopTracking(); /** @brief This slot is called if the user want's to choose a file name for logging. A new windows to navigate through the file system and choose a file opens.*/ void OnChooseFileClicked(); /** @brief This slot starts logging. Logging is only possible if a device is tracking. If not the logging mechanism start when the start tracking is called.*/ void StartLogging(); /** @brief This slot stops logging. If logging is not running it does nothing.*/ void StopLogging(); /** @brief This slot enables / disables UI elements depending on the tracking device after a device is changed.*/ void OnTrackingDeviceChanged(); /** @brief This slot selects the Tracking Volume appropriate for a given model */ void OnTrackingVolumeChanged(QString qstr); /** @brief Shows or hides the tracking volume according to the checkboxe's state */ void OnShowTrackingVolumeChanged(); /** @brief This slot auto detects tools of a NDI Aurora tracking device. If tools where found they will be stored internally as a tool storage. The user is also asked if he wants to save this tool storage to load it later. Only call it if a Aurora device was configured because other devices don't support auto detection.*/ void OnAutoDetectTools(); /** @brief Slot for tracking timer. The timer updates the IGT pipline and also the logging filter if logging is activated.*/ void UpdateRenderTrackingTimer(); void UpdateLoggingTrackingTimer(); /** @brief Slot for showing the rendering disabled warning label*/ void OnChangeRenderUpdateRate(); /** @brief Resets the Tracking Tools: this means all tools are removed. */ void OnResetTools(); /** @brief Opens a dialog where a new navigation tool can be created. */ void OnAddSingleTool(); /** @brief This slot is called if the user finishes the creation of a new tool. */ void OnAddSingleToolFinished(); /** @brief This slot is called if the user cancels the creation of a new tool. */ void OnAddSingleToolCanceled(); void OnTimeOut(); protected slots: //help slots for enable/disable buttons void DisableLoggingButtons(); void EnableLoggingButtons(); void DisableOptionsButtons(); void EnableOptionsButtons(); void EnableTrackingConfigurationButtons(); void DisableTrackingConfigurationButtons(); void EnableTrackingControls(); void DisableTrackingControls(); + void EnableDisableTimerButtons(int enable); void OnToggleDifferentUpdateRates(); //slots for worker thread void OnAutoDetectToolsFinished(bool success, QString errorMessage); void OnConnectFinished(bool success, QString errorMessage); void OnStartTrackingFinished(bool success, QString errorMessage); void OnStopTrackingFinished(bool success, QString errorMessage); void OnDisconnectFinished(bool success, QString errorMessage); protected: Ui::QmitkMITKIGTTrackingToolboxViewControls* m_Controls; QmitkStdMultiWidget* m_MultiWidget; bool m_tracking; ///> bool which is true if tracking is running, false if not bool m_connected; ///> bool that is true when a tracking device is connected bool m_logging; ///> bool which is true if logging is running, false if not int m_loggedFrames; ///> stores the current number of logged frames if logging is on mitk::NavigationToolStorage::Pointer m_toolStorage; ///>stores the loaded tools mitk::DataNode::Pointer m_TrackingVolumeNode; ///>holds the data node of the tracking volume if volume is visualized bool lastTrackingVolumeState; ///>temporary holds the state of the tracking volume (activated/not activated) during some methods QString m_ToolStorageFilename; ///>stores the filename of the current tool storage QString m_AutoSaveFilename; ///>a filename for auto saving tools if no m_ToolStorageFilename was given by the user /** @brief Shows a message box with the text given as parameter. */ void MessageBox(std::string s); /** @brief reinits the view globally. */ void GlobalReinit(); //members for the filter pipeline mitk::TrackingDeviceSource::Pointer m_TrackingDeviceSource; ///> member for the source of the IGT pipeline mitk::TrackingDeviceData m_TrackingDeviceData; ///> stores the tracking device data as long as this is not handled by the tracking device configuration widget mitk::NavigationDataObjectVisualizationFilter::Pointer m_ToolVisualizationFilter; ///> holds the tool visualization filter (second filter of the IGT pipeline) mitk::NavigationDataRecorder::Pointer m_loggingFilter; ///> holds the logging filter if logging is on (third filter of the IGT pipeline) + //members for open IGT link server + mitk::NavigationDataToIGTLMessageFilter::Pointer m_IGTLConversionFilter; ///> Converts the navigation data as open IGT link message and makes this filter available as microservice + mitk::IGTLServer::Pointer m_IGTLServer; + mitk::IGTLMessageProvider::Pointer m_IGTLMessageProvider; + /** @brief This timer updates the IGT pipline and also the logging filter if logging is activated.*/ QTimer* m_TrackingRenderTimer; QTimer* m_TrackingLoggingTimer; QTimer* m_TimeoutTimer; /** Replaces the current navigation tool storage which is stored in m_toolStorage. * Basically handles the microservice stuff: unregisteres the old storage, then * replaces the storage and registers the new one. */ void ReplaceCurrentToolStorage(mitk::NavigationToolStorage::Pointer newStorage, std::string newStorageName); /** * \brief Stores the properties of some QWidgets (and the tool storage file name) to QSettings. */ void StoreUISettings(); /** * \brief Loads the properties of some QWidgets (and the tool storage file name) from QSettings. */ void LoadUISettings(); /** * Help method for updating the tool label */ void UpdateToolStorageLabel(QString pathOfLoadedStorage); /** * Auto saves the current tool storage to a temporary file. This ist used for persistence. */ void AutoSaveToolStorage(); //members for worker thread QThread* m_WorkerThread; QmitkMITKIGTTrackingToolboxViewWorker* m_Worker; }; /** * Worker thread class for this view. */ class QmitkMITKIGTTrackingToolboxViewWorker : public QObject { Q_OBJECT public: enum WorkerMethod{ eAutoDetectTools = 0, eConnectDevice = 1, eStartTracking = 2, eStopTracking = 3, eDisconnectDevice = 4 }; void SetWorkerMethod(WorkerMethod w); void SetTrackingDevice(mitk::TrackingDevice::Pointer t); void SetDataStorage(mitk::DataStorage::Pointer d); void SetInverseMode(bool mode); void SetTrackingDeviceData(mitk::TrackingDeviceData d); void SetNavigationToolStorage(mitk::NavigationToolStorage::Pointer n); itkGetMacro(NavigationToolStorage,mitk::NavigationToolStorage::Pointer); itkGetMacro(TrackingDeviceSource,mitk::TrackingDeviceSource::Pointer); itkGetMacro(TrackingDeviceData,mitk::TrackingDeviceData); itkGetMacro(ToolVisualizationFilter,mitk::NavigationDataObjectVisualizationFilter::Pointer); public slots: void ThreadFunc(); signals: void AutoDetectToolsFinished(bool success, QString errorMessage); void ConnectDeviceFinished(bool success, QString errorMessage); void StartTrackingFinished(bool success, QString errorMessage); void StopTrackingFinished(bool success, QString errorMessage); void DisconnectDeviceFinished(bool success, QString errorMessage); protected: mitk::TrackingDevice::Pointer m_TrackingDevice; WorkerMethod m_WorkerMethod; mitk::DataStorage::Pointer m_DataStorage; mitk::NavigationToolStorage::Pointer m_NavigationToolStorage; //members for the filter pipeline which is created in the worker thread during ConnectDevice() mitk::TrackingDeviceSource::Pointer m_TrackingDeviceSource; ///> member for the source of the IGT pipeline mitk::TrackingDeviceData m_TrackingDeviceData; ///> stores the tracking device data as long as this is not handled by the tracking device configuration widget mitk::NavigationDataObjectVisualizationFilter::Pointer m_ToolVisualizationFilter; ///> holds the tool visualization filter (second filter of the IGT pipeline) //members some internal flags bool m_InverseMode; //flag that is true when the inverse mode is enabled //stores the original colors of the tracking tools std::map m_OriginalColors; //internal methods void AutoDetectTools(); void ConnectDevice(); void StartTracking(); void StopTracking(); void DisconnectDevice(); }; #endif // _QMITKMITKIGTTRACKINGTOOLBOXVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui index d01673ecab..0c6200aa1b 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui @@ -1,791 +1,805 @@ QmitkMITKIGTTrackingToolboxViewControls 0 0 - 388 - 658 + 457 + 1009 0 0 QmitkTemplate 0 Tracking 0 0 0 0 16777215 280 0 0 6 75 true <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tracking Tools</span></p></body></html> 0 0 ToolStorage: <none> Qt::Horizontal 40 20 200 80 Qt::Horizontal 13 49 120 0 Auto Detection 120 0 Add Single Tool 120 0 Load Tool Storage 120 0 Reset <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:10pt; font-weight:600;">Tracking Control</span></p></body></html> Status: disconnected Qt::Horizontal 40 20 142 0 Connect Qt::Horizontal 40 20 142 0 Start Tracking Qt::Horizontal 40 20 <html><head/><body><p><span style=" color:#ff0000;">Tracking Frozen!</span></p></body></html> true 142 0 Freeze Tracking Qt::Vertical 20 40 Options - + - - - true - - - Show Tracking Volume - - - true - - - - - - - Select Model: - - - - - - - - - - Qt::Horizontal - - - - - + - + - Update Rate [per second] + Disable All Timers - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 1 - - - 100 - - - 10 - - - - - - - - - Use different Render and Log Update Rates - - - - - - - + - false + true - Render Update Rate [fps] + <html><head/><body><p align="right"><span style=" color:#ff0000;">Rendering Disabled!</span></p></body></html> - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - 0 - - - 100 - - - 10 + + Qt::AutoText - - - true - - - <html><head/><body><p align="right"><span style=" color:#ff0000;">Rendering Disabled!</span></p></body></html> - - - Qt::AutoText + + + Update Rate Options + + + + + + + Update Rate [per second] + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 100 + + + 10 + + + + + + + + + Use different Render and Log Update Rates + + + + + + + + + false + + + Render Update Rate [fps] + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + 0 + + + 100 + + + 10 + + + + + + + + + + + false + + + Log Update Rate [per second] + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + false + + + 1 + + + 120 + + + 10 + + + 60 + + + + + + - - - - - false - - - Log Update Rate [per second] - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - false - - - 1 - - - 120 - - - 10 - - - 60 - - - - - - - - - Disable All Timers + + + Tracking Volume Options + + + + + true + + + Show Tracking Volume + + + true + + + + + + + Select Model: + + + + + + + - - - Qt::Vertical - - - - 20 - 100 - + + + Other Options - - - - - - - - Show Tool Quaternions - - - - - - - Caution, only for backward compatibility: - - - - - - - Inverse mode (Quaternions are stored inverse) - - - - + + + + + Show Tool Quaternions + + + + + + + Enable Open IGT Link MicroService + + + true + + + + + + + Caution, only for backward compatibility: + + + + + + + Inverse mode (Quaternions are stored inverse) + + + + + Qt::Vertical 20 600 Logging Filename: Choose File Limit Number Of Logged Frames: Qt::Horizontal 40 20 1 9999 300 CSV format true XML format Logging Status Logging OFF Logged Frames: 0 Qt::Horizontal 40 20 Start Logging Stop Logging Qt::Vertical 20 40 QmitkTrackingDeviceConfigurationWidget QWidget
QmitkTrackingDeviceConfigurationWidget.h
1
QmitkToolTrackingStatusWidget QWidget
QmitkToolTrackingStatusWidget.h
1
QmitkNavigationToolCreationWidget QWidget
QmitkNavigationToolCreationWidget.h
1
diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp index 3c06c30f0f..3767f5598c 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkNavigationDataPlayerView.cpp @@ -1,248 +1,237 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Qmitk #include "QmitkNavigationDataPlayerView.h" // QT #include #include //mitk #include #include -#include -#include #include #include #include +#include // VTK #include const std::string QmitkNavigationDataPlayerView::VIEW_ID = "org.mitk.views.navigationdataplayer"; QmitkNavigationDataPlayerView::QmitkNavigationDataPlayerView() : m_Controls( 0 ) { } QmitkNavigationDataPlayerView::~QmitkNavigationDataPlayerView() { } void QmitkNavigationDataPlayerView::CreateQtPartControl( QWidget *parent ) { // build up qt view, unless already done if ( !m_Controls ) { // create GUI widgets from the Qt Designer's .ui file m_Controls = new Ui::QmitkNavigationDataPlayerViewControls; m_Controls->setupUi( parent ); this->CreateConnections(); // make deselected Player invisible m_Controls->m_TimedWidget->setVisible(false); } } void QmitkNavigationDataPlayerView::SetFocus() { if ( m_Controls ) { m_Controls->m_grpbxControls->setFocus(); } } void QmitkNavigationDataPlayerView::CreateConnections() { connect( m_Controls->m_RdbSequential, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); connect( m_Controls->m_RdbTimeBased, SIGNAL(released()), this, SLOT(OnSelectPlayer()) ); connect( m_Controls->m_BtnOpenFile, SIGNAL(released()), this, SLOT(OnOpenFile()) ); connect( m_Controls->m_ChkDisplay, SIGNAL(released()), this, SLOT(OnSetDisplay()) ); connect( m_Controls->m_chkRepeat, SIGNAL(stateChanged(int)), this, SLOT(OnSetRepeat(int)) ); connect( m_Controls->m_ChkMicroservice, SIGNAL(released()), this, SLOT(OnSetMicroservice()) ); connect( m_Controls->m_SequentialWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); connect( m_Controls->m_TimedWidget, SIGNAL(SignalUpdate()), this, SLOT(OnUpdate()) ); this->SetInteractionComponentsEnabledState(false); } void QmitkNavigationDataPlayerView::OnOpenFile() { mitk::NavigationDataReaderInterface::Pointer reader = NULL; QString filter = tr("NavigationData File (*.csv *.xml)"); QString fileName = QFileDialog::getOpenFileName(NULL, tr("Open NavigationData Set"), "", filter); if ( fileName.isNull() ) { return; } // user pressed cancel try { - QString suffix = QFileInfo(fileName).suffix().toLower(); - if(suffix == "xml") - { - reader = mitk::NavigationDataReaderXML::New(); - } - else if(suffix == "csv") - { - reader = mitk::NavigationDataReaderCSV::New(); - } - - m_Data = reader->Read(fileName.toStdString()); + m_Data = dynamic_cast (mitk::IOUtil::LoadBaseData(fileName.toStdString()).GetPointer()); } catch ( const mitk::Exception &e ) { MITK_WARN("NavigationDataPlayerView") << "could not open file " << fileName.toStdString(); QMessageBox::critical(0, "Error Reading File", "The file '" + fileName +"' could not be read.\n" + e.GetDescription() ); return; } // Update Labels m_Controls->m_LblFilePath->setText(fileName); m_Controls->m_LblFrames->setText(QString::number(m_Data->Size())); m_Controls->m_LblTools->setText(QString::number(m_Data->GetNumberOfTools())); // Initialize Widgets and create Player this->OnSelectPlayer(); this->SetInteractionComponentsEnabledState(true); } void QmitkNavigationDataPlayerView::OnSelectPlayer() { if (m_Controls->m_RdbSequential->isChecked()) { m_Controls->m_SequentialWidget->setVisible(true); m_Controls->m_TimedWidget->setVisible(false); mitk::NavigationDataSequentialPlayer::Pointer seqPlayer = mitk::NavigationDataSequentialPlayer::New(); seqPlayer->SetNavigationDataSet(m_Data); m_Controls->m_SequentialWidget->SetPlayer(seqPlayer); m_Player = seqPlayer; } else { m_Controls->m_SequentialWidget->setVisible(false); m_Controls->m_TimedWidget->setVisible(true); mitk::NavigationDataPlayer::Pointer timedPlayer = mitk::NavigationDataPlayer::New(); timedPlayer->SetNavigationDataSet(m_Data); m_Controls->m_TimedWidget->SetPlayer(timedPlayer); m_Player = timedPlayer; } this->ConfigurePlayer(); // SetupRenderingPipeline this->OnSetDisplay(); } void QmitkNavigationDataPlayerView::ConfigurePlayer() { // set repeat mode according to the checkbox m_Player->SetRepeat( m_Controls->m_chkRepeat->isChecked() ); } void QmitkNavigationDataPlayerView::OnSetRepeat(int checkState) { m_Player->SetRepeat(checkState != 0); } void QmitkNavigationDataPlayerView::OnSetMicroservice(){ if(m_Controls->m_ChkMicroservice->isChecked()) { m_ToolStorage = mitk::NavigationToolStorage::New(); for (itk::ProcessObject::DataObjectPointerArraySizeType i = 0; i < m_Player->GetNumberOfIndexedOutputs(); i++) { mitk::NavigationTool::Pointer currentDummyTool = mitk::NavigationTool::New(); mitk::VirtualTrackingTool::Pointer dummyTool = mitk::VirtualTrackingTool::New(); std::stringstream name; name << "Virtual Tool " << i; dummyTool->SetToolName(name.str()); currentDummyTool->SetTrackingTool(dummyTool.GetPointer()); currentDummyTool->SetDataNode(m_RenderingNodes.at(i)); currentDummyTool->SetIdentifier(name.str()); m_ToolStorage->AddTool(currentDummyTool); } m_Player->RegisterAsMicroservice(); m_ToolStorage->SetName("NavigationDataPlayer Tool Storage"); m_ToolStorage->RegisterAsMicroservice(m_Player->GetMicroserviceID()); } else { if (m_ToolStorage.IsNotNull()) m_ToolStorage->UnRegisterMicroservice(); m_ToolStorage = NULL; m_Player->UnRegisterMicroservice(); } } void QmitkNavigationDataPlayerView::OnUpdate(){ if (m_VisFilter.IsNotNull()) { m_VisFilter->Update(); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } } void QmitkNavigationDataPlayerView::OnSetDisplay(){ DestroyPipeline(); if ( (m_Controls->m_ChkDisplay->isChecked()) && ( m_Player.IsNotNull() )) { CreatePipeline(); } } void QmitkNavigationDataPlayerView::CreatePipeline(){ m_VisFilter = mitk::NavigationDataObjectVisualizationFilter::New(); m_VisFilter->ConnectTo(m_Player); for (unsigned int i = 0 ; i < m_Player->GetNumberOfIndexedOutputs(); i++ ) { mitk::DataNode::Pointer node = mitk::DataNode::New(); QString name = "Recorded Tool " + QString::number(i + 1); node->SetName(name.toStdString()); //create small sphere and use it as surface mitk::Surface::Pointer mySphere = mitk::Surface::New(); vtkSphereSource *vtkData = vtkSphereSource::New(); vtkData->SetRadius(5.0f); vtkData->SetCenter(0.0, 0.0, 0.0); vtkData->Update(); mySphere->SetVtkPolyData(vtkData->GetOutput()); vtkData->Delete(); node->SetData(mySphere); m_VisFilter->SetRepresentationObject(i, mySphere); // Add Node to DataStorageand to local list of Nodes GetDataStorage()->Add(node); m_RenderingNodes.push_back(node); } m_VisFilter->Update(); mitk::RenderingManager::GetInstance()->InitializeViewsByBoundingObjects(GetDataStorage()); mitk::RenderingManager::GetInstance()->RequestUpdateAll(); } void QmitkNavigationDataPlayerView::DestroyPipeline(){ m_VisFilter = NULL; for (unsigned int i = 0; i < m_RenderingNodes.size(); i++){ this->GetDataStorage()->Remove(m_RenderingNodes[i]); } m_RenderingNodes.clear(); } void QmitkNavigationDataPlayerView::SetInteractionComponentsEnabledState(bool isActive){ m_Controls->m_grpbxSettings->setEnabled(isActive); m_Controls->m_grpbxControls->setEnabled(isActive); } \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igttracking/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.igttracking/src/internal/mitkPluginActivator.cpp index 578dae18ac..11b444de11 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/mitkPluginActivator.cpp +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/mitkPluginActivator.cpp @@ -1,54 +1,56 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkPluginActivator.h" #include #include "QmitkMITKIGTNavigationToolManagerView.h" #include "QmitkMITKIGTTrackingToolboxView.h" #include "QmitkNavigationDataPlayerView.h" +#include "IGTNavigationToolCalibration.h" //#include //Workaround for bug in persistence module (see bug 16643 for details) //CAN BE REMOVED WHEN THE BUG IS FIXED namespace mitk { void PluginActivator::start(ctkPluginContext* context) { // mitk::PersistenceService::LoadModule(); //Workaround for bug in persistence module (see bug 16643 for details) //CAN BE REMOVED WHEN THE BUG IS FIXED BERRY_REGISTER_EXTENSION_CLASS(QmitkMITKIGTNavigationToolManagerView, context) - BERRY_REGISTER_EXTENSION_CLASS( QmitkMITKIGTTrackingToolboxView , context) - BERRY_REGISTER_EXTENSION_CLASS( QmitkNavigationDataPlayerView , context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkMITKIGTTrackingToolboxView , context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkNavigationDataPlayerView , context) + BERRY_REGISTER_EXTENSION_CLASS(IGTNavigationToolCalibration , context) } void PluginActivator::stop(ctkPluginContext* context) { Q_UNUSED(context) } } #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) Q_EXPORT_PLUGIN2(org_mitk_gui_qt_igttracking, mitk::PluginActivator) #endif diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp index 4648476704..1fa6d6328f 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.cpp @@ -1,396 +1,478 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ // Blueberry #include #include //Mitk #include #include #include #include #include // Qmitk #include "UltrasoundSupport.h" // Qt #include #include #include // Ultrasound #include "mitkUSDevice.h" #include "QmitkUSAbstractCustomWidget.h" #include #include #include "usServiceReference.h" #include "internal/org_mitk_gui_qt_ultrasound_Activator.h" const std::string UltrasoundSupport::VIEW_ID = "org.mitk.views.ultrasoundsupport"; void UltrasoundSupport::SetFocus() { } void UltrasoundSupport::CreateQtPartControl( QWidget *parent ) { -m_Timer = new QTimer(this); +//initialize timers +m_UpdateTimer = new QTimer(this); +m_RenderingTimer2d = new QTimer(this); +m_RenderingTimer3d = new QTimer(this); // create GUI widgets from the Qt Designer's .ui file m_Controls.setupUi( parent ); +//load persistence data before connecting slots (so no slots are called in this phase...) +LoadUISettings(); + +//connect signals and slots... connect( m_Controls.m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this, SLOT(OnClickedAddNewDevice()) ); // Change Widget Visibilities connect( m_Controls.m_DeviceManagerWidget, SIGNAL(NewDeviceButtonClicked()), this->m_Controls.m_NewVideoDeviceWidget, SLOT(CreateNewDevice()) ); // Init NewDeviceWidget connect( m_Controls.m_ActiveVideoDevices, SIGNAL(ServiceSelectionChanged(us::ServiceReferenceU)), this, SLOT(OnChangedActiveDevice()) ); connect( m_Controls.m_RunImageTimer, SIGNAL(clicked()), this, SLOT(OnChangedActiveDevice()) ); connect( m_Controls.m_ShowImageStream, SIGNAL(clicked()), this, SLOT(OnChangedActiveDevice()) ); connect( m_Controls.m_NewVideoDeviceWidget, SIGNAL(Finished()), this, SLOT(OnNewDeviceWidgetDone()) ); // After NewDeviceWidget finished editing -connect( m_Controls.m_FrameRate, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit(int)) ); +connect( m_Controls.m_FrameRatePipeline, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit()) ); +connect( m_Controls.m_FrameRate2d, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit()) ); +connect( m_Controls.m_FrameRate3d, SIGNAL(valueChanged(int)), this, SLOT(OnChangedFramerateLimit()) ); connect( m_Controls.m_FreezeButton, SIGNAL(clicked()), this, SLOT(OnClickedFreezeButton()) ); -connect( m_Timer, SIGNAL(timeout()), this, SLOT(DisplayImage())); +connect( m_UpdateTimer, SIGNAL(timeout()), this, SLOT(UpdateImage())); +connect( m_RenderingTimer2d, SIGNAL(timeout()), this, SLOT(RenderImage2d())); +connect( m_RenderingTimer3d, SIGNAL(timeout()), this, SLOT(RenderImage3d())); +connect( m_Controls.m_Update2DView, SIGNAL(clicked()), this, SLOT(StartTimers()) ); +connect( m_Controls.m_Update3DView, SIGNAL(clicked()), this, SLOT(StartTimers()) ); // Initializations m_Controls.m_NewVideoDeviceWidget->setVisible(false); std::string filter = "(&(" + us::ServiceConstants::OBJECTCLASS() + "=" + "org.mitk.services.UltrasoundDevice)(" + mitk::USDevice::GetPropertyKeys().US_PROPKEY_ISACTIVE + "=true))"; m_Controls.m_ActiveVideoDevices->Initialize( mitk::USDevice::GetPropertyKeys().US_PROPKEY_LABEL ,filter); m_Controls.m_ActiveVideoDevices->SetAutomaticallySelectFirstEntry(true); -m_FrameCounter = 0; +m_FrameCounterPipeline = 0; +m_FrameCounter2d = 0; +m_FrameCounter3d = 0; // Create Node for US Stream if (m_Node.IsNull()) { -m_Node = mitk::DataNode::New(); -m_Node->SetName("US Support Viewing Stream"); -//create a dummy image (gray values 0..255) for correct initialization of level window, etc. -mitk::Image::Pointer dummyImage = mitk::ImageGenerator::GenerateRandomImage(100, 100, 1, 1, 1, 1, 1, 255,0); -m_Node->SetData(dummyImage); -m_OldGeometry = dynamic_cast(dummyImage->GetGeometry()); + m_Node = mitk::DataNode::New(); + m_Node->SetName("US Support Viewing Stream"); + //create a dummy image (gray values 0..255) for correct initialization of level window, etc. + mitk::Image::Pointer dummyImage = mitk::ImageGenerator::GenerateRandomImage(100, 100, 1, 1, 1, 1, 1, 255,0); + m_Node->SetData(dummyImage); + m_OldGeometry = dynamic_cast(dummyImage->GetGeometry()); } m_Controls.tabWidget->setTabEnabled(1, false); -LoadUISettings(); } void UltrasoundSupport::OnClickedAddNewDevice() { m_Controls.m_NewVideoDeviceWidget->setVisible(true); m_Controls.m_DeviceManagerWidget->setVisible(false); m_Controls.m_Headline->setText("Add New Video Device:"); m_Controls.m_WidgetActiveDevices->setVisible(false); } -void UltrasoundSupport::DisplayImage() +void UltrasoundSupport::UpdateImage() { //Update device m_Device->Modified(); m_Device->Update(); //Only update the view if the image is shown if(m_Controls.m_ShowImageStream->isChecked()) { //Update data node mitk::Image::Pointer curOutput = m_Device->GetOutput(); m_Node->SetData(curOutput); // if the geometry changed: reinitialize the ultrasound image if((m_OldGeometry.IsNotNull()) && (curOutput->GetGeometry() != NULL) && (!mitk::Equal(m_OldGeometry.GetPointer(),curOutput->GetGeometry(),0.0001,false)) ) { mitk::IRenderWindowPart* renderWindow = this->GetRenderWindowPart(); if ( (renderWindow != NULL) && (curOutput->GetTimeGeometry()->IsValid()) && (m_Controls.m_ShowImageStream->isChecked()) ) { renderWindow->GetRenderingManager()->InitializeViews( curOutput->GetGeometry(), mitk::RenderingManager::REQUEST_UPDATE_ALL, true ); renderWindow->GetRenderingManager()->RequestUpdateAll(); } m_CurrentImageWidth = curOutput->GetDimension(0); m_CurrentImageHeight = curOutput->GetDimension(1); m_OldGeometry = dynamic_cast(curOutput->GetGeometry()); } - //if not: only update the view - else - { - this->RequestRenderWindowUpdate(); - } + } //Update frame counter -m_FrameCounter ++; -if (m_FrameCounter >= 10) +m_FrameCounterPipeline ++; +if (m_FrameCounterPipeline >= 10) { + //compute framerate of pipeline update int nMilliseconds = m_Clock.restart(); int fps = 10000.0f / (nMilliseconds ); - m_Controls.m_FramerateLabel->setText("Current Framerate: "+ QString::number(fps) +" FPS"); - m_FrameCounter = 0; + m_FPSPipeline = fps; + m_FrameCounterPipeline = 0; + + //display lowest framerate in UI + int lowestFPS=m_FPSPipeline; + if (m_Controls.m_Update2DView->isChecked() && (m_FPS2disChecked() && (m_FPS3dsetText("Current Framerate: "+ QString::number(lowestFPS) +" FPS"); } } -void UltrasoundSupport::OnChangedFramerateLimit(int value) +void UltrasoundSupport::RenderImage2d() { -m_Timer->stop(); -m_Timer->setInterval(1000 / value); -m_Timer->start(); +this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_2DWINDOWS); +m_FrameCounter2d ++; +if (m_FrameCounter2d >= 10) + { + //compute framerate of 2d render window update + int nMilliseconds = m_Clock2d.restart(); + int fps = 10000.0f / (nMilliseconds ); + m_FPS2d = fps; + m_FrameCounter2d = 0; + } +} + +void UltrasoundSupport::RenderImage3d() +{ +this->RequestRenderWindowUpdate(mitk::RenderingManager::REQUEST_UPDATE_3DWINDOWS); +m_FrameCounter3d ++; +if (m_FrameCounter3d >= 10) + { + //compute framerate of 2d render window update + int nMilliseconds = m_Clock3d.restart(); + int fps = 10000.0f / (nMilliseconds ); + m_FPS3d = fps; + m_FrameCounter3d = 0; + } +} + +void UltrasoundSupport::OnChangedFramerateLimit() +{ +StopTimers(); +int intervalPipeline = (1000 / m_Controls.m_FrameRatePipeline->value()); +int interval2D = (1000 / m_Controls.m_FrameRate2d->value()); +int interval3D = (1000 / m_Controls.m_FrameRate3d->value()); +SetTimerIntervals(intervalPipeline,interval2D,interval3D); +StartTimers(); } void UltrasoundSupport::OnClickedFreezeButton() { if ( m_Device.IsNull() ) { MITK_WARN("UltrasoundSupport") << "Freeze button clicked though no device is selected."; return; } if ( m_Device->GetIsFreezed() ) { m_Device->SetIsFreezed(false); m_Controls.m_FreezeButton->setText("Freeze"); } else { m_Device->SetIsFreezed(true); m_Controls.m_FreezeButton->setText("Start Viewing Again"); } } void UltrasoundSupport::OnChangedActiveDevice() { //clean up and stop timer -m_Timer->stop(); +StopTimers(); this->RemoveControlWidgets(); this->GetDataStorage()->Remove(m_Node); m_Node->ReleaseData(); //get current device, abort if it is invalid m_Device = m_Controls.m_ActiveVideoDevices->GetSelectedService(); if (m_Device.IsNull()) { m_Controls.tabWidget->setTabEnabled(1, false); return; } //create the widgets for this device and enable the widget tab this->CreateControlWidgets(); m_Controls.tabWidget->setTabEnabled(1, true); //show node if the option is enabled if(m_Controls.m_ShowImageStream->isChecked()) {this->GetDataStorage()->Add(m_Node);} //start timer if(m_Controls.m_RunImageTimer->isChecked()) { - int interval = (1000 / m_Controls.m_FrameRate->value()); - m_Timer->setInterval(interval); - m_Timer->start(); + int intervalPipeline = (1000 / m_Controls.m_FrameRatePipeline->value()); + int interval2D = (1000 / m_Controls.m_FrameRate2d->value()); + int interval3D = (1000 / m_Controls.m_FrameRate3d->value()); + SetTimerIntervals(intervalPipeline,interval2D,interval3D); + StartTimers(); m_Controls.m_TimerWidget->setEnabled(true); } else { m_Controls.m_TimerWidget->setEnabled(false); } } void UltrasoundSupport::OnNewDeviceWidgetDone() { m_Controls.m_NewVideoDeviceWidget->setVisible(false); m_Controls.m_DeviceManagerWidget->setVisible(true); m_Controls.m_Headline->setText("Ultrasound Devices:"); m_Controls.m_WidgetActiveDevices->setVisible(true); } void UltrasoundSupport::CreateControlWidgets() { m_ControlProbesWidget = new QmitkUSControlsProbesWidget(m_Device->GetControlInterfaceProbes(), m_Controls.m_ToolBoxControlWidgets); m_Controls.probesWidgetContainer->addWidget(m_ControlProbesWidget); // create b mode widget for current device m_ControlBModeWidget = new QmitkUSControlsBModeWidget(m_Device->GetControlInterfaceBMode(), m_Controls.m_ToolBoxControlWidgets); m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlBModeWidget, "B Mode Controls"); if ( ! m_Device->GetControlInterfaceBMode() ) {m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count()-1, false);} // create doppler widget for current device m_ControlDopplerWidget = new QmitkUSControlsDopplerWidget(m_Device->GetControlInterfaceDoppler(), m_Controls.m_ToolBoxControlWidgets); m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlDopplerWidget, "Doppler Controls"); if ( ! m_Device->GetControlInterfaceDoppler() ) {m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count()-1, false);} ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if ( pluginContext ) { std::string filter = "(ork.mitk.services.UltrasoundCustomWidget.deviceClass=" + m_Device->GetDeviceClass() + ")"; QString interfaceName = QString::fromStdString(us_service_interface_iid() ); m_CustomWidgetServiceReference = pluginContext->getServiceReferences(interfaceName, QString::fromStdString(filter)); if (m_CustomWidgetServiceReference.size() > 0) { m_ControlCustomWidget = pluginContext->getService (m_CustomWidgetServiceReference.at(0))->CloneForQt(m_Controls.tab2); m_ControlCustomWidget->SetDevice(m_Device); m_Controls.m_ToolBoxControlWidgets->addItem(m_ControlCustomWidget, "Custom Controls"); } else { m_Controls.m_ToolBoxControlWidgets->addItem(new QWidget(m_Controls.m_ToolBoxControlWidgets), "Custom Controls"); m_Controls.m_ToolBoxControlWidgets->setItemEnabled(m_Controls.m_ToolBoxControlWidgets->count()-1, false); } } // select first enabled control widget for ( int n = 0; n < m_Controls.m_ToolBoxControlWidgets->count(); ++n) { if ( m_Controls.m_ToolBoxControlWidgets->isItemEnabled(n) ) { m_Controls.m_ToolBoxControlWidgets->setCurrentIndex(n); break; } } } void UltrasoundSupport::RemoveControlWidgets() { if(!m_ControlProbesWidget) {return;} //widgets do not exist... nothing to do // remove all control widgets from the tool box widget while (m_Controls.m_ToolBoxControlWidgets->count() > 0) { m_Controls.m_ToolBoxControlWidgets->removeItem(0); } // remove probes widget (which is not part of the tool box widget) m_Controls.probesWidgetContainer->removeWidget(m_ControlProbesWidget); delete m_ControlProbesWidget; m_ControlProbesWidget = 0; delete m_ControlBModeWidget; m_ControlBModeWidget = 0; delete m_ControlDopplerWidget; m_ControlDopplerWidget = 0; // delete custom widget if it is present if ( m_ControlCustomWidget ) { ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); delete m_ControlCustomWidget; m_ControlCustomWidget = 0; if ( m_CustomWidgetServiceReference.size() > 0 ) { pluginContext->ungetService(m_CustomWidgetServiceReference.at(0)); } } } void UltrasoundSupport::OnDeciveServiceEvent(const ctkServiceEvent event) { if ( m_Device.IsNull() || event.getType() != us::ServiceEvent::MODIFIED ) { return; } ctkServiceReference service = event.getServiceReference(); if ( m_Device->GetManufacturer() != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_MANUFACTURER)).toString().toStdString() && m_Device->GetName() != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_NAME)).toString().toStdString() ) { return; } -if ( ! m_Device->GetIsActive() && m_Timer->isActive() ) +if ( ! m_Device->GetIsActive() && m_UpdateTimer->isActive() ) { -m_Timer->stop(); +StopTimers(); } if ( m_CurrentDynamicRange != service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DYNAMIC_RANGE)).toDouble() ) { m_CurrentDynamicRange = service.getProperty(QString::fromStdString(mitk::USDevice::GetPropertyKeys().US_PROPKEY_BMODE_DYNAMIC_RANGE)).toDouble(); // update level window for the current dynamic range mitk::LevelWindow levelWindow; m_Node->GetLevelWindow(levelWindow); levelWindow.SetAuto(m_Image, true, true); m_Node->SetLevelWindow(levelWindow); } } UltrasoundSupport::UltrasoundSupport() : m_ControlCustomWidget(0), m_ControlBModeWidget(0), m_ControlProbesWidget(0), m_ImageAlreadySetToNode(false), m_CurrentImageWidth(0), m_CurrentImageHeight(0) { ctkPluginContext* pluginContext = mitk::PluginActivator::GetContext(); if ( pluginContext ) { // to be notified about service event of an USDevice pluginContext->connectServiceListener(this, "OnDeciveServiceEvent", QString::fromStdString("(" + us::ServiceConstants::OBJECTCLASS() + "=" + us_service_interface_iid() + ")")); } } UltrasoundSupport::~UltrasoundSupport() { try { - m_Timer->stop(); + StopTimers(); // Get all active devicesand deactivate them to prevent freeze std::vector devices = this->m_Controls.m_ActiveVideoDevices->GetAllServices(); for (int i = 0; i < devices.size(); i ++) { mitk::USDevice::Pointer device = devices[i]; if (device.IsNotNull() && device->GetIsActive()) { device->Deactivate(); device->Disconnect(); } } StoreUISettings(); } catch(std::exception &e) { MITK_ERROR << "Exception during call of destructor! Message: " << e.what(); } } void UltrasoundSupport::StoreUISettings() { QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); settings.setValue("DisplayImage", QVariant(m_Controls.m_ShowImageStream->isChecked())); settings.setValue("RunImageTimer", QVariant(m_Controls.m_RunImageTimer->isChecked())); + settings.setValue("Update2DView", QVariant(m_Controls.m_Update2DView->isChecked())); + settings.setValue("Update3DView", QVariant(m_Controls.m_Update3DView->isChecked())); + settings.setValue("UpdateRatePipeline", QVariant(m_Controls.m_FrameRatePipeline->value())); + settings.setValue("UpdateRate2d", QVariant(m_Controls.m_FrameRate2d->value())); + settings.setValue("UpdateRate3d", QVariant(m_Controls.m_FrameRate3d->value())); settings.endGroup(); } void UltrasoundSupport::LoadUISettings() { QSettings settings; settings.beginGroup(QString::fromStdString(VIEW_ID)); m_Controls.m_ShowImageStream->setChecked(settings.value("DisplayImage", true).toBool()); m_Controls.m_RunImageTimer->setChecked(settings.value("RunImageTimer", true).toBool()); + m_Controls.m_Update2DView->setChecked(settings.value("Update2DView", true).toBool()); + m_Controls.m_Update3DView->setChecked(settings.value("Update3DView", true).toBool()); + m_Controls.m_FrameRatePipeline->setValue(settings.value("UpdateRatePipeline", 50).toInt()); + m_Controls.m_FrameRate2d->setValue(settings.value("UpdateRate2d", 20).toInt()); + m_Controls.m_FrameRate3d->setValue(settings.value("UpdateRate3d", 5).toInt()); settings.endGroup(); + +} + +void UltrasoundSupport::StartTimers() +{ +m_UpdateTimer->start(); +if (m_Controls.m_Update2DView->isChecked()) {m_RenderingTimer2d->start();} +if (m_Controls.m_Update3DView->isChecked()) {m_RenderingTimer3d->start();} +} + +void UltrasoundSupport::StopTimers() +{ +m_UpdateTimer->stop(); +m_RenderingTimer2d->stop(); +m_RenderingTimer3d->stop(); +} + +void UltrasoundSupport::SetTimerIntervals(int intervalPipeline, int interval2D, int interval3D) +{ +m_UpdateTimer->setInterval(intervalPipeline); +m_RenderingTimer2d->setInterval(interval2D); +m_RenderingTimer3d->setInterval(interval3D); } diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h index 95deec9a01..88133e46bc 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupport.h @@ -1,132 +1,149 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #ifndef UltrasoundSupport_h #define UltrasoundSupport_h #include #include #include "ui_UltrasoundSupportControls.h" #include "QmitkUSAbstractCustomWidget.h" #include "QmitkUSControlsBModeWidget.h" #include "QmitkUSControlsDopplerWidget.h" #include "QmitkUSControlsProbesWidget.h" #include #include /*! \brief UltrasoundSupport This plugin provides functionality to manage Ultrasound devices, create video devices and to view device images. \sa QmitkFunctionality \ingroup ${plugin_target}_internal */ class UltrasoundSupport : public QmitkAbstractView { // this is needed for all Qt objects that should have a Qt meta-object // (everything that derives from QObject and wants to have signal/slots) Q_OBJECT public: virtual void SetFocus() override; static const std::string VIEW_ID; virtual void CreateQtPartControl(QWidget *parent) override; UltrasoundSupport(); virtual ~UltrasoundSupport(); public slots: /* * \brief This is called when the newDeviceWidget is closed */ void OnNewDeviceWidgetDone(); protected slots: void OnClickedAddNewDevice(); - void OnChangedFramerateLimit(int); + void OnChangedFramerateLimit(); /* *\brief Called, when the selection in the list of the active devices changes. */ void OnChangedActiveDevice(); void OnClickedFreezeButton(); void OnDeciveServiceEvent(const ctkServiceEvent event); /* - * \brief This is the main imaging loop that is called regularily during the imaging process + * \brief This is the main imaging loop that updates the image and is called regularily during the imaging process */ - void DisplayImage(); + void UpdateImage(); + + void RenderImage2d(); + + void RenderImage3d(); + + void StartTimers(); + + void StopTimers(); protected: void CreateControlWidgets(); void RemoveControlWidgets(); /** The device that is currently used to aquire images */ mitk::USDevice::Pointer m_Device; + + void SetTimerIntervals(int intervalPipeline, int interval2D, int interval3D); /** This timer triggers periodic updates to the pipeline */ - QTimer* m_Timer; + QTimer* m_UpdateTimer; + QTimer* m_RenderingTimer2d; + QTimer* m_RenderingTimer3d; - /** This clock is used to compute the framerate in the method DisplayImage(). */ + /** These clocks are used to compute the framerate in the methods DisplayImage(),RenderImage2d() and RenderImage3d(). */ QTime m_Clock; + QTime m_Clock2d; + QTime m_Clock3d; /** A counter to comute the framerate. */ - int m_FrameCounter; + int m_FrameCounterPipeline; + int m_FrameCounter2d; + int m_FrameCounter3d; + int m_FPSPipeline, m_FPS2d, m_FPS3d; /** Stores the properties of some QWidgets (and the tool storage file name) to QSettings.*/ void StoreUISettings(); /** Loads the properties of some QWidgets (and the tool storage file name) from QSettings.*/ void LoadUISettings(); /** The node that we feed images into.*/ mitk::DataNode::Pointer m_Node; /** The image that is hold by the node above.*/ mitk::Image::Pointer m_Image; /** The old geometry of m_Image. It is needed to check if the geometry changed (e.g. because * the zoom factor was modified) and the image needs to be reinitialized. */ mitk::SlicedGeometry3D::Pointer m_OldGeometry; Ui::UltrasoundSupportControls m_Controls; QmitkUSAbstractCustomWidget* m_ControlCustomWidget; QmitkUSControlsBModeWidget* m_ControlBModeWidget; QmitkUSControlsDopplerWidget* m_ControlDopplerWidget; QmitkUSControlsProbesWidget* m_ControlProbesWidget; QList m_CustomWidgetServiceReference; bool m_ImageAlreadySetToNode; unsigned int m_CurrentImageWidth; unsigned int m_CurrentImageHeight; double m_CurrentDynamicRange; }; #endif // UltrasoundSupport_h diff --git a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui index af878b2ff7..0043b03043 100644 --- a/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui +++ b/Plugins/org.mitk.gui.qt.ultrasound/src/internal/UltrasoundSupportControls.ui @@ -1,297 +1,391 @@ UltrasoundSupportControls 0 0 - 307 - 355 + 407 + 820 0 0 QmitkTemplate 2 0 true false false :/USUI/ultrasound01-probe-300ppi.png :/USUI/ultrasound01-probe-300ppi.png:/USUI/ultrasound01-probe-300ppi.png Device Management 0 10 75 true Ultrasound Devices: 10 75 true Active Devices: 0 0 - Show Image Stream + Show US image in MITK true Qt::Vertical 20 40 false :/USUI/ultrasound02-scan-300ppi.png :/USUI/ultrasound02-scan-72ppi-deactivated.png :/USUI/ultrasound02-scan-300ppi.png:/USUI/ultrasound02-scan-300ppi.png US Imaging Qt::Vertical 20 40 Qt::Horizontal - Update Image Automatically + Update Image Data Automatically true Freeze :/USUI/system-lock-screen.png:/USUI/system-lock-screen.png <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:7.8pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600;">Framrate Settings:</span></p></body></html> - Current Framerate: 0 FPS + Current overall Framerate: 0 FPS + + + + + + Image Pipeline Framerate Limit [FPS]: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + 500 + + + 50 + + + + + - + - Framerate Limit: + Update 2D View + + + true Qt::Horizontal 40 20 - + + + Framerate Limit [FPS]: + + + + + 1 - 50 + 100 + + + 20 + + + + + + + + + + + Update 3D View + + + true + + + + + + + Qt::Horizontal + + + + 18 + 20 + + + + + + + + Framerate Limit [FPS]: + + + + + + + 1 + + + 100 - 30 + 5 QmitkUSDeviceManagerWidget QWidget
QmitkUSDeviceManagerWidget.h
1
QmitkUSNewVideoDeviceWidget QWidget
QmitkUSNewVideoDeviceWidget.h
1
QmitkServiceListWidget QWidget
QmitkServiceListWidget.h
1