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/mitkNavigationDataSet.cpp b/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp index 57f5c947ae..cb0c13e8e3 100644 --- a/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp +++ b/Modules/IGT/DataManagement/mitkNavigationDataSet.cpp @@ -1,161 +1,161 @@ /*=================================================================== 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 to many or too few navigation Datas to NavigationDataSet. " << m_NavigationDataVectors.size() << " 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 NULL; } if ( toolIndex >= m_NavigationDataVectors.at(index).size() ) { MITK_WARN("NavigationDataSet") << "There is NavigatitionData available at index " << index << " for tool " << toolIndex << "."; return NULL; } 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) { return m_NavigationDataVectors[index]; } unsigned int mitk::NavigationDataSet::GetNumberOfTools() { return m_NumberOfTools; } unsigned int mitk::NavigationDataSet::Size() { 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 * ) { } // <--- methods necessary for BaseData // ---> methods for Iterators mitk::NavigationDataSet::NavigationDataSetIterator mitk::NavigationDataSet::Begin() { return m_NavigationDataVectors.begin(); } mitk::NavigationDataSet::NavigationDataSetIterator mitk::NavigationDataSet::End() { return m_NavigationDataVectors.end(); -} \ No newline at end of file +} 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/mitkOpenIGTLinkTrackingDeviceTest.cpp b/Modules/IGT/Testing/mitkOpenIGTLinkTrackingDeviceTest.cpp new file mode 100644 index 0000000000..9cf52ea47b --- /dev/null +++ b/Modules/IGT/Testing/mitkOpenIGTLinkTrackingDeviceTest.cpp @@ -0,0 +1,84 @@ +/*=================================================================== + +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 + + +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(); + + Sleep(20000); + + 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..1b74c7d343 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.cpp @@ -0,0 +1,329 @@ +/*=================================================================== + +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 + +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); +} + +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"; + //m_OpenIGTLinkClient->SendMessage(msgFactory->CreateInstance(message)); + + 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..9f05bce29c --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingDevice.h @@ -0,0 +1,143 @@ +/*=================================================================== + +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 mitk::OpenIGTLinkTrackingDevice::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 2000 (2 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 = 2000); + + + /** + * \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); + + 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/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.cpp b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.cpp new file mode 100644 index 0000000000..13f9ae4d24 --- /dev/null +++ b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.cpp @@ -0,0 +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 + +mitk::OpenIGTLinkTrackingTool::OpenIGTLinkTrackingTool() :InternalTrackingTool() +{ +} + +mitk::OpenIGTLinkTrackingTool::~OpenIGTLinkTrackingTool(void) +{ +} diff --git a/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.h b/Modules/IGT/TrackingDevices/mitkOpenIGTLinkTrackingTool.h new file mode 100644 index 0000000000..cb965258ed --- /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/files.cmake b/Modules/IGT/files.cmake index aef21bf3f1..0d99f60ab5 100644 --- a/Modules/IGT/files.cmake +++ b/Modules/IGT/files.cmake @@ -1,92 +1,94 @@ 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/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp index e28ee0ee90..9112f4bff8 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.cpp @@ -1,732 +1,743 @@ /*=================================================================== 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 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; + 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); + // 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(); + 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(); + 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(); + 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(); } 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 #else if (m_Controls->m_trackingDeviceChooser->currentIndex()==1) //Aurora prefix = m_Controls->portTypeAurora->currentText(); else //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/QmitkTrackingDeviceConfigurationWidget.h b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.h index c2cf5c37d1..e388918703 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.h +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidget.h @@ -1,273 +1,277 @@ /*=================================================================== 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 QMITKTRACKINGDEVICECONFIGURATIONWIDGET_H #define QMITKTRACKINGDEVICECONFIGURATIONWIDGET_H #include #include #include "MitkIGTUIExports.h" #include "ui_QmitkTrackingDeviceConfigurationWidgetControls.h" #include "mitkTrackingDevice.h" #include class QmitkTrackingDeviceConfigurationWidgetConnectionWorker; class QmitkTrackingDeviceConfigurationWidgetScanPortsWorker; //itk headers /** Documentation: * \brief An object of this class offers an UI to configurate * a tracking device. If the user finished the configuration process and * a fully configurated tracking device is availiabe the object emits a * signal "TrackingDeviceConfigurationFinished()". You can then get the * tracking device by calling the method GetTrackingDevice(). * * Once the tracking device is configurated there are two ways to reset * the UI to allow the user for configuring a new device. The method Reset() * can be called and there is also a button "reset" which can be pressed by * the user. In both cases a signal "TrackingDeviceConfigurationReseted()" * is emitted and you may wait for a new configurated tracking device. * * The possibility to reset the configuration by the user can also be switched * of by calling the method EnableUserReset(boolean enable). * * \ingroup IGTUI */ class MITKIGTUI_EXPORT QmitkTrackingDeviceConfigurationWidget : public QWidget { Q_OBJECT public: static const std::string VIEW_ID; QmitkTrackingDeviceConfigurationWidget(QWidget* parent = 0, Qt::WindowFlags f = 0); ~QmitkTrackingDeviceConfigurationWidget(); /* @return Returns the current configurated tracking device. If the user didn't finished the * configuration process or if there is an error during configuration NULL is returned. */ mitk::TrackingDevice::Pointer GetTrackingDevice(); enum Style { SIMPLE, ADVANCED, }; /* @brief Resets the UI to allow the user for configurating a new tracking device. */ void Reset(); /** @brief External call to disable this widget when configuration is finished. This is also called by the "finished" button, * but if you disable the advanced user control you might want to call this when the configuration is finished. * If you want to configure a new device call the Reset() funktion later. */ void ConfigurationFinished(); /* @brief Sets our unsets the possibility to reset the UI and start * a new configuration by the user. Concretely this means the * button "reset" is shown or not. */ void EnableUserReset(bool enable); /** @return Returns true if the tracking device is completely configured (you can get it by calling GetTrackingDevice() in this case). * Returns false if configuration is not finished. */ bool GetTrackingDeviceConfigured(); + /** @return Returns the frame rate set in the m_frameRatePolaris ComboBox + */ + mitk::IlluminationActivationRate GetPolarisFrameRate(); + /** @brief Sets the style of this widget. Default is ADVANCED. Caution: The style can only be set once at startup! */ void SetGUIStyle(Style style); /** @brief Enables/disables the advanced user controls which means the reset and finished button. When disabled you'll get NO * signals from this widget and you've to check by yourself if the configuration is finished. Default value is false. * Advanced user control is only availiable when style is ADVANCED. */ void EnableAdvancedUserControl(bool enable); signals: /* @brief This signal is sent if the user has finished the configuration of the tracking device. * The device is now availiable if the method GetTrackingDevice() is called. The tracking * device you'll get is completly configurated but no tools are added yet. */ void TrackingDeviceConfigurationFinished(); /* @brief This signal is sent if the UI was reseted and the user is required to configurate * a new tracking device. */ void TrackingDeviceConfigurationReseted(); /* @brief This signal is sent if the tracking device was changed. */ void TrackingDeviceSelectionChanged(); /* @brief This signal is sent if an internal thread (caused by an action of the user) was started. The widget is blocked until the progress ends.*/ void ProgressStarted(); /* @brief This signal is sent if a progress which was started before ends.*/ void ProgressFinished(); protected: /// \brief Creation of the connections virtual void CreateConnections(); virtual void CreateQtPartControl(QWidget *parent); Ui::QmitkTrackingDeviceConfigurationWidgetControls* m_Controls; std::stringstream m_output; mitk::TrackingDevice::Pointer m_TrackingDevice; std::string m_MTCalibrationFile; std::string m_OptitrackCalibrationFile; bool m_TrackingDeviceConfigurated; bool m_AdvancedUserControl; // key is port name (e.g. "COM1", "/dev/ttyS0"), value will be filled with the type of tracking device at this port typedef QMap PortDeviceMap; QmitkTrackingDeviceConfigurationWidgetScanPortsWorker* m_ScanPortsWorker; QmitkTrackingDeviceConfigurationWidgetConnectionWorker* m_TestConnectionWorker; QThread* m_ScanPortsWorkerThread; QThread* m_TestConnectionWorkerThread; //######################### internal help methods ####################################### void ResetOutput(); void AddOutput(std::string s); mitk::TrackingDevice::Pointer ConstructTrackingDevice(); void StoreUISettings(); void LoadUISettings(); protected slots: /* @brief This method is called when the user changes the selection of the trackingdevice (m_trackingDeviceChooser). It then sets the correct widget for the selected tracking device.*/ void TrackingDeviceChanged(); /* @brief This method is called when the user presses the button "test connection". The method will then create a temporary tracking device, * try to open a connection and start tracking. The user can see the result of the connection test on the small output window. */ void TestConnection(); void TestConnectionFinished(bool connected, QString output); /* @brief This method is called when the user presses the button "finished". A new tracking device will be created in this case and will then * then be availiable by calling GetTrackingDevice(). Also a signal TrackingDeviceConfigurationFinished() will be emitted. After this the * UI will be disablet until the widget is reseted to configure a new tracking device. */ void Finished(); /* @brief This method is called when the user presses the button "reset". He can configure a new tracking device then. The signal * TrackingDeviceConfigurationReseted() will be emitted if this method is called. The method GetTrackingDevice() will return * NULL until a new tracking device is configured. */ void ResetByUser(); /* @return Returns a configured NDI 5D tracking device. Unfortunately the NDI 5D tracking device is not yet in the open source part * so this method only returns NULL at the moment. */ virtual mitk::TrackingDevice::Pointer ConfigureNDI5DTrackingDevice(); /* @return Returns a configured NDI 6D tracking device. * The type (which means Aurora/Polaris) will not be set in the returnvalue. You have to this later. */ mitk::TrackingDevice::Pointer ConfigureNDI6DTrackingDevice(); /* @return Returns a configured Optitrack tracking device. * The type (which means Aurora/Polaris/Optitrack) will not be set in the returnvalue. You have to this later. */ mitk::TrackingDevice::Pointer ConfigureOptitrackTrackingDevice(); /* @brief Scans the serial ports automatically for a connected tracking device. If the method finds a device * it selects the right type and sets the corresponding port in the widget. */ void AutoScanPorts(); /** This slot is called when the port scanning is finished. */ void AutoScanPortsFinished(int PolarisPort, int AuroraPort, QString result, int PortTypePolaris, int PortTypeAurora); /* @brief Opens a file dialog. The users sets the calibration file which location is then stored in the member m_MTCalibrationFile.*/ void SetMTCalibrationFileClicked(); /* @brief Opens a file dialog. The users sets the calibration file which location is then stored in the member m_OptitrackCalibrationFile.*/ void SetOptitrackCalibrationFileClicked(); private: PERSISTENCE_GET_SERVICE_METHOD_MACRO }; //################################################################################################### //############ PRIVATE WORKER CLASSES FOR THREADS ################################################### //################################################################################################### /** * Worker thread class for test connection. */ class QmitkTrackingDeviceConfigurationWidgetConnectionWorker : public QObject { Q_OBJECT public: void SetTrackingDevice(mitk::TrackingDevice::Pointer t); public slots: void TestConnectionThreadFunc(); signals: void ConnectionTested(bool connected, QString output); protected: mitk::TrackingDevice::Pointer m_TrackingDevice; }; /** * Worker thread class for scan ports. */ class QmitkTrackingDeviceConfigurationWidgetScanPortsWorker : public QObject { Q_OBJECT public slots: void ScanPortsThreadFunc(); signals: /** * @param PolarisPort Returns the port, returns -1 if no device was found. * @param AuroraPort Returns the port, returns -1 if no device was found. * @param PortTypePolaris Returns the port type (0=usb,1=tty), returns -1 if the port type is not specified, e.g, in case of Windows. * @param PortTypeAurora Returns the port type (0=usb,1=tty), returns -1 if the port type is not specified, e.g, in case of Windows. */ void PortsScanned(int PolarisPort, int AuroraPort, QString result, int PortTypePolaris, int PortTypeAurora); protected: /** @brief Scans the given port for a NDI tracking device. * @return Returns the type of the device if one was found. Returns TrackingSystemInvalid if none was found. */ mitk::TrackingDeviceType ScanPort(QString port); }; #endif diff --git a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui index 23e1731ea1..afec742192 100644 --- a/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui +++ b/Modules/IGTUI/Qmitk/QmitkTrackingDeviceConfigurationWidgetControls.ui @@ -1,1084 +1,1127 @@ QmitkTrackingDeviceConfigurationWidgetControls 0 0 - 390 - 368 + 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 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 - - - false - + - 5D + 6D - false + true - + + + false + - 6D + 5D - true + false Qt::Horizontal 62 20 Qt::Vertical QSizePolicy::Expanding - 158 - 17 + 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:'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> +</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> 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:'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> +</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> 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:'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> +</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> 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:'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> +</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> 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 <!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 - 63 + 64 26 Qt::Vertical 20 269 16777215 0 Qt::Vertical 20 40 diff --git a/Modules/OpenIGTLink/mitkIGTLDevice.cpp b/Modules/OpenIGTLink/mitkIGTLDevice.cpp index 7ef3757487..d7a925a11f 100644 --- a/Modules/OpenIGTLink/mitkIGTLDevice.cpp +++ b/Modules/OpenIGTLink/mitkIGTLDevice.cpp @@ -1,485 +1,486 @@ /*=================================================================== 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 "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(NULL), m_ThreadID(0) { m_StopCommunicationMutex = itk::FastMutexLock::New(); m_StateMutex = itk::FastMutexLock::New(); // m_LatestMessageMutex = itk::FastMutexLock::New(); m_CommunicationFinishedMutex = itk::FastMutexLock::New(); // execution rights are owned by the application thread at the beginning m_CommunicationFinishedMutex->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())) { m_MultiThreader->TerminateThread(m_ThreadID); } m_MultiThreader = NULL; } 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); 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_" ) != NULL || std::strstr( curDevType, "STP_" ) != NULL || std::strstr( curDevType, "RTS_" ) != NULL) { 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()); 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_" ) != NULL ) { 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; else return IGTL_STATUS_UNKNOWN_ERROR; } void mitk::IGTLDevice::RunCommunication() { 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)) { // 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); } // StopCommunication was called, thus the mode should be changed back to Ready now // that the tracking loop has ended. this->SetState(Ready); 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); // 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(); // 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(); //} //std::string mitk::IGTLDevice::GetNextCommandDeviceType() //{ // return this->m_CommandQueue->GetNextMsgDeviceType(); //} ITK_THREAD_RETURN_TYPE mitk::IGTLDevice::ThreadStartCommunication(void* pInfoStruct) { /* extract this pointer from Thread Info structure */ struct itk::MultiThreader::ThreadInfoStruct * pInfo = (struct itk::MultiThreader::ThreadInfoStruct*)pInfoStruct; if (pInfo == NULL) { return ITK_THREAD_RETURN_VALUE; } if (pInfo->UserData == NULL) { return ITK_THREAD_RETURN_VALUE; } IGTLDevice *igtlDevice = (IGTLDevice*)pInfo->UserData; if (igtlDevice != NULL) { igtlDevice->RunCommunication(); } igtlDevice->m_ThreadID = 0; // erase thread id because thread will end. return ITK_THREAD_RETURN_VALUE; } diff --git a/Plugins/org.mitk.gui.qt.igttracking/resources/iconNavigationToolManager.xpm b/Plugins/org.mitk.gui.qt.igttracking/resources/iconNavigationToolManager.xpm index 9098156a9c..c7c1164cb5 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/resources/iconNavigationToolManager.xpm +++ b/Plugins/org.mitk.gui.qt.igttracking/resources/iconNavigationToolManager.xpm @@ -1,840 +1,999 @@ /* XPM */ -static char * icon_xpm[] = { -"100 100 737 2", +static char * iconNavigationToolManager_xpm[] = { +"100 100 896 2", " c None", -". c #FFFFFF", -"+ c #FEFEFE", -"@ c #FBFBFB", -"# c #FAFAFA", -"$ c #F1F1F1", -"% c #C3C3C3", -"& c #A1A1A1", -"* c #737373", -"= c #6A6A6A", -"- c #898989", -"; c #B5B5B5", -"> c #F3F3F3", -", c #C6C6C6", -"' c #585858", -") c #0E0E0E", -"! c #050505", -"~ c #000000", -"{ c #111111", -"] c #616161", -"^ c #7C7C7C", -"/ c #A4A4A4", -"( c #EBEBEB", -"_ c #B4B4B4", -": c #3D3D3D", -"< c #383838", -"[ c #E7E7E7", -"} c #D4D4D4", -"| c #8C8C8C", -"1 c #7B7B7B", -"2 c #9A9A9A", -"3 c #E3E3E3", -"4 c #B1B1B1", -"5 c #313131", -"6 c #F8F8F8", -"7 c #E0E0E0", -"8 c #969696", -"9 c #7A7A7A", -"0 c #909090", -"a c #D8D8D8", -"b c #434343", -"c c #030303", -"d c #8F8F8F", -"e c #E8E8E8", -"f c #888888", -"g c #CCCCCC", -"h c #FDFDFD", -"i c #A6A6A6", -"j c #404040", -"k c #1E1E1E", -"l c #0F0F0F", -"m c #BDBDBD", -"n c #F0F0F0", -"o c #ACACAC", -"p c #6C6C6C", -"q c #878787", -"r c #F6F6F6", -"s c #F9F9F9", -"t c #727272", -"u c #BBBBBB", -"v c #BABABA", -"w c #565656", -"x c #060606", -"y c #252525", -"z c #DEDEDE", -"A c #2D2D2D", -"B c #6F6F6F", -"C c #686868", -"D c #EFEFEF", -"E c #E9E9E9", -"F c #8E8E8E", -"G c #2A2A2A", -"H c #4B4B4B", -"I c #F4F4F4", -"J c #0C0C0C", -"K c #020202", -"L c #999999", -"M c #777777", -"N c #C7C7C7", -"O c #626262", -"P c #454545", -"Q c #8B8B8B", -"R c #979797", -"S c #7D7D7D", -"T c #040404", -"U c #757575", -"V c #FCFCFC", -"W c #9B9B9B", -"X c #989898", -"Y c #CBCBCB", -"Z c #212121", -"` c #CDCDCD", -" . c #343434", -".. c #E6E6E6", -"+. c #A5A5A5", -"@. c #353535", -"#. c #7E7E7E", -"$. c #171717", -"%. c #CECECE", -"&. c #CACACA", -"*. c #D1D1D1", -"=. c #C5C5C5", -"-. c #242424", -";. c #090909", -">. c #B7B7B7", -",. c #393939", -"'. c #9D9D9D", -"). c #F5F5F5", -"!. c #6D6D6D", -"~. c #B2B2B2", -"{. c #929292", -"]. c #181818", -"^. c #5A5A5A", -"/. c #1F1F1F", -"(. c #0D0D0D", -"_. c #D7D7D7", -":. c #080808", -"<. c #828282", -"[. c #1C1C1C", -"}. c #F8F9FA", -"|. c #E5EAEF", -"1. c #DCE2EA", -"2. c #DEE4EB", -"3. c #ECEFF4", -"4. c #ADADAD", -"5. c #717171", -"6. c #131313", -"7. c #3A3A3A", -"8. c #F2F4F7", -"9. c #B9C5D4", -"0. c #9CABBE", -"a. c #8F9EB1", -"b. c #92A0B0", -"c. c #909EB0", -"d. c #91A0B4", -"e. c #A5B3C5", -"f. c #CCD5E1", -"g. c #EEEEEE", -"h. c #070707", -"i. c #AAAAAA", -"j. c #484848", -"k. c #010101", -"l. c #787878", -"m. c #D9E0E8", -"n. c #A5B2C2", -"o. c #95A1AF", -"p. c #B7B9BB", -"q. c #BEBEBE", -"r. c #BDBDBE", -"s. c #ACB1B7", -"t. c #94A1B2", -"u. c #AFBDCD", -"v. c #FAFAFB", -"w. c #141414", -"x. c #4D4D4D", -"y. c #EAEAEA", -"z. c #414141", -"A. c #D0D0D0", -"B. c #DDE3EA", -"C. c #A2AFBF", -"D. c #A8AEB5", -"E. c #BFBFBF", -"F. c #929EAD", -"G. c #AFBBCB", -"H. c #FDFEFE", -"I. c #D2D2D2", -"J. c #818181", -"K. c #2C2D2F", -"L. c #000001", -"M. c #121212", -"N. c #B0B0B0", -"O. c #EDEDED", -"P. c #9F9F9F", -"Q. c #F7F9FA", -"R. c #A7B4C4", -"S. c #A6ACB5", -"T. c #93A0AF", -"U. c #BAC6D5", -"V. c #8CA3BF", -"W. c #294669", -"X. c #262D35", -"Y. c #656565", -"Z. c #DFDFDF", -"`. c #6E6E6E", -" + c #F2F2F2", -".+ c #C2CDDA", -"++ c #95A1B0", -"@+ c #BBBCBD", -"#+ c #9EABBC", -"$+ c #EEF1F5", -"%+ c #ECF1F7", -"&+ c #7099C9", -"*+ c #5585BF", -"=+ c #BAC7D6", -"-+ c #535353", -";+ c #E1E1E1", -">+ c #ABABAB", -",+ c #797979", -"'+ c #FCFCFD", -")+ c #A4B2C3", -"!+ c #B4B7BA", -"~+ c #99A4B1", -"{+ c #C6D0DC", -"]+ c #BBCEE5", -"^+ c #4D80BC", -"/+ c #81A5CF", -"(+ c #F6F9FB", -"_+ c #AFAFAF", -":+ c #8D8D8D", -"<+ c #C0C0C0", -"[+ c #ECF0F4", -"}+ c #97A5B6", -"|+ c #AEB2B8", -"1+ c #ADBACB", -"2+ c #F8FAFC", -"3+ c #86A8D1", -"4+ c #4C80BC", -"5+ c #B6CBE3", -"6+ c #CFCFCF", -"7+ c #DADADA", -"8+ c #E1E6ED", -"9+ c #98A4B3", -"0+ c #B8BABC", -"a+ c #A1AFC1", -"b+ c #D0DDED", -"c+ c #5787C0", -"d+ c #6C96C7", -"e+ c #E9EFF6", -"f+ c #B9BBBC", -"g+ c #9FAEC0", -"h+ c #FBFCFD", -"i+ c #9BB8D9", -"j+ c #4A7EBB", -"k+ c #A1BBDB", -"l+ c #E6EAF0", -"m+ c #95A3B3", -"n+ c #A7B5C6", -"o+ c #FDFDFE", -"p+ c #E5ECF5", -"q+ c #6793C6", -"r+ c #5A89C1", -"s+ c #D5E1EF", -"t+ c #F6F7F9", -"u+ c #9CABBC", -"v+ c #A3ABB4", -"w+ c #B9C5D3", -"x+ c #ECECEC", -"y+ c #B1C7E1", -"z+ c #4B7FBB", -"A+ c #8AACD3", -"B+ c #FAFBFD", -"C+ c #B2BFCF", -"D+ c #A1A9B3", -"E+ c #DBE1E9", -"F+ c #9C9C9C", -"G+ c #696969", -"H+ c #F3F7FA", -"I+ c #7CA2CD", -"J+ c #4F82BD", -"K+ c #C0D2E7", -"L+ c #DEE4EC", -"M+ c #8C9EB3", -"N+ c #BCBCBD", -"O+ c #ABB8C9", -"P+ c #C8C8C8", -"Q+ c #C3D3E5", -"R+ c #5284BE", -"S+ c #759CCB", -"T+ c #EFF4F9", -"U+ c #F5F8FB", -"V+ c #A0BBDB", -"W+ c #4976AB", -"X+ c #8597AC", -"Y+ c #A2AFBE", -"Z+ c #E3E8EE", -"`+ c #575757", -" @ c #767676", -".@ c #161616", -"+@ c #364250", -"@@ c #335680", -"#@ c #9EB6D2", -"$@ c #EDF2F8", -"%@ c #97B5D8", -"&@ c #89A2C1", -"*@ c #96A3B3", -"=@ c #A1AEBE", -"-@ c #D2DAE4", -";@ c #C9C9C9", -">@ c #C4C4C4", -",@ c #222222", -"'@ c #030609", -")@ c #494B4D", -"!@ c #E4ECF5", -"~@ c #8EAED4", -"{@ c #638FC4", -"]@ c #B9CDE4", -"^@ c #C4CEDB", -"/@ c #9FADBF", -"(@ c #93A0B0", -"_@ c #A4ABB4", -":@ c #ABB0B7", -"<@ c #9CA5B1", -"[@ c #93A1B2", -"}@ c #AAB8C8", -"|@ c #E2E7EE", -"1@ c #666666", -"2@ c #F7F7F7", -"3@ c #636363", -"4@ c #838383", -"5@ c #DBDBDB", -"6@ c #DCE5F1", -"7@ c #85A8D1", -"8@ c #C2D3E7", -"9@ c #F4F6F9", -"0@ c #CFD8E2", -"a@ c #B5C2D1", -"b@ c #ABB9CA", -"c@ c #AEBCCC", -"d@ c #BEC9D7", -"e@ c #707070", -"f@ c #B8B8B8", -"g@ c #808080", -"h@ c #D3DFEE", -"i@ c #7DA2CE", -"j@ c #749CCA", -"k@ c #CAD9EB", -"l@ c #4E4E4E", -"m@ c #545454", -"n@ c #868686", -"o@ c #B3B3B3", -"p@ c #D3E0EE", -"q@ c #5C5C5C", -"r@ c #BCBCBC", -"s@ c #9E9E9E", -"t@ c #E4E4E4", -"u@ c #C1D3E7", -"v@ c #6B95C7", -"w@ c #86A9D1", -"x@ c #DCE6F1", -"y@ c #C2C2C2", -"z@ c #939393", -"A@ c #628FC4", -"B@ c #D5D5D5", -"C@ c #0B0B0B", -"D@ c #4F4F4F", -"E@ c #F0F3F6", -"F@ c #EAEEF2", -"G@ c #FAFBFC", -"H@ c #B0C6E1", -"I@ c #5A89C0", -"J@ c #7F7F7F", -"K@ c #959595", -"L@ c #747474", -"M@ c #BDC8D6", -"N@ c #9EAEC0", -"O@ c #90A0B4", -"P@ c #8F9EB2", -"Q@ c #8F9FB3", -"R@ c #9CACBF", -"S@ c #A7C0DD", -"T@ c #5283BE", -"U@ c #858585", -"V@ c #5B5B5B", -"W@ c #202020", -"X@ c #848484", -"Y@ c #8A8A8A", -"Z@ c #A3B0C1", -"`@ c #B3B6BA", -" # c #BCBDBE", -".# c #97A2B0", -"+# c #A0AEBE", -"@# c #C9D3DF", -"## c #F4F7FA", -"$# c #9EBADA", -"%# c #4C7FBB", -"&# c #5385BE", -"*# c #A9C1DE", -"=# c #B6B6B6", -"-# c #555555", -";# c #CED7E2", -"># c #9EABBB", -",# c #ADB2B7", -"'# c #B2B5B9", -")# c #97A6B7", -"!# c #799AC0", -"~# c #5B8AC1", -"{# c #B2C8E2", -"]# c #AEAEAE", -"^# c #A3B0C0", -"/# c #B0B4B9", -"(# c #B6B8BB", -"_# c #708BAA", -":# c #608ABC", -"<# c #BACEE5", -"[# c #A8A8A8", -"}# c #919191", -"|# c #191919", -"1# c #D3D3D3", -"2# c #B2BFCE", -"3# c #9DA6B1", -"4# c #A3AAB3", -"5# c #95A9C2", -"6# c #F0F2F6", -"7# c #9AA8B9", -"8# c #98A5B6", -"9# c #E8ECF1", -"0# c #E2E2E2", -"a# c #5D5D5D", -"b# c #C1C1C1", -"c# c #D6DDE6", -"d# c #98A4B2", -"e# c #9AA5B2", -"f# c #CDD6E0", -"g# c #232323", -"h# c #494949", -"i# c #C7D1DC", -"j# c #A7AEB6", -"k# c #BFCAD7", -"l# c #EBEBE8", -"m# c #282828", -"n# c #C2CDD9", -"o# c #A5ACB5", -"p# c #BCC7D4", -"q# c #BCBAB0", -"r# c #9D9C89", -"s# c #F8F7F6", -"t# c #B3B3B4", -"u# c #505D6C", -"v# c #676D73", -"w# c #151515", -"x# c #949494", -"y# c #C9D2DE", -"z# c #A0A9B4", -"A# c #A6ADB5", -"B# c #C2CCD9", -"C# c #EAE9E6", -"D# c #A3A888", -"E# c #959E72", -"F# c #C6C5BB", -"G# c #D7E2EF", -"H# c #5A88BE", -"I# c #4F7199", -"J# c #73787D", -"K# c #DBE2E9", -"L# c #96A3B2", -"M# c #98A3B1", -"N# c #B4B4A4", -"O# c #A3AF7D", -"P# c #B8C991", -"Q# c #A7AA90", -"R# c #F6F6F5", -"S# c #DDDDDD", -"T# c #A2BCDB", -"U# c #9AB7D8", -"V# c #D6D6D6", -"W# c #363636", -"X# c #F5F7F9", -"Y# c #B9BABC", -"Z# c #9CAABB", -"`# c #EFF2F6", -" $ c #D6D5CF", -".$ c #9DA47E", -"+$ c #C2D59A", -"@$ c #C3D69B", -"#$ c #9AA477", -"$$ c #6F6E64", -"%$ c #A3A3A3", -"&$ c #6D97C8", -"*$ c #5686BF", -"=$ c #CFDCEC", -"-$ c #4A4A4A", -";$ c #4C4C4C", -">$ c #BBC7D5", -",$ c #939FAE", -"'$ c #97A2AF", -")$ c #B5C1D1", -"!$ c #FBFBFA", -"~$ c #ACAE97", -"{$ c #AFBE88", -"]$ c #B9CA91", -"^$ c #878A6F", -"/$ c #EDEDEC", -"($ c #DCDCDC", -"_$ c #B8CCE4", -":$ c #84A7D0", -"<$ c #F7F9FC", -"[$ c #DDE6F1", -"}$ c #7A95B5", -"|$ c #9FA8B2", -"1$ c #A5ACB4", -"2$ c #F3F5F8", -"3$ c #C5C3BA", -"4$ c #9AA377", -"5$ c #9BA577", -"6$ c #C3C2B8", -"7$ c #F7F9FB", -"8$ c #83A6D0", -"9$ c #D8E3F0", -"0$ c #82A6D0", -"a$ c #4779B4", -"b$ c #728EB0", -"c$ c #99A3B0", -"d$ c #A3B1C1", -"e$ c #F0EFED", -"f$ c #A6AA8D", -"g$ c #BACC93", -"h$ c #B9CB92", -"i$ c #A6AA8E", -"j$ c #F5F5F3", -"k$ c #CDDBEC", -"l$ c #5586BF", -"m$ c #6E98C8", -"n$ c #EAF0F7", -"o$ c #CFDDED", -"p$ c #79A0CC", -"q$ c #789ECC", -"r$ c #C3D2E4", -"s$ c #ADBBCB", -"t$ c #94A2B3", -"u$ c #A0A8B3", -"v$ c #A2AAB3", -"w$ c #E7EBF0", -"x$ c #B7B7A8", -"y$ c #9EAA79", -"z$ c #9BA678", -"A$ c #C2C0B6", -"B$ c #98B6D8", -"C$ c #A3BDDC", -"D$ c #C7D7E9", -"E$ c #7199C9", -"F$ c #80A4CF", -"G$ c #D6E2EF", -"H$ c #A1B0C3", -"I$ c #99A9BD", -"J$ c #9FAFC2", -"K$ c #B3C0D0", -"L$ c #D7DEE7", -"M$ c #C9CED0", -"N$ c #9DA481", -"O$ c #C1D399", -"P$ c #A5A98D", -"Q$ c #F4F4F2", -"R$ c #E2EAF4", -"S$ c #6491C5", -"T$ c #5C8BC1", -"U$ c #BED0E6", -"V$ c #6893C6", -"W$ c #89ABD2", -"X$ c #DFE8F3", -"Y$ c #FCFDFD", -"Z$ c #F0F4F9", -"`$ c #A9C1DD", -" % c #748686", -".% c #A7B480", -"+% c #BED197", -"@% c #BCCE95", -"#% c #B5C58E", -"$% c #B1C18B", -"%% c #AEBD87", -"&% c #AAB884", -"*% c #838961", -"=% c #C7C6BD", -"-% c #AEC5E0", -";% c #4B7EBB", -">% c #8DADD4", -",% c #B5CAE3", -"'% c #5F8DC3", -")% c #92B1D5", -"!% c #E7EEF6", -"~% c #4B75A3", -"{% c #5A655D", -"]% c #919677", -"^% c #95987B", -"/% c #989A7F", -"(% c #9B9D84", -"_% c #9FA089", -":% c #A3A48F", -"<% c #A8A895", -"[% c #AEAD9D", -"}% c #B4B3A5", -"|% c #BBBBAE", -"1% c #E0DFDB", -"2% c #F2F5FA", -"3% c #5082BD", -"4% c #C2D3E8", -"5% c #FCFDFE", -"6% c #ACC4E0", -"7% c #5687BF", -"8% c #9AB7D9", -"9% c #F1F5F9", -"0% c #EFF3F9", -"a% c #A8C1DE", -"b% c #608DC3", -"c% c #6C95C7", -"d% c #B4C4D4", -"e% c #EFEFEE", -"f% c #F5F4F3", -"g% c #F8F8F7", -"h% c #FAFAF9", -"i% c #FEFEFD", -"j% c #C4D5E8", -"k% c #5183BD", -"l% c #779ECC", -"m% c #4F81BD", -"n% c #A3BEDC", -"o% c #CBDAEB", -"p% c #83A7D0", -"q% c #4F81BC", -"r% c #90B0D5", -"s% c #8FAFD4", -"t% c #ACC4DF", -"u% c #9BB7D9", -"v% c #EEF3F8", -"w% c #5F8CC2", -"x% c #DAE4F0", -"y% c #5D8CC2", -"z% c #E0E9F3", -"A% c #E8EEF6", -"B% c #92B1D6", -"C% c #91B1D5", -"D% c #DAE4F1", -"E% c #A5BFDD", -"F% c #96B4D7", -"G% c #A6BFDD", -"H% c #5E8CC2", -"I% c #5485BF", -"J% c #C6D6E9", -"K% c #C9D8EA", -"L% c #DBE5F1", -"M% c #4E80BC", -"N% c #80A5CF", -"O% c #CEDCEC", -"P% c #799FCC", -"Q% c #ECF1F8", -"R% c #A5BEDD", -"S% c #5D8BC2", -"T% c #6F98C8", -"U% c #B7CCE4", -"V% c #F9FBFC", -"W% c #C5D5E9", -"X% c #82A6CF", -"Y% c #C8D8EA", -"Z% c #93B2D6", -"`% c #D1DEED", -" & c #BCCFE5", -".& c #6692C5", -"+& c #8BACD3", -"@& c #EBF1F7", -"#& c #9CB8D9", -"$& c #9FBBDB", -"%& c #B3C9E2", -"&& c #C7D7EA", -"*& c #7FA4CE", -"=& c #95B3D7", -"-& c #DDE6F2", -";& c #ABC3DF", -">& c #A2BDDC", -",& c #719AC9", -"'& c #8AABD2", -")& c #A2BCDC", -"!& c #F9FAFC", -"~& c #7EA3CE", -"{& c #DEE7F2", -"]& c #BFD1E6", -"^& c #99B6D8", -"/& c #5888C0", -"(& c #ADC5E0", -"_& c #A1BCDB", -":& c #729BCA", -"<& c #C8D7EA", -"[& c #5384BE", -"}& c #EFF3F8", -"|& c #E7EDF5", -"1& c #B7CBE3", -"2& c #97B5D7", -"3& c #DDE7F2", -"4& c #88AAD2", -"5& c #6994C6", -"6& c #5989C0", -"7& c #749BCA", -"8& c #608EC3", -"9& c #7FA3CE", -"0& c #729AC9", -"a& c #7CA1CD", -"b& c #98B5D8", -"c& c #CCDAEB", -"d& c #769DCB", -"e& c #7BA0CD", -"f& c #E7EEF5", -"g& c #9FBADA", -"h& c #BDD0E6", -"i& c #739BCA", -"j& c #C3D4E8", -"k& c #D9E4F0", -"l& c #5485BE", -"m& c #E1EAF3", -"n& c #BED1E6", -"o& c #4E81BC", -"p& c #6491C4", -"q& c #8CADD3", -"r& c #E6EDF5", -"s& c #759DCB", -"t& c #B2C8E1", -"u& c #5C8AC1", -"v& c #7AA0CC", -"w& c #E3EBF4", -"x& c #D4E0EE", -"y& c #E5EDF5", -"z& c #9EB9DA", -"A& c #F3F6FA", -"B& c #9DB9DA", -"C& c #779ECB", -"D& c #789FCC", -"E& c #E4EBF4", -"F& c #EEF2F8", -"G& c #5988C0", -"H& c #AFC6E1", -"I& c #E4ECF4", -"J& c #ADC4E0", -"K& c #6A95C7", -"L& c #C1D2E7", -"M& c #F9FBFD", -"N& c #F6F8FB", -"O& c #C2D4E8", -"P& c #CAD9EA", -"Q& c #5787BF", -"R& c #7AA0CD", -"S& c #E1E9F3", -"T& c #7BA1CD", -"U& c #E0E8F3", -"V& c #BBCFE5", -"W& c #DFE8F2", -"X& c #97B4D7", -"Y& c #729ACA", -"Z& c #95B4D7", -"`& c #94B3D6", -" * c #5182BD", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . + + @ # + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . + . $ % & * = - ; > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . + , ' ) ! ~ ~ { ] ^ / ( + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . + _ : ~ ~ ~ ~ ~ < [ } | 1 2 3 + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . + 4 5 ~ ~ ~ ~ ~ ~ ] 6 + + 7 8 9 0 a + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . 3 b ~ ~ ~ ~ ~ ~ c d + . . . + e & 1 f g h . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . + i j k ~ ~ ~ ~ ~ l m + . . . . . + n o p q r . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . s t u v w x ~ ~ ~ y z . . . . . . . . + g A B ( . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . } C D + E F G ~ ~ H I . . . . . . . + + & J K q + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . + L M h . + h N O J M + . . . . . . . + [ P ~ ~ A g + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . + Q 0 + . . + + I R S r . . . . . . . + d T ~ ~ ~ U V . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . + W X + . . . + . Y Z C ` + + . . . + a < ~ ~ ~ ~ ...+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . + +.^ + + . . . + 2 K ~ @.2 s + . . + #.~ ~ ~ ~ ~ $.%.+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . &.B @ . . . . h = ~ ~ ~ J p *.+ + =.-.~ ~ ~ ~ ~ ;.>.+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . n M z + . . . ( ,.~ ~ ~ ~ ~ < '.).!.~ ~ ~ ~ ~ ~ x ~.+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . + R {.+ . . + ` ].~ ~ ~ ~ ~ ~ { ^./.~ ~ ~ ~ ~ ~ (.% + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . 3 1 _.. . + +.:.~ ~ ~ ~ ~ ~ K <.2 ,.~ ~ ~ ~ ~ [._.+ . . . . . . . . . . . . . . . . . . . . . . . . . }.|.1.2.3.h . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . + 4.- [ . @ 5.~ ~ ~ ~ ~ ~ ~ ,.z + } 5.6.~ ~ ~ 7.( . . . . . . . . . . . . . . . . . . . . . . . . 8.9.0.a.b.c.d.e.f.+ . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . + {.1 N g.b ~ ~ ~ ~ ~ ~ h.8 + + . @ i.j.k.~ l.h . . . . . . . . . . . . . . . . . . . . . . . m.n.o.p.q.q.q.r.s.t.u.v.. . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . h =.L S w.~ ~ ~ ~ ~ ~ x.y.. . . . + 7 S z.A.. . . . . . . . . . . . . . . . . . . . . . . B.C.D.E.E.E.E.E.E.E.q.F.G.H.. . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . h I.J.K.L.~ ~ ~ M.N.. . . . . + O.<.P.+ . . . . . . . . . . . . . . . . . . . . . . Q.R.S.E.E.E.E.E.E.E.E.E.E.T.U.+ . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + V.W.X.T ~ Y.).. . + + . Z.= `. ++ . . . . . . . . . . . . . . . . . . . . . . .+++E.E.E.E.E.E.E.E.E.E.E.@+#+$+. . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . %+&+*+=+W -+<.[ s + V ;+>+p ,+E + + . . . . . . . . . . . . . . . . . . . . . '+)+!+E.E.E.E.E.E.E.E.E.E.E.E.~+{+. . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ]+^+/+(+. D _+| B :+l.^.1 <+# + . . . . . . . . . . . . . . . . . . . . . . . [+}+q.E.E.E.E.E.E.E.E.E.E.E.E.|+1++ . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2+3+4+5+. . . . ).%.6+=.7+@ + + . . . . . . . . . . . . . . . . . . . . . . . . 8+9+E.E.E.E.E.E.E.E.E.E.E.E.E.0+a+'+. . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . b+c+d+e+. . . . . . . + + + . . . . . . . . . . . . . . . . . . . . . . . . . . 2.9+E.E.E.E.E.E.E.E.E.E.E.E.E.f+g+h+. . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . + i+j+k++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . l+m+E.E.E.E.E.E.E.E.E.E.E.E.E.!+n+o+. . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . + . . . . . . . . p+q+r+s+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . t+u+@+E.E.E.E.E.E.E.E.E.E.E.E.v+w+. . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . + + I e x+..+ . . . . y+z+A+B+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + C+D+E.E.E.E.E.E.E.E.E.E.E.q.m+E+. . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . + + [ F+Y.G+S `.2 A.h . H+I+J+K+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . L+M+N+E.E.E.E.E.E.E.E.E.E.D+O+o+. . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . + V & `.J.q.D r e P+- * <+Q+R+S+T+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . U+V+W+X+q.E.E.E.E.E.E.E.E.s.Y+Z+. . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . + h d `+v + + + . + V @k..@+@@@#@+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . $@%@j+r+&@*@!+q.E.E.E.E.q.D+=@-@. . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . + >.5.;@+ . . . . . >@,@~ ~ ~ '@)@P.[ + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . !@~@j+{@]@+ ^@/@(@_@s.:@<@[@}@|@. . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . O.1@0 2@. . . . . 2@3@~ ~ ~ ~ ~ ~ { 4@/ 5@+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6@7@j+d+8@+ . . 9@0@a@b@c@d@2.o+. . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . + R T 6.e@I.+ . + + 4.6.~ ~ ~ ~ ~ ~ < ;+f@g@'.+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . h@i@j+j@k@. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . > l@~ ~ k.@.X $ + $ m@~ ~ ~ ~ ~ ~ ~ 3@s . 5@n@o@+ . . . . . . . . . . . . . . . . . . . . . . . . . . . k@j@j+i@p@. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . + 3 G ~ ~ ~ ~ h.q@r@s@:.~ ~ ~ ~ ~ ~ T 8 + . . I.S t@. . . . . . . . . . . . . . . . . . . . . . . . . + u@v@j+w@x@. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . *.$.~ ~ ~ ~ ~ ~ ,@m@c ~ ~ ~ ~ ~ ~ ) y@+ . . + z@R + . . . . . . . . . . . . . . . . . . . . . . . + ]@A@j+~@p+. . . . . . . . . . . . . . . . . . . . . . . . . $ B@+ . . . . . ", -". . . . . . . . . . . . E.C@~ ~ ~ ~ ~ ~ D@5@J./.~ ~ ~ ~ ~ G t@+ . . + Z.M g.. . . . . . . . . . . . h+E@F@$+G@. . . . . + H@I@j+%@$@. . . . . . . . . . . . . . . . . . . . . . . . . D J@3@K@+ . . . . ", -". . . . . . . . . . . . q.J ~ ~ ~ ~ ~ (.i + V >.m@K ~ ~ ~ `+s . . . . h L@y@. . . . . . . . . . 8.M@N@O@P@Q@R@9.$+. . B+S@T@^+V+U+. . . . . . . . . . . . . . . . . . . . V h . . . . y@Q O.U@Q h . . . ", -". . . . . . . . . . . + 6+$.~ ~ ~ ~ ~ V@).+ . + ( U@W@~ ~ X@h . . . + + Y@2 + . . . . . . . . -@Z@o.`@ #q. #!+.#+#@###$#%#&#*#h+. . . . . . . . . . . . . . . . . . . . ;@f q &.. . # J@~.. n e@[ . . . ", -". . . . . . . . . . . + E @.~ ~ ~ ~ ].=#+ . . + + h f@-#M.; . . . . . + +.Q + . . . . . . . ;#>#,#E.E.E.E.E.E.E.'#)#!#j+~#{#+ . . . . . . . . . . . . . . . . . . . . 7+S ]#N.M ~.m g@J@6 . > 9 n . . . ", -". . . . . . . . . . . + V `.~ ~ ~ ~ = 6 + . . . . . . y.g@W # + + . . + / S + . . . . . . F@^#/#E.E.E.E.E.E.E.E.E.(#_#:#<#+ . . . . . . . . . . . . . . . . . . . . . =#'.. + o Y@d [#> . . +9 n . . . ", -". . . . . . . . . . . . + q.Z ~ ~ Z , + . . . . . . . + }#|#e@1#+ + . + :+U@+ . . . . . + 2#3#E.E.E.E.E.E.E.E.E.E.E.4#5#+ . . . . . . . . . . . . . . . . . . . . . . ; 0 . . + + + . . . . V Q W + . . ", -". . . . . . . . . . . . . h 1 ~ ~ ,+@ + . . . . . . . s 1@~ ~ @.X D + s e@E.. . . . . . 6#7# #E.E.E.E.E.E.E.E.E.E.E.q.8#9#. . . . . . . . . . . . . . . . . . . . . . t@J@).. . . . . . . . . e X@- 0#. ", -". . . . . . . . . . . . . . 5@' |#% + . . . . . . . . x+: ~ ~ ~ C@a#b#1#G+n . . . . . . c#d#E.E.E.E.E.E.E.E.E.E.E.E.E.e#f#. . . . . . . . . . . . . . . . . . . . . . I 9 g.. . . . . . . . . . r L 1 R ", -". . . . . . . . . . . . . . + 7 p e@g V . . . . . . + _.W@~ ~ ~ ~ ~ g#h#:++ . . . . . . i#v+E.E.E.E.E.E.E.E.E.E.E.E.E.j#k#. . . . . . . . . . . . h l#. . . . . . . . 2@l.( . . . . . . . . . . . + 7 R ", -". . . . . . . . . . . . . . . . > / ,+g@E.6 . . . . + 4 ;.~ ~ ~ ~ ~ ~ m#` . . . . . . . n#o#E.E.E.E.E.E.E.E.E.E.E.E.E.:@p#. . . . . . . . . . . . q#r#s#. . . . . . . 7 J.r . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . ).t#u#v#]#n + + h X@~ ~ ~ ~ ~ ~ w#x#+ . . . . . . . y#z#E.E.E.E.E.E.E.E.E.E.E.E.E.A#B#. . . . . . . . . . . C#D#E#F#. . @ $ h . . / '.. . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . G#H#I#J#M P...6 w ~ ~ ~ ~ ~ k x#@ . . . . . . . . K#L#q.E.E.E.E.E.E.E.E.E.E.E.E.M#-@. . . . . . . . . . + N#O#P#Q#R#_ S !.- S#6 g@B@. . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . + T#j+U#'+V#F @l.-.~ ~ ~ K W#+.h + . . . . . . . . X#+#Y#E.E.E.E.E.E.E.E.E.E.E.N+Z#`#. . . . . . . . . . $.$+$@$#$$$<.% [ %$g@9 n@V . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . e+&$*$=$. . + 3 W 1@-$;$^ / 7++ + . . . . . . . . . + >$,$E.E.E.E.E.E.E.E.E.E.E.'$)$+ . . . . . . . . . !$~${$@$@$]$^$/$. . . } 4.($. . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . _$^+:$<$. . . . . V ).> + + . . . . . . . . . . . . . [$}$|$E.E.E.E.E.E.E.E.E.1$R.2$. . . . . . . . . . 3$4$@$@$@$@$5$6$. . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . 7$8$^+]@. . . . . . . . . + . . . . . . . . . . . . . 9$0$a$b$c$q.E.E.E.E.E.q.3#d$2.. . . . . . . . . . e$f$g$@$@$@$@$h$i$j$. . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . k$l$m$n$. . . . . . . . . . . . . . . . . . . . . . o$p$j+q$r$s$t$u$'#(#`@v$[@O+w$. . . . . . . . . . + x$y$@$@$@$@$@$@$z$A$. . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . H.B$j+C$+ . . . . . . . . . . . . . . . . . . . . . D$E$j+F$G$. + E+a@H$I$J$K$L$o+. . . . . . . . . . + M$N$O$@$@$@$@$@$@$g$P$Q$. . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . R$S$T$9$. . . . . . . . . . . . . . . . . . . . + U$V$j+W$X$. . . . . h '+Y$. . . . . . . . . . . . Z$`$ %.%+%@%g$P##%$%%%&%*%=%. . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . -%;%>%B+. . . . . . . . . . . . . . . . . . . + ,%'%j+)%!%. . . . . . . . . . . . . . . . . . . + k$:$~%{%]%^%/%(%_%:%<%[%}%|%1%. . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . 2%p$3%4%. . . . . . . . . . . . . . . . . . . 5%6%7%z+8%9%. . . . . . . . . . . . . . . . . . . 0%a%b%j+c%d%e%f%g%h%@ h i%+ . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . j%k%l%9%. . . . . . . . . . . . . . . . . . 2+C$J+m%n%2+. . . . . . . . . . . . . . . . . . + o%p%;%q%r%9$+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . h+s%j+t%+ . . . . . . . . . . . . . . . . . Z$u%z+7%t%5%. . . . . . . . . . . . . . . . . . v%S@w%j+&$,%2+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . x%y%{@z%. . . . . . . . . . . . . . . . . A%B%j+w%,%+ . . . . . . . . . . . . . . . . . + k@0$j+q%C%D%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . + E%j+F%o+. . . . . . . . . . . . . . . . X$W$j+q+U$+ . . . . . . . . . . . . . . . . . $@G%H%j+m$5+2+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . %+&+I%o%. . . . . . . . . . . . . . . . G$F$j+&+J%. . . . . . . . . . . . . . . . . + K%/+j+J+B%L%+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . ]+M%N%U+. . . . . . . . . . . . . . . O%q$j+P%o$. . . . . . . . . . . . . . . . . Q%R%S%j+T%U%V%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . 2+3+%#5++ . . . . . . . . . . . . . . W%T%j+X%9$. . . . . . . . . . . . . . . . + Y%F$j+3%Z%x@. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . `%c+v@A%. . . . . . . . . . . . . + &.&j++&z%. . . . . . . . . . . . . . . . @&C$T$j+&+_$B+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . + #&j+$&+ . . . . . . . . . . . . + %&y%j+Z%e+. . . . . . . . . . . . . . . + &&*&j+k%=&-&. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . p+V$r+s+. . . . . . . . . . . . 5%;&l$z+#&2%. . . . . . . . . . . . . . . n$>&~#j+,&]@B+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . y+z+'&V%. . . . . . . . . . . 7$)&q%3%E%!&. . . . . . . . . . . . . . + J%~&j+k%F%{&. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . ##I+q%]&. . . . . . . . . . . 0%^&j+/&(&o+. . . . . . . . . . . . . . e+_&r+j+:&<#h+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . <&[&j@}&. . . . . . . . . . |&r%j+b%1&+ . . . . . . . . . . . . . + W%i@j+R+2&X$+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . 5%Z%j+*#+ . . . . . . . . . 3&4&j+5&]&+ . . . . . . . . . . . . . A%V+6&j+7& &h+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . -&b%8&3&. . . . . . . . . s+9&j+0&<&. . . . . . . . . . . . . H.j%a&j+[&b&z%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . + a%j+Z%5%. . . . . . . . c&d&j+e&`%. . . . . . . . . . . . . f&g&/&j+j@h&'+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . v%i&[&<&. . . . . . . . j&&$j+p%k&. . . . . . . . . . . . o+j&e&j+l&^&m&. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . n&o&i@##. . . . . . + ]+p&j+q&R$. . . . . . . . . . . . r&$#c+j+s&U$Y$. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . V%W$z+{#+ . . . . . + t&u&j+=&@&. . . . . . . . . . . o+4%v&j+l&u%w&. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . x&I@V$y&. . . . . h+*#l&%#z&A&. . . . . . . . . . . p+B&7%j+C&]&5%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . + g&j+#&+ . . . . U+V+^+k%G%B+. . . . . . . . . . o+K+D&j+l$i+E&. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . !%v@c+`%. . . . F&%@j+G&H&o+. . . . . . . . . . E&#&*$j+D&K+5%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . + ,%%#w@2+. . . p+s%j+A@_$+ . . . . . . . . . 5%K+l%j+7%B&I&. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . B+J&G&]+. . . <$T#j+K&L&+ . . . . . . . . . w&u%l$j+P%u@o+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . M&s+N&. . . . O&0$P&. . . . . . . . . 5%n&d&j+Q&$#r&. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . + n$. . . . . . . . . R$U#l&j+R&4%o+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . '+h&S+j+/&g&!%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . S&^&[&j+T&j&H.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . h+ &j@j+G&V+A%. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . U&b&[&j+I+W%H.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . h+V&i&j+r+_&e+. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . W&X&R+j+i@J%+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . h+<#Y&j+~#>&n$. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . {&Z&k%j+~&D$+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . B+]@E$j+u&n%@&. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . -&`& *j+F$<&+ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "}; +". c #C3C3C3", +"+ c #A1A1A1", +"@ c #737373", +"# c #6A6A6A", +"$ c #898989", +"% c #B5B5B5", +"& c #C6C6C6", +"* c #585858", +"= c #0E0E0E", +"- c #050505", +"; c #000000", +"> c #111111", +", c #616161", +"' c #7C7C7C", +") c #A4A4A4", +"! c #EBEBEB", +"~ c #B4B4B4", +"{ c #3D3D3D", +"] c #383838", +"^ c #E7E7E7", +"/ c #D4D4D4", +"( c #8C8C8C", +"_ c #7B7B7B", +": c #9A9A9A", +"< c #E3E3E3", +"[ c #B1B1B1", +"} c #313131", +"| c #FFFFFF", +"1 c #E0E0E0", +"2 c #969696", +"3 c #7A7A7A", +"4 c #909090", +"5 c #D8D8D8", +"6 c #434343", +"7 c #030303", +"8 c #8F8F8F", +"9 c #E8E8E8", +"0 c #888888", +"a c #CCCCCC", +"b c #A6A6A6", +"c c #404040", +"d c #1E1E1E", +"e c #0F0F0F", +"f c #BDBDBD", +"g c #ACACAC", +"h c #6C6C6C", +"i c #878787", +"j c #727272", +"k c #BBBBBB", +"l c #BABABA", +"m c #565656", +"n c #060606", +"o c #252525", +"p c #DEDEDE", +"q c #2D2D2D", +"r c #6F6F6F", +"s c #686868", +"t c #E9E9E9", +"u c #8E8E8E", +"v c #2A2A2A", +"w c #4B4B4B", +"x c #0C0C0C", +"y c #020202", +"z c #999999", +"A c #777777", +"B c #C7C7C7", +"C c #626262", +"D c #454545", +"E c #8B8B8B", +"F c #979797", +"G c #7D7D7D", +"H c #040404", +"I c #757575", +"J c #9B9B9B", +"K c #989898", +"L c #CBCBCB", +"M c #212121", +"N c #CDCDCD", +"O c #343434", +"P c #E6E6E6", +"Q c #A5A5A5", +"R c #353535", +"S c #7E7E7E", +"T c #171717", +"U c #CECECE", +"V c #CACACA", +"W c #D1D1D1", +"X c #C5C5C5", +"Y c #242424", +"Z c #090909", +"` c #B7B7B7", +" . c #393939", +".. c #9D9D9D", +"+. c #6D6D6D", +"@. c #B2B2B2", +"#. c #929292", +"$. c #181818", +"%. c #5A5A5A", +"&. c #1F1F1F", +"*. c #0D0D0D", +"=. c #D7D7D7", +"-. c #080808", +";. c #828282", +">. c #1C1C1C", +",. c #E5EAEE", +"'. c #DCE2E9", +"). c #DEE4EA", +"!. c #ECEFF3", +"~. c #ADADAD", +"{. c #717171", +"]. c #131313", +"^. c #3A3A3A", +"/. c #BFCAD4", +"(. c #A8B4C2", +"_. c #9EABB7", +":. c #A0ACB6", +"<. c #9BA8B6", +"[. c #97A6B7", +"}. c #A8B5C6", +"|. c #CCD5E0", +"1. c #070707", +"2. c #AAAAAA", +"3. c #484848", +"4. c #010101", +"5. c #787878", +"6. c #DCE1E6", +"7. c #B5BFC7", +"8. c #B1B9BD", +"9. c #CECFC9", +"0. c #D5D4CD", +"a. c #D4D3CD", +"b. c #D2D2CD", +"c. c #CCCBC9", +"d. c #B8BCBF", +"e. c #9BA7B6", +"f. c #B0BECD", +"g. c #141414", +"h. c #4D4D4D", +"i. c #EAEAEA", +"j. c #414141", +"k. c #D0D0D0", +"l. c #E0E5E7", +"m. c #B8C1C7", +"n. c #C7CAC5", +"o. c #DEDDD1", +"p. c #E4E2D5", +"q. c #E7E5D8", +"r. c #E6E4D9", +"s. c #E3E2D9", +"t. c #DCDCD5", +"u. c #D4D3CF", +"v. c #CACAC8", +"w. c #9CA7B4", +"x. c #B0BCCC", +"y. c #D2D2D2", +"z. c #818181", +"A. c #2C2D2F", +"B. c #000001", +"C. c #121212", +"D. c #B0B0B0", +"E. c #9F9F9F", +"F. c #BCC5CA", +"G. c #CBCCC8", +"H. c #E4E2D4", +"I. c #EDEBD9", +"J. c #F1EFDA", +"K. c #F4F1DD", +"L. c #F3F1DE", +"M. c #F1EFE0", +"N. c #EAE9DE", +"O. c #E2E2DB", +"P. c #D6D5D2", +"Q. c #CCCCCB", +"R. c #9BA7B4", +"S. c #BBC6D5", +"T. c #8CA3BF", +"U. c #294669", +"V. c #262D35", +"W. c #656565", +"X. c #DFDFDF", +"Y. c #6E6E6E", +"Z. c #CDD5DA", +"`. c #BDC2C2", +" + c #E5E3D4", +".+ c #F0EDD8", +"++ c #F7F3DA", +"@+ c #FAF6DB", +"#+ c #FBF7DC", +"$+ c #FBF7DE", +"%+ c #F9F6E1", +"&+ c #F5F3E4", +"*+ c #EEECE3", +"=+ c #E2E1DC", +"-+ c #D4D4D1", +";+ c #A2AEBF", +">+ c #ECF1F7", +",+ c #7099C9", +"'+ c #5585BF", +")+ c #BAC7D6", +"!+ c #535353", +"~+ c #E1E1E1", +"{+ c #ABABAB", +"]+ c #797979", +"^+ c #BEC7CB", +"/+ c #DAD9CF", +"(+ c #EEECD8", +"_+ c #F7F4D9", +":+ c #FCF7D8", +"<+ c #FDF9D6", +"[+ c #FEF9D6", +"}+ c #FDF9DA", +"|+ c #FDF9DE", +"1+ c #FAF7E4", +"2+ c #F5F3E7", +"3+ c #EBEAE3", +"4+ c #DEDEDA", +"5+ c #CFCFCE", +"6+ c #A3ACB8", +"7+ c #C6D0DC", +"8+ c #BBCEE5", +"9+ c #4D80BC", +"0+ c #81A5CF", +"a+ c #AFAFAF", +"b+ c #8D8D8D", +"c+ c #C0C0C0", +"d+ c #EEF0F0", +"e+ c #BCC4C6", +"f+ c #F3EFDA", +"g+ c #FAF6D9", +"h+ c #FEF9D5", +"i+ c #FEF9D2", +"j+ c #FEFADD", +"k+ c #FDF9E4", +"l+ c #F9F7E8", +"m+ c #F1F0E7", +"n+ c #E3E3DF", +"o+ c #D5D5D3", +"p+ c #B8BCC1", +"q+ c #AEBBCC", +"r+ c #86A8D1", +"s+ c #4C80BC", +"t+ c #B6CBE3", +"u+ c #CFCFCF", +"v+ c #DADADA", +"w+ c #E5E8EA", +"x+ c #C0C6C7", +"y+ c #E9E6D8", +"z+ c #F5F2DB", +"A+ c #FCF7D9", +"B+ c #FEF9D4", +"C+ c #FEF9D1", +"D+ c #FEFADC", +"E+ c #FDFAE3", +"F+ c #FAF8E9", +"G+ c #F4F3EA", +"H+ c #E8E7E3", +"I+ c #D8D8D6", +"J+ c #C3C5C7", +"K+ c #A4B2C3", +"L+ c #D0DDED", +"M+ c #5787C0", +"N+ c #6C96C7", +"O+ c #E9EFF6", +"P+ c #E3E7E9", +"Q+ c #C0C6C6", +"R+ c #E8E6D8", +"S+ c #F5F2DC", +"T+ c #FBF7DB", +"U+ c #FEF9D7", +"V+ c #FFFAD8", +"W+ c #FEFADE", +"X+ c #FDFAE5", +"Y+ c #FBF9EA", +"Z+ c #F4F3EB", +"`+ c #C4C6C7", +" @ c #A2B1C2", +".@ c #9BB8D9", +"+@ c #4A7EBB", +"@@ c #A1BBDB", +"#@ c #E8ECEE", +"$@ c #B9C1C5", +"%@ c #E5E3D8", +"&@ c #F2F0DE", +"*@ c #FAF6DE", +"=@ c #FDF9DB", +"-@ c #FEF9DA", +";@ c #FEFADA", +">@ c #FEFAE1", +",@ c #FDFAE8", +"'@ c #F9F8ED", +")@ c #F3F2EB", +"!@ c #E6E6E3", +"~@ c #D6D6D5", +"{@ c #BFC2C4", +"]@ c #AAB7C8", +"^@ c #E5ECF5", +"/@ c #6793C6", +"(@ c #5A89C1", +"_@ c #D5E1EF", +":@ c #B6C0C8", +"<@ c #DCDCD3", +"[@ c #ECEADD", +"}@ c #F6F3E1", +"|@ c #FBF8E1", +"1@ c #FDF9E1", +"2@ c #FDFAE1", +"3@ c #FDFAE4", +"4@ c #FBF9EC", +"5@ c #F7F5ED", +"6@ c #EEEDE8", +"7@ c #E0E0DE", +"8@ c #D2D2D1", +"9@ c #ADB4BC", +"0@ c #BAC5D3", +"a@ c #ECECEC", +"b@ c #B1C7E1", +"c@ c #4B7FBB", +"d@ c #8AACD3", +"e@ c #BFC9D3", +"f@ c #C2C6C7", +"g@ c #E4E3DB", +"h@ c #EFEDE1", +"i@ c #F6F3E4", +"j@ c #F9F7E6", +"k@ c #FAF8E7", +"l@ c #FBF9E9", +"m@ c #F9F8EC", +"n@ c #F0EFEA", +"o@ c #D9D9D8", +"p@ c #9DAAB8", +"q@ c #DBE1E9", +"r@ c #9C9C9C", +"s@ c #696969", +"t@ c #7CA2CD", +"u@ c #4F82BD", +"v@ c #C0D2E7", +"w@ c #E0E5EB", +"x@ c #A4B2C0", +"y@ c #D6D5D0", +"z@ c #E3E2DB", +"A@ c #ECEBE2", +"B@ c #F2F0E6", +"C@ c #F5F3E9", +"D@ c #DADAD8", +"E@ c #ABB2BB", +"F@ c #ADBACA", +"G@ c #BEBEBE", +"H@ c #C8C8C8", +"I@ c #C3D3E5", +"J@ c #5284BE", +"K@ c #759CCB", +"L@ c #A2BCDA", +"M@ c #5C84B2", +"N@ c #A1AEBC", +"O@ c #D4D4D0", +"P@ c #DFDFDA", +"Q@ c #E4E4DE", +"R@ c #E9E8E3", +"S@ c #E8E8E3", +"T@ c #E7E6E3", +"U@ c #DAD9D8", +"V@ c #A6B3C1", +"W@ c #E3E8EE", +"X@ c #575757", +"Y@ c #767676", +"Z@ c #161616", +"`@ c #364250", +" # c #335680", +".# c #9EB6D2", +"+# c #97B5D8", +"@# c #5E8BC2", +"## c #93A9C5", +"$# c #A7B2BE", +"%# c #C7CACA", +"&# c #D5D4D2", +"*# c #D9D8D6", +"=# c #D7D7D5", +"-# c #A5B2C1", +";# c #D2DAE4", +"># c #C9C9C9", +",# c #C4C4C4", +"'# c #222222", +")# c #030609", +"!# c #494B4D", +"~# c #E4ECF5", +"{# c #8EAED4", +"]# c #638FC4", +"^# c #B9CDE4", +"/# c #C6D0DB", +"(# c #A8B5C5", +"_# c #A1ACBA", +":# c #B3B9C0", +"<# c #B9BEC3", +"[# c #B8BCC2", +"}# c #A7AFBA", +"|# c #9BA8B8", +"1# c #ACBAC9", +"2# c #E2E7EE", +"3# c #666666", +"4# c #636363", +"5# c #838383", +"6# c #DBDBDB", +"7# c #DCE5F1", +"8# c #85A8D1", +"9# c #C2D3E7", +"0# c #D0D8E2", +"a# c #B7C4D2", +"b# c #BFC9D7", +"c# c #DEE4EB", +"d# c #707070", +"e# c #B8B8B8", +"f# c #808080", +"g# c #D3DFEE", +"h# c #7DA2CE", +"i# c #749CCA", +"j# c #CAD9EB", +"k# c #4E4E4E", +"l# c #545454", +"m# c #868686", +"n# c #B3B3B3", +"o# c #D3E0EE", +"p# c #5C5C5C", +"q# c #BCBCBC", +"r# c #9E9E9E", +"s# c #E4E4E4", +"t# c #C1D3E7", +"u# c #6B95C7", +"v# c #86A9D1", +"w# c #DCE6F1", +"x# c #C2C2C2", +"y# c #939393", +"z# c #628FC4", +"A# c #D5D5D5", +"B# c #BFBFBF", +"C# c #0B0B0B", +"D# c #4F4F4F", +"E# c #EAEEF1", +"F# c #B0C6E1", +"G# c #5A89C0", +"H# c #7F7F7F", +"I# c #959595", +"J# c #747474", +"K# c #C5CED7", +"L# c #ADBAC5", +"M# c #A4B0BE", +"N# c #A2AEBC", +"O# c #9FACBB", +"P# c #A6B3C4", +"Q# c #BCC8D5", +"R# c #A7C0DD", +"S# c #5283BE", +"T# c #A0BBDB", +"U# c #858585", +"V# c #5B5B5B", +"W# c #202020", +"X# c #848484", +"Y# c #8A8A8A", +"Z# c #D7DEE3", +"`# c #B6BFC8", +" $ c #B5BDC0", +".$ c #D0D0CC", +"+$ c #D7D7D1", +"@$ c #D8D7D1", +"#$ c #D5D4D0", +"$$ c #C9CBCA", +"%$ c #AAB2BC", +"&$ c #A9B5C3", +"*$ c #CAD4DF", +"=$ c #9EBADA", +"-$ c #4C7FBB", +";$ c #5385BE", +">$ c #A9C1DE", +",$ c #B6B6B6", +"'$ c #555555", +")$ c #D4DBE1", +"!$ c #B8C0C6", +"~$ c #CDCFCA", +"{$ c #E1E0D4", +"]$ c #EAE8DC", +"^$ c #E9E8DC", +"/$ c #E7E5DD", +"($ c #E0DFD9", +"_$ c #D7D7D3", +":$ c #A4B1BF", +"<$ c #7D9DC2", +"[$ c #5B8AC1", +"}$ c #B2C8E2", +"|$ c #AEAEAE", +"1$ c #EBEEEF", +"2$ c #BAC3C9", +"3$ c #D2D3CC", +"4$ c #E6E4D6", +"5$ c #F0EDDB", +"6$ c #F6F3DF", +"7$ c #F5F3E1", +"8$ c #F3F1E3", +"9$ c #EDECE2", +"0$ c #E5E4DE", +"a$ c #D9D8D5", +"b$ c #C7C8CA", +"c$ c #7E95B2", +"d$ c #638CBD", +"e$ c #BACEE5", +"f$ c #A8A8A8", +"g$ c #919191", +"h$ c #191919", +"i$ c #D3D3D3", +"j$ c #C2CBD1", +"k$ c #C5C8C5", +"l$ c #E7E4D6", +"m$ c #F2EFDA", +"n$ c #F8F5DB", +"o$ c #FCF8DC", +"p$ c #FBF8DF", +"q$ c #FAF7E2", +"r$ c #F6F4E5", +"s$ c #F0EEE5", +"t$ c #D7D7D4", +"u$ c #B4BAC0", +"v$ c #9BAEC5", +"w$ c #B8C1C5", +"x$ c #DFDED2", +"y$ c #EFECD9", +"z$ c #F8F4DA", +"A$ c #FCF8D8", +"B$ c #FDF9DF", +"C$ c #FBF8E5", +"D$ c #F6F4E8", +"E$ c #EDECE5", +"F$ c #DFDFDB", +"G$ c #D0D0CF", +"H$ c #A2AEBD", +"I$ c #E8ECF1", +"J$ c #E2E2E2", +"K$ c #5D5D5D", +"L$ c #C1C1C1", +"M$ c #DBE1E4", +"N$ c #BEC4C4", +"O$ c #F3F0DA", +"P$ c #FBF7DA", +"Q$ c #F2F1E8", +"R$ c #E5E5E1", +"S$ c #D6D6D4", +"T$ c #A8B2BD", +"U$ c #CED7E0", +"V$ c #232323", +"W$ c #494949", +"X$ c #D0D7DC", +"Y$ c #C7CAC7", +"Z$ c #B5BBC2", +"`$ c #C1CCD8", +" % c #EBEBE8", +".% c #282828", +"+% c #CBD4D9", +"@% c #C7CBC7", +"#% c #FEF9D8", +"$% c #B9BDC3", +"%% c #BEC9D5", +"&% c #BCBAB0", +"*% c #9D9C89", +"=% c #B3B3B4", +"-% c #505D6C", +";% c #676D73", +">% c #151515", +",% c #949494", +"'% c #CFD6DE", +")% c #BFC4C5", +"!% c #E3E2D7", +"~% c #F1EFDD", +"{% c #FAF6DD", +"]% c #FEF9D9", +"^% c #FCFAE8", +"/% c #F9F7EC", +"(% c #F1F0EA", +"_% c #E5E4E1", +":% c #D5D5D4", +"<% c #B2B8BF", +"[% c #C3CDDA", +"}% c #EAE9E6", +"|% c #A3A888", +"1% c #959E72", +"2% c #C6C5BB", +"3% c #D7E2EF", +"4% c #5A88BE", +"5% c #4F7199", +"6% c #73787D", +"7% c #DDE4E7", +"8% c #B0B9BF", +"9% c #DCDBD3", +"0% c #EAE9DC", +"a% c #F5F2E0", +"b% c #FAF7E1", +"c% c #FCF9E0", +"d% c #FDF9E3", +"e% c #FCFAE7", +"f% c #FAF8EB", +"g% c #F5F4EB", +"h% c #ECEBE7", +"i% c #DEDEDC", +"j% c #A2ACB9", +"k% c #B4B4A4", +"l% c #A3AF7D", +"m% c #B8C991", +"n% c #A7AA90", +"o% c #DDDDDD", +"p% c #A2BCDB", +"q% c #9AB7D8", +"r% c #D6D6D6", +"s% c #363636", +"t% c #AEBAC4", +"u% c #CFCFCB", +"v% c #E1E0D7", +"w% c #EDEBDF", +"x% c #F4F2E3", +"y% c #F8F6E4", +"z% c #FAF7E6", +"A% c #F8F6EA", +"B% c #E2E2DF", +"C% c #C7C7C8", +"D% c #A2AFBF", +"E% c #D6D5CF", +"F% c #9DA47E", +"G% c #C2D59A", +"H% c #C3D69B", +"I% c #9AA477", +"J% c #6F6E64", +"K% c #A3A3A3", +"L% c #6D97C8", +"M% c #5686BF", +"N% c #CFDCEC", +"O% c #4A4A4A", +"P% c #4C4C4C", +"Q% c #C0CAD5", +"R% c #A7B1BA", +"S% c #D5D4CF", +"T% c #E0DFD8", +"U% c #EAE9E0", +"V% c #EFEDE3", +"W% c #F2F1E7", +"X% c #F0EFE8", +"Y% c #EAEAE5", +"Z% c #E3E2DF", +"`% c #A0AAB6", +" & c #B6C2D2", +".& c #ACAE97", +"+& c #AFBE88", +"@& c #B9CA91", +"#& c #878A6F", +"$& c #EDEDEC", +"%& c #DCDCDC", +"&& c #B8CCE4", +"*& c #84A7D0", +"=& c #DDE6F0", +"-& c #859DB9", +";& c #B1B8BD", +">& c #D3D2CF", +",& c #DBDAD6", +"'& c #E1E0DB", +")& c #E5E4DF", +"!& c #DCDCDA", +"~& c #AFB5BC", +"{& c #AAB6C6", +"]& c #C5C3BA", +"^& c #9AA377", +"/& c #9BA577", +"(& c #C3C2B8", +"_& c #83A6D0", +":& c #D8E3F0", +"<& c #82A6D0", +"[& c #4A7AB4", +"}& c #7B95B4", +"|& c #A6AFB8", +"1& c #CCCCCA", +"2& c #D2D2CF", +"3& c #D4D3D1", +"4& c #D3D3D1", +"5& c #A5ADB7", +"6& c #A6B3C3", +"7& c #A6AA8D", +"8& c #BACC93", +"9& c #B9CB92", +"0& c #A6AA8E", +"a& c #CDDBEC", +"b& c #5586BF", +"c& c #6E98C8", +"d& c #EAF0F7", +"e& c #CFDDED", +"f& c #79A0CC", +"g& c #789ECC", +"h& c #C3D2E4", +"i& c #AFBDCC", +"j& c #A8B0BA", +"k& c #BBBDC1", +"l& c #BEC0C3", +"m& c #BBBEC1", +"n& c #A9B1B9", +"o& c #98A6B6", +"p& c #ACB9CA", +"q& c #E7EBF0", +"r& c #B7B7A8", +"s& c #9EAA79", +"t& c #9BA678", +"u& c #C2C0B6", +"v& c #98B6D8", +"w& c #A3BDDC", +"x& c #C7D7E9", +"y& c #7199C9", +"z& c #80A4CF", +"A& c #D6E2EF", +"B& c #B6C2D1", +"C& c #A3B1C4", +"D& c #9BABBE", +"E& c #A0B0C3", +"F& c #B3C0D0", +"G& c #D7DEE7", +"H& c #C9CED0", +"I& c #9DA481", +"J& c #C1D399", +"K& c #A5A98D", +"L& c #E2EAF4", +"M& c #6491C5", +"N& c #5C8BC1", +"O& c #BED0E6", +"P& c #6893C6", +"Q& c #89ABD2", +"R& c #DFE8F3", +"S& c #A9C1DD", +"T& c #748686", +"U& c #A7B480", +"V& c #BED197", +"W& c #BCCE95", +"X& c #B5C58E", +"Y& c #B1C18B", +"Z& c #AEBD87", +"`& c #AAB884", +" * c #838961", +".* c #C7C6BD", +"+* c #AEC5E0", +"@* c #4B7EBB", +"#* c #8DADD4", +"$* c #B5CAE3", +"%* c #5F8DC3", +"&* c #92B1D5", +"** c #E7EEF6", +"=* c #4B75A3", +"-* c #5A655D", +";* c #919677", +">* c #95987B", +",* c #989A7F", +"'* c #9B9D84", +")* c #9FA089", +"!* c #A3A48F", +"~* c #A8A895", +"{* c #AEAD9D", +"]* c #B4B3A5", +"^* c #BBBBAE", +"/* c #E0DFDB", +"(* c #5082BD", +"_* c #C2D3E8", +":* c #ACC4E0", +"<* c #5687BF", +"[* c #9AB7D9", +"}* c #A8C1DE", +"|* c #608DC3", +"1* c #6C95C7", +"2* c #B4C4D4", +"3* c #C4D5E8", +"4* c #5183BD", +"5* c #779ECC", +"6* c #4F81BD", +"7* c #A3BEDC", +"8* c #CBDAEB", +"9* c #83A7D0", +"0* c #4F81BC", +"a* c #90B0D5", +"b* c #8FAFD4", +"c* c #ACC4DF", +"d* c #9BB7D9", +"e* c #5F8CC2", +"f* c #DAE4F0", +"g* c #5D8CC2", +"h* c #E0E9F3", +"i* c #E8EEF6", +"j* c #92B1D6", +"k* c #91B1D5", +"l* c #DAE4F1", +"m* c #A5BFDD", +"n* c #96B4D7", +"o* c #A6BFDD", +"p* c #5E8CC2", +"q* c #5485BF", +"r* c #C6D6E9", +"s* c #C9D8EA", +"t* c #DBE5F1", +"u* c #4E80BC", +"v* c #80A5CF", +"w* c #CEDCEC", +"x* c #799FCC", +"y* c #ECF1F8", +"z* c #A5BEDD", +"A* c #5D8BC2", +"B* c #6F98C8", +"C* c #B7CCE4", +"D* c #C5D5E9", +"E* c #82A6CF", +"F* c #C8D8EA", +"G* c #93B2D6", +"H* c #D1DEED", +"I* c #BCCFE5", +"J* c #6692C5", +"K* c #8BACD3", +"L* c #EBF1F7", +"M* c #9CB8D9", +"N* c #9FBBDB", +"O* c #B3C9E2", +"P* c #C7D7EA", +"Q* c #7FA4CE", +"R* c #95B3D7", +"S* c #DDE6F2", +"T* c #ABC3DF", +"U* c #A2BDDC", +"V* c #719AC9", +"W* c #8AABD2", +"X* c #A2BCDC", +"Y* c #7EA3CE", +"Z* c #DEE7F2", +"`* c #BFD1E6", +" = c #99B6D8", +".= c #5888C0", +"+= c #ADC5E0", +"@= c #A1BCDB", +"#= c #729BCA", +"$= c #C8D7EA", +"%= c #5384BE", +"&= c #E7EDF5", +"*= c #B7CBE3", +"== c #97B5D7", +"-= c #DDE7F2", +";= c #88AAD2", +">= c #6994C6", +",= c #5989C0", +"'= c #749BCA", +")= c #608EC3", +"!= c #7FA3CE", +"~= c #729AC9", +"{= c #7CA1CD", +"]= c #98B5D8", +"^= c #CCDAEB", +"/= c #769DCB", +"(= c #7BA0CD", +"_= c #E7EEF5", +":= c #9FBADA", +"<= c #BDD0E6", +"[= c #739BCA", +"}= c #C3D4E8", +"|= c #D9E4F0", +"1= c #5485BE", +"2= c #E1EAF3", +"3= c #BED1E6", +"4= c #4E81BC", +"5= c #6491C4", +"6= c #8CADD3", +"7= c #E6EDF5", +"8= c #759DCB", +"9= c #B2C8E1", +"0= c #5C8AC1", +"a= c #7AA0CC", +"b= c #E3EBF4", +"c= c #D4E0EE", +"d= c #E5EDF5", +"e= c #9EB9DA", +"f= c #9DB9DA", +"g= c #779ECB", +"h= c #789FCC", +"i= c #E4EBF4", +"j= c #5988C0", +"k= c #AFC6E1", +"l= c #E4ECF4", +"m= c #ADC4E0", +"n= c #6A95C7", +"o= c #C1D2E7", +"p= c #C2D4E8", +"q= c #CAD9EA", +"r= c #5787BF", +"s= c #7AA0CD", +"t= c #E1E9F3", +"u= c #7BA1CD", +"v= c #E0E8F3", +"w= c #BBCFE5", +"x= c #DFE8F2", +"y= c #97B4D7", +"z= c #729ACA", +"A= c #95B4D7", +"B= c #94B3D6", +"C= c #5182BD", +" ", +" ", +" ", +" ", +" ", +" ", +" . + @ # $ % ", +" & * = - ; ; > , ' ) ! ", +" ~ { ; ; ; ; ; ] ^ / ( _ : < ", +" [ } ; ; ; ; ; ; , | | | 1 2 3 4 5 ", +" < 6 ; ; ; ; ; ; 7 8 | | | | | 9 + _ 0 a ", +" b c d ; ; ; ; ; e f | | | | | | | | g h i ", +" j k l m n ; ; ; o p | | | | | | | | | a q r ! ", +" / s | t u v ; ; w | | | | | | | | | | + x y i ", +" z A | | | | B C x A | | | | | | | | | ^ D ; ; q a ", +" E 4 | | | | | | F G | | | | | | | | | 8 H ; ; ; I ", +" J K | | | | | | L M s N | | | | | | 5 ] ; ; ; ; O P ", +" Q ' | | | | | | : y ; R : | | | | | S ; ; ; ; ; T U ", +" V r | | | | | | # ; ; ; x h W | | X Y ; ; ; ; ; Z ` ", +" A p | | | | ! .; ; ; ; ; ] ..| +.; ; ; ; ; ; n @. ", +" F #.| | | | N $.; ; ; ; ; ; > %.&.; ; ; ; ; ; *.. ", +" < _ =.| | | Q -.; ; ; ; ; ; y ;.: .; ; ; ; ; >.=. ,.'.).!. ", +" ~.$ ^ | | {.; ; ; ; ; ; ; .p | / {.].; ; ; ^.! /.(._.:.<.[.}.|. ", +" #._ B 6 ; ; ; ; ; ; 1.2 | | | | 2.3.4.; 5. 6.7.8.9.0.a.b.c.d.e.f. ", +" X z G g.; ; ; ; ; ; h.i.| | | | | 1 G j.k. l.m.n.o.p.q.r.s.t.u.v.w.x. ", +" y.z.A.B.; ; ; C.D.| | | | | | ;.E. F.G.H.I.J.K.L.M.N.O.P.Q.R.S. ", +" T.U.V.H ; W.| | | | | | X.# Y. Z.`. +.+++@+#+$+%+&+*+=+-+& ;+ ", +" >+,+'+)+J !+;.^ | | | ~+{+h ]+t ^+/+(+_+:+<+[+}+|+1+2+3+4+5+6+7+ ", +" 8+9+0+ a+( r b+5.%._ c+ d+e+ +f+g+h+i+i+[+j+k+l+m+n+o+p+q+ ", +" r+s+t+ U u+X v+ w+x+y+z+A+B+C+C+h+D+E+F+G+H+I+J+K+ ", +" L+M+N+O+ P+Q+R+S+T+U+B+B+V+W+X+Y+Z+H+I+`+ @ ", +" .@+@@@ #@$@%@&@*@=@-@;@j+>@,@'@)@!@~@{@]@ ", +" ^@/@(@_@ :@<@[@}@|@1@2@3@,@4@5@6@7@8@9@0@ ", +" 9 a@P b@c@d@ e@f@g@h@i@j@k@l@m@5@n@!@o@L p@q@ ", +" ^ r@W.s@G Y.: k. t@u@v@ w@x@y@z@A@B@C@G+)@6@!@D@u+E@F@ ", +" + Y.z.G@ | 9 H@$ @ c+I@J@K@ L@M@N@O@P@Q@R@S@T@7@U@u+p+V@W@ ", +" 8 X@l | | | | | | Y@4.Z@`@ #.# +#+@@###$#%#&#*#I+=#8@L E@-#;# ", +" ` {.>#| | | | | | ,#'#; ; ; )#!#E.^ ~#{#+@]#^# /#(#_#:#<#[#}#|#1#2# ", +" 3#4 | | | | | | | 4#; ; ; ; ; ; > 5#) 6# 7#8#+@N+9# 0#a#q+f.b#c# ", +" F H ].d#y.| | | | ~.].; ; ; ; ; ; ] ~+e#f#.. g#h#+@i#j# ", +" k#; ; 4.R K | | | l#; ; ; ; ; ; ; 4#| | 6#m#n# j#i#+@h#o# ", +" < v ; ; ; ; 1.p#q#r#-.; ; ; ; ; ; H 2 | | | y.G s# t#u#+@v#w# ", +" W T ; ; ; ; ; ; '#l#7 ; ; ; ; ; ; = x#| | | | y#F ^#z#+@{#^@ A# ", +" B#C#; ; ; ; ; ; D#6#z.&.; ; ; ; ; v s#| | | | X.A E# F#G#+@+# H#4#I# ", +" G@x ; ; ; ; ; *.b | | ` l#y ; ; ; X@| | | | | | J#x# K#L#M#N#O#P#Q# R#S#9+T# x#E U#E ", +" u+T ; ; ; ; ; V#| | | | ! U#W#; ; X#| | | | | | Y#: Z#`# $.$+$@$#$$$%$&$*$ =$-$;$>$ >#0 i V H#@. d#^ ", +" t R ; ; ; ; $.,$| | | | | | e#'$C.% | | | | | | Q E )$!$~${$q.]$^$/$($_$`+:$<$+@[$}$ v+G |$D.A @.f f#H# 3 ", +" Y.; ; ; ; # | | | | | | | | i.f#J | | | | | | ) G 1$2$3$4$5$K.6$7$8$9$0$a$b$c$d$e$ ,$.. g Y#8 f$ 3 ", +" G@M ; ; M & | | | | | | | | | g$h$d#i$| | | | b+U# j$k$l$m$n$T+o$p$q$r$s$Q@t$u$v$ % 4 E J ", +" _ ; ; ]+| | | | | | | | | | 3#; ; R K | | d#B# w$x$y$z$A$[+U+}+B$C$D$E$F$G$H$I$ s#H# 9 X#$ J$ ", +" 6#* h$. | | | | | | | | | a@{ ; ; ; C#K$L$i$s@ M$N$l$O$P$h+i+i+[+j+k+l+Q$R$S$T$U$ 3 z _ F ", +" 1 h d#a | | | | | | | | =.W#; ; ; ; ; V$W$b+ X$Y$y+z+A+B+C+C+h+D+E+Y+G+H+I+Z$`$ % 5.! 1 F ", +" ) ]+f#B#| | | | | | [ Z ; ; ; ; ; ; .%N +%@%R+S+T+U+B+B+#%W+X+Y+Z+H+I+$%%% &%*% 1 z. ", +" =%-%;%|$| | | | X#; ; ; ; ; ; >%,% '%)%!%~%{%=@]%-@j+>@^%/%(%_%:%<%[% }%|%1%2% ) .. ", +" 3%4%5%6%A E.P | m ; ; ; ; ; d ,% 7%8%9%0%a%b%c%1@d%e%f%g%h%i%G$j%;# k%l%m%n% ~ G +.$ o% f#A# ", +" p%+@q% r%u Y@5.Y ; ; ; y s%Q t%u%v%w%x%y%z%l+A%Z+6@B%:%C%D% E%F%G%H%I%J%;.. ^ K%f#3 m# ", +" O+L%M%N% < J 3#O%P%' ) v+ Q%R%S%T%U%V%W%Q$X%Y%Z%=#N `% & .&+&H%H%@&#&$& / ~.%& ", +" &&9+*& =&-&;&>&,&'&)&)&n+!&o+a ~&{& ]&^&H%H%H%H%/&(& ", +" _&9+^# :&<&[&}&|&1&2&3&4&4&U H@5&6&c# 7&8&H%H%H%H%9&0& ", +" a&b&c&d& e&f&+@g&h&i&|#j&k&l&m&n&o&p&q& r&s&H%H%H%H%H%H%t&u& ", +" v&+@w& x&y&+@z&A& q@B&C&D&E&F&G& H&I&J&H%H%H%H%H%H%8&K& ", +" L&M&N&:& O&P&+@Q&R& S&T&U&V&W&8&m%X&Y&Z&`& *.* ", +" +*@*#* $*%*+@&*** a&*&=*-*;*>*,*'*)*!*~*{*]*^*/* ", +" f&(*_* :*<*c@[* }*|*+@1*2* ", +" 3*4*5* w&u@6*7* 8*9*@*0*a*:& ", +" b*+@c* d*c@<*c* R#e*+@L%$* ", +" f*g*]#h* i*j*+@e*$* j#<&+@0*k*l* ", +" m*+@n* R&Q&+@/@O& o*p*+@c&t+ ", +" >+,+q*8* A&z&+@,+r* s*0++@u@j*t* ", +" 8+u*v* w*g&+@x*e& y*z*A*+@B*C* ", +" r+-$t+ D*B*+@E*:& F*z&+@(*G*w# ", +" H*M+u#i* I*J*+@K*h* L*w&N&+@,+&& ", +" M*+@N* O*g*+@G*O+ P*Q*+@4*R*S* ", +" ^@P&(@_@ T*b&c@M* d&U*[$+@V*^# ", +" b@c@W* X*0*(*m* r*Y*+@4*n*Z* ", +" t@0*`* =+@.=+= O+@=(@+@#=e$ ", +" $=%=i# &=a*+@|**= D*h#+@J@==R& ", +" G*+@>$ -=;=+@>=`* i*T#,=+@'=I* ", +" S*|*)=-= _@!=+@~=$= 3*{=+@%=]=h* ", +" }*+@G* ^=/=+@(=H* _=:=.=+@i#<= ", +" [=%=$= }=L%+@9*|= }=(=+@1= =2= ", +" 3=4=h# 8+5=+@6=L& 7==$M++@8=O& ", +" Q&c@}$ 9=0=+@R*L* _*a=+@1=d*b= ", +" c=G#P&d= >$1=-$e= ^@f=<*+@g=`* ", +" :=+@M* T#9+4*o* v@h=+@b&.@i= ", +" **u#M+H* +#+@j=k= i=M*M%+@h=v@ ", +" $*-$v# ^@b*+@z#&& v@5*+@<*f=l= ", +" m=j=8+ p%+@n=o= b=d*b&+@x*t# ", +" _@ p=<&q= 3=/=+@r==$7= ", +" d& L&q%1=+@s=_* ", +" <=K@+@.=:=** ", +" t= =%=+@u=}= ", +" I*i#+@j=T#i* ", +" v=]=%=+@t@D* ", +" w=[=+@(@@=O+ ", +" x=y=J@+@h#r* ", +" e$z=+@[$U*d& ", +" Z*A=4*+@Y*x& ", +" ^#y&+@0=7*L* ", +" S*B=C=+@z&$= "}; diff --git a/Plugins/org.mitk.gui.qt.igttracking/resources/iconTrackingToolBox.xpm b/Plugins/org.mitk.gui.qt.igttracking/resources/iconTrackingToolBox.xpm index 2d6dd64c79..3a34f6b2bf 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/resources/iconTrackingToolBox.xpm +++ b/Plugins/org.mitk.gui.qt.igttracking/resources/iconTrackingToolBox.xpm @@ -1,536 +1,3050 @@ /* XPM */ -static char * icon2_xpm[] = { -"100 100 433 2", +static char * iconTrackingToolBox_xpm[] = { +"100 100 2947 2", " c None", -". c #FFFFFF", -"+ c #FDFDFD", -"@ c #FDFEFE", -"# c #AEBDD0", -"$ c #B2C1D2", -"% c #F8F9FB", -"& c #C7D1DE", -"* c #567DAD", -"= c #4B76AA", -"- c #8AA2C1", -"; c #D4DCE5", -"> c #FEFEFE", -", c #F4F6F8", -"' c #819DBD", -") c #4B7BB5", -"! c #4E80BC", -"~ c #4979B2", -"{ c #6487B2", -"] c #A9BACE", -"^ c #F3F5F8", -"/ c #AFBED1", -"( c #4A76AB", -"_ c #4F81BD", -": c #4E7FBB", -"< c #4975AB", -"[ c #829DBE", -"} c #CBD4E0", -"| c #E1E6ED", -"1 c #6C8DB5", -"2 c #4D7FBA", -"3 c #4B7AB4", -"4 c #5C82AF", -"5 c #A1B3CA", -"6 c #ECF0F4", -"7 c #99AEC7", -"8 c #4877AF", -"9 c #4875AC", -"0 c #7A98BB", -"a c #C2CDDB", -"b c #C9D3DF", -"c c #587FAE", -"d c #4C7CB6", -"e c #547BAA", -"f c #BDCAD8", -"g c #F6F7F9", -"h c #849FBE", -"i c #4B7BB4", -"j c #B1C0D2", -"k c #4B76AB", -"l c #E3E8EE", -"m c #6F8FB6", -"n c #4D7EB9", -"o c #E1E6EC", -"p c #9BAFC8", -"q c #4876AE", -"r c #A7B6C3", -"s c #F4F3EC", -"t c #F5F4ED", -"u c #F6F5EF", -"v c #F7F6F0", -"w c #F7F7F2", -"x c #F8F8F4", -"y c #F9F8F5", -"z c #FAF9F6", -"A c #FAFAF7", -"B c #FBFBF9", -"C c #FCFBFA", -"D c #FCFCFB", -"E c #FDFDFC", -"F c #FEFDFD", -"G c #FEFEFD", -"H c #DAE1E9", -"I c #587CA8", -"J c #7C97B4", -"K c #E6E6DF", -"L c #F0EEE4", -"M c #F0EEE5", -"N c #F0EFE5", -"O c #F1EFE6", -"P c #F1EFE7", -"Q c #F2F0E7", -"R c #F2F0E8", -"S c #F3F1E9", -"T c #F3F2EA", -"U c #F6F4EF", -"V c #F6F5F0", -"W c #F7F6F1", -"X c #F8F7F3", -"Y c #FBFBF8", -"Z c #FCFBF9", -"` c #FCFCFA", -" . c #FDFCFB", -".. c #F2F4F7", -"+. c #99ADC6", -"@. c #557DAD", -"#. c #4B7CB6", -"$. c #557CAB", -"%. c #BBC4CA", -"&. c #F1F0E7", -"*. c #F4F2EB", -"=. c #F5F3ED", -"-. c #F5F4EE", -";. c #F9F8F4", -">. c #F9F9F6", -",. c #FBFAF8", -"'. c #FDFDFE", -"). c #7A97BB", -"!. c #4977AF", -"~. c #90A4B9", -"{. c #EEECE3", -"]. c #F2F1E9", -"^. c #F3F1EA", -"/. c #F4F3ED", -"(. c #F8F7F2", -"_. c #F9F9F5", -":. c #FAF9F7", -"<. c #FFFFFE", -"[. c #A1B4CA", -"}. c #4E78AA", -"|. c #4A7AB4", -"1. c #4E7FBA", -"2. c #6889B1", -"3. c #D1D6D5", -"4. c #F3F2EB", -"5. c #F7F6F2", -"6. c #EFF3F8", -"7. c #678DBB", -"8. c #537CAC", -"9. c #4976AB", -"0. c #ABBBCD", -"a. c #EEF3F8", -"b. c #6994C6", -"c. c #9DB8D7", -"d. c #6488B2", -"e. c #4979B1", -"f. c #7E9ABC", -"g. c #ECF2F8", -"h. c #6793C6", -"i. c #A9C2DE", -"j. c #D5DCE6", -"k. c #8BA3C1", -"l. c #587CA7", -"m. c #C3CEDC", -"n. c #EBF1F7", -"o. c #6591C5", -"p. c #ACC4E0", -"q. c #D7DFE7", -"r. c #EAF0F7", -"s. c #6390C4", -"t. c #B0C7E1", -"u. c #E9EFF6", -"v. c #628FC4", -"w. c #B3C9E2", -"x. c #E7EEF6", -"y. c #618EC3", -"z. c #B5CAE3", -"A. c #E5ECF5", -"B. c #608EC3", -"C. c #B8CCE4", -"D. c #E4EBF4", -"E. c #608DC3", -"F. c #BACEE5", -"G. c #E2EAF4", -"H. c #5F8DC2", -"I. c #BDD0E6", -"J. c #E0E9F3", -"K. c #5E8CC2", -"L. c #C0D2E7", -"M. c #DFE8F3", -"N. c #5D8CC2", -"O. c #C2D3E8", -"P. c #DDE7F2", -"Q. c #5D8BC2", -"R. c #C4D5E8", -"S. c #DCE6F1", -"T. c #5C8AC1", -"U. c #C7D7E9", -"V. c #DAE4F1", -"W. c #5B8AC1", -"X. c #CAD9EA", -"Y. c #D8E3F0", -"Z. c #5A8AC1", -"`. c #CCDAEB", -" + c #D5E1EF", -".+ c #CEDCEC", -"++ c #D3E0EE", -"@+ c #D0DDED", -"#+ c #D1DEED", -"$+ c #D2DFEE", -"%+ c #D4E0EF", -"&+ c #CBDAEB", -"*+ c #D6E2EF", -"=+ c #C9D8EA", -"-+ c #DAE5F1", -";+ c #C1D3E7", -">+ c #5C8BC1", -",+ c #DEE8F2", -"'+ c #BED1E6", -")+ c #BCCFE5", -"!+ c #BACDE4", -"~+ c #F2F1E8", -"{+ c #B7CBE3", -"]+ c #B4C9E2", -"^+ c #E7EDF5", -"/+ c #B1C7E1", -"(+ c #E8EFF6", -"_+ c #AFC6E0", -":+ c #FBFAF7", -"<+ c #ACC4DF", -"[+ c #6692C5", -"}+ c #ECF1F7", -"|+ c #A9C1DE", -"1+ c #6893C6", -"2+ c #EDF2F8", -"3+ c #A6BFDD", -"4+ c #ECEBE1", -"5+ c #EFEDE3", -"6+ c #A4BEDC", -"7+ c #6B95C7", -"8+ c #F1F5F9", -"9+ c #BEC5C6", -"0+ c #98A8B4", -"a+ c #AAB6BC", -"b+ c #E7E7DF", -"c+ c #A1BCDB", -"d+ c #6D96C8", -"e+ c #F2F5FA", -"f+ c #D9DBD6", -"g+ c #7D95AA", -"h+ c #6B8DAE", -"i+ c #6887A5", -"j+ c #B5BEC2", -"k+ c #D0D4D1", -"l+ c #ADB8BF", -"m+ c #B7C0C3", -"n+ c #E9E9E0", -"o+ c #9EBADA", -"p+ c #6F98C8", -"q+ c #F2F6FA", -"r+ c #D2D5D2", -"s+ c #6E8AA5", -"t+ c #6D90B2", -"u+ c #6A8AAA", -"v+ c #ABB7BE", -"w+ c #E1E2DB", -"x+ c #8A9FB0", -"y+ c #6A8BAA", -"z+ c #6988A5", -"A+ c #ADB8BE", -"B+ c #9BB7D9", -"C+ c #7199C9", -"D+ c #F3F6FA", -"E+ c #E9E8E0", -"F+ c #9AA9B5", -"G+ c #6583A0", -"H+ c #869CAE", -"I+ c #CED2D0", -"J+ c #D5D8D4", -"K+ c #708CA6", -"L+ c #6C8FB0", -"M+ c #98A9B6", -"N+ c #ECEBE2", -"O+ c #98B5D8", -"P+ c #739BCA", -"Q+ c #F4F7FB", -"R+ c #BDC8CF", -"S+ c #7D99B3", -"T+ c #D0D5D4", -"U+ c #8EA2B2", -"V+ c #6786A3", -"W+ c #7791A9", -"X+ c #BBC3C5", -"Y+ c #96B4D7", -"Z+ c #749CCB", -"`+ c #F5F8FB", -" @ c #B0C0CB", -".@ c #8AA5BE", -"+@ c #E8E8E1", -"@@ c #96ACC0", -"#@ c #96AABB", -"$@ c #93B2D6", -"%@ c #769DCB", -"&@ c #F6F8FB", -"*@ c #9AAEBF", -"=@ c #96ACBF", -"-@ c #EDECE3", -";@ c #D5DAD9", -">@ c #7E9CB9", -",@ c #C5CFD3", -"'@ c #90B0D5", -")@ c #799FCC", -"!@ c #F7F9FC", -"~@ c #A4B1BA", -"{@ c #6A86A1", -"]@ c #7F96AB", -"^@ c #D4D7D3", -"/@ c #9EAFBC", -"(@ c #859FB7", -"_@ c #E5E6DF", -":@ c #FCFDFE", -"<@ c #8DADD4", -"[@ c #7BA0CD", -"}@ c #D3D7D3", -"|@ c #708CA5", -"1@ c #698AA9", -"2@ c #ABB6BD", -"3@ c #8299AD", -"4@ c #6888A6", -"5@ c #8098AD", -"6@ c #DFE0DA", -"7@ c #8AACD3", -"8@ c #7CA2CE", -"9@ c #F9FAFC", -"0@ c #D8DAD6", -"a@ c #7992A9", -"b@ c #B1BBC0", -"c@ c #BAC3C6", -"d@ c #6A8AA9", -"e@ c #6E91B3", -"f@ c #6C8AA7", -"g@ c #CBD0CF", -"h@ c #FCFCFD", -"i@ c #88AAD2", -"j@ c #7EA3CE", -"k@ c #FAFBFD", -"l@ c #A9B5BD", -"m@ c #6986A1", -"n@ c #9FAEB8", -"o@ c #C8CDCC", -"p@ c #6E8BA6", -"q@ c #7D95AB", -"r@ c #D7D9D5", -"s@ c #FBFCFD", -"t@ c #85A8D1", -"u@ c #81A5CF", -"v@ c #BBC8D0", -"w@ c #829EB9", -"x@ c #E1E3DE", -"y@ c #DBDEDB", -"z@ c #7792AB", -"A@ c #94A6B5", -"B@ c #C0C7C8", -"C@ c #F7F5F0", -"D@ c #82A6D0", -"E@ c #84A7D0", -"F@ c #FAFCFD", -"G@ c #AABCC9", -"H@ c #8EA8BF", -"I@ c #EAEAE1", -"J@ c #B7C5CE", -"K@ c #84A1BB", -"L@ c #DFE1DD", -"M@ c #F9FBFD", -"N@ c #80A4CF", -"O@ c #87A9D1", -"P@ c #99B0C3", -"Q@ c #9EB3C5", -"R@ c #E9E9E1", -"S@ c #92AAC0", -"T@ c #A8BAC8", -"U@ c #F8FAFC", -"V@ c #8AABD2", -"W@ c #8AA4BD", -"X@ c #B0C0CC", -"Y@ c #CDD5D7", -"Z@ c #7C9BB8", -"`@ c #CCD4D6", -" # c #7BA1CD", -".# c #8CADD4", -"+# c #E0E2DE", -"@# c #7F9DBA", -"## c #C1CCD2", -"$# c #A8BAC9", -"%# c #91AAC0", -"&# c #F7F9FB", -"*# c #8FAFD5", -"=# c #7B9AB8", -"-# c #D0D7D8", -";# c #E0E3DE", -"># c #85A1BB", -",# c #B6C4CE", -"'# c #769ECB", -")# c #CFD3D0", -"!# c #CDD1CE", -"~# c #AEBBC2", -"{# c #7995AF", -"]# c #BBC5C7", -"^# c #7894AE", -"/# c #B9C3C7", -"(# c #EAE9E0", -"_# c #749CCA", -":# c #95B3D7", -"<# c #D8DBD6", -"[# c #819486", -"}# c #81946C", -"|# c #80946C", -"1# c #7A906A", -"2# c #7F936C", -"3# c #7C907A", -"4# c #C8CDCA", -"5# c #729ACA", -"6# c #839676", -"7# c #8B9E53", -"8# c #819566", -"9# c #C6CCC9", -"0# c #6F99C9", -"a# c #9BB8D9", -"b# c #6D97C8", -"c# c #6C96C7", -"d# c #EFF4F9", -"e# c #F1EFE5", -"f# c #A6C0DD", -"g# c #EBF0F7", -"h# c #C7CCC9", -"i# c #B2C8E2", -"j# c #F4F2EC", -"k# c #829577", -"l# c #899D54", -"m# c #809467", -"n# c #CCD2D3", -"o# c #E8EEF6", -"p# c #B4CAE3", -"q# c #DBDDD8", -"r# c #93A29F", -"s# c #8A9C8E", -"t# c #8B9D97", -"u# c #D4DBE1", -"v# c #F4F7FA", -"w# c #B0C6E1", -"x# c #D9E4F0", -"y# c #E7E6DE", -"z# c #EFF0ED", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . @ # $ % . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . & * = - ; > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . , ' ) ! ~ { ] ^ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . / ( _ _ _ : < [ } > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . | 1 2 _ _ _ _ _ 3 4 5 6 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . @ 7 8 _ _ _ _ _ _ _ ! 9 0 a @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . b c ! _ _ _ _ _ _ _ _ _ d e f > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . g h i _ _ _ _ _ _ _ _ _ _ ! c } . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . j k ! _ _ _ _ _ _ _ _ _ _ 8 7 @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . l m n _ _ _ _ _ _ _ _ _ _ 2 1 o > > > > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . > p q _ _ _ _ _ _ _ _ _ _ _ ( r s t u v w x y z A B C D E E F G > > > > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . H I ! _ _ _ _ _ _ _ _ _ _ ) J K L L L L L L L L M N O P Q R S T s t U V W X y z A Y Z ` .E + G > > > > > > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . ..+.@.#._ _ _ _ _ _ _ _ ! $.%.L L L L L L L L L L L L L L L L L L L L L L L L L M M O O &.R S T *.=.-.V W X ;.>.A ,.B ` .E E G > > > > > . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . '.a ).9 ! _ _ _ _ _ _ !.~.{.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M O O &.R ].^.*./.-.u W (.x _.:.,.B C D E E F G > > > > > <.. . ", -". . . . . . . . . . . . . . 6 [.}.|._ _ _ _ 1.2.3.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M N O &.R ].^.4.s t u v 5.X y z ", -". . . . . . . . . . . . . . . 6.7.8.< : _ _ 9.0.*.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . a.b.c.] d.e.#.f...x L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . g.h.i.> j.k.l.m.. E ^.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . n.o.p.> . % q.> . . (.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . r.s.t.> . . . . . . D ].L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . u.v.w.. . . . . . . > 5.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . x.y.z.. . . . . . . . ` R L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . A.B.C.. . . . . . . . > W L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . D.E.F.. . . . . . . . . Z Q L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . G.H.I.. . . . . . . . . > V L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . J.K.L.. . . . . . . . . . B P L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . M.N.O.. . . . . . . . . . > u L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . P.Q.R.. . . . . . . . . . . ,.O L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . S.T.U.. . . . . . . . . . . > -.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . V.W.X.. . . . . . . . . . . . A O L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . Y.Z.`.. . . . . . . . . . . . > -.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . +W..+. . . . . . . . . . . . . z N L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . ++W.@+. . . . . . . . . . . . . G =.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . #+W.$+. . . . . . . . . . . . . . _.M L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ", -". . . . . . . . . . . . . . . .+W.%+. . . . . . . . . . . . . . G s L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L /.", -". . . . . . . . . . . . . . . &+W.*+. . . . . . . . . . . . . . . y L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L &.A ", -". . . . . . . . . . . . . . . =+W.Y.. . . . . . . . . . . . . . . + *.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L W > ", -". . . . . . . . . . . . . . . U.W.-+. . . . . . . . . . . . . . . . x L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L *.E . ", -". . . . . . . . . . . . . . . R.T.S.. . . . . . . . . . . . . . . . E T L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L O z . . ", -". . . . . . . . . . . . . . . ;+>+,+. . . . . . . . . . . . . . . . . X L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L V > . . ", -". . . . . . . . . . . . . . . '+>+J.. . . . . . . . . . . . . . . . . .S L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ^.` . . . ", -". . . . . . . . . . . . . . . )+K.G.. . . . . . . . . . . . . . . . . . w L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L M ;.. . . . ", -". . . . . . . . . . . . . . . !+H.D.. . . . . . . . . . . . . . . . . . D ~+L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L -.> . . . . ", -". . . . . . . . . . . . . . . {+B.A.. . . . . . . . . . . . . . . . . . > W L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L ~+B . . . . . ", -". . . . . . . . . . . . . . . ]+v.^+. . . . . . . . . . . . . . . . . . . C R L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L X > . . . . . ", -". . . . . . . . . . . . . . . /+s.(+. . . . . . . . . . . . . . . . . . . > v L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L =.F . . . . . . ", -". . . . . . . . . . . . . . . _+o.r.. . . . . . . . . . . . . . . . . . . . B &.L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L &.:+. . . . . . . ", -". . . . . . . . . . . . . . . <+[+}+. . . . . . . . . . . . . . . . . . . . > V L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L 5.> . . . . . . . ", -". . . . . . . . . . . . . . . |+1+2+. . . . . . . . . . . . . . . . . . . . . ,.O L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L L s E . . . . . . . . ", -". . . . . . . . . . . . . . . 3+b.6.. . . . . . . . . . . . . . . . . . . . . > u L L L L L L L L L L L L L L L L L L L L L L L 4+5+L L L L L L L L L L L L L L L L L L L L L L L O z . . . . . . . . . ", -". . . . . . . . . . . . . . . 6+7+8+. . . . . . . . . . . . . . . . . . . . . . A O L L L L L L L L L L L L L L L L L L L L L 9+0+a+b+L L L L L L L 5+5+L L L L L L L L L L L L L V > . . . . . . . . . ", -". . . . . . . . . . . . . . > c+d+e+. . . . . . . . . . . . . . . . . . . . . . > -.L L L L L L L L L L L L L L L L L L L L f+g+h+i+j+L L L L L L k+l+m+n+L L L L L L L L L L L T D . . . . . . . . . . ", -". . . . . . . . . . . . . . > o+p+q+. . . . . . . . . . . . . . . . . . . . . . . A N L L L L L L L L L L L L L L L L L L L r+s+t+u+v+5+L L L L w+x+y+z+A+5+L L L L L L L L L M y . . . . . . . . . . . ", -". . . . . . . . . . . . . . > B+C+D+. . . . . . . . . . . . . . . . . . . . . . . > =.L L L L L L L L L L L L L L L L L L L E+F+G+H+I+L L L L L J+K+t+L+M+N+L L L L L L L L L U > . . . . . . . . . . . ", -". . . . . . . . . . . . . . @ O+P+Q+. . . . . . . . . . . . . . . . . . . . . . . . z M L L L L L L L L L L L L L L L L L L L R+S+T+L L L L L L E+U+V+W+X+L L L L L L L L L ].B . . . . . . . . . . . . ", -". . . . . . . . . . . . . . '.Y+Z+`+. . . . . . . . . . . . . . . . . . . . . . . . G s L L L L L L L L L L L L L L L L L L 5+ @.@+@L L L L L L N+@@#@r+5+L L L L L L L L L X . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . '.$@%@&@. . . . . . . . . . . . . . . . . . . . . . . . . _.M L L L L L L L L L L L L L L L L L N+*@=@-@L L L L L L ;@>@,@L L L L L L L L L L t G . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . '.'@)@!@. . . . . . . . . . . . . . . . . . . . . . . . . F *.L L L L L L L L L L L L L L L L N+~@{@]@r+L L L L L ^@/@(@_@L L L L L L L L L Q ,.. . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . :@<@[@!@. . . . . . . . . . . . . . . . . . . . . . . . . . x L L L L L L L L L L L L L L L L }@|@t+1@2@5+L L L r+3@4@5@6@L L L L L L L L L 5.> . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . :@7@8@9@. . . . . . . . . . . . . . . . . . . . . . . . . . E T L L L L L L L L L L L L L L L 0@a@L+4@b@5+L L L c@d@e@f@g@L L L L L L L L s E . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . h@i@j@k@. . . . . . . . . . . . . . . . . . . . . . . . . . . X L L L L L L L L L L L L L L L 5+l@m@n@w+L L L L o@p@h+q@r@L L L L L L L O z . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . s@t@u@k@. . . . . . . . . . . . . . . . . . . . . . . . . . . E ^.L L L L L L L L L L L L L L L v@w@x@L L L L L y@z@A@B@5+L L L L L L L C@> . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . k@D@E@F@. . . . . . . . . . . . . . . . . . . . . . . . . . . . X L L L L L L L L L L L L L L 5+G@H@I@L L L L 5+J@K@L@L L L L L L L L T D . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . M@N@O@s@. . . . . . . . . . . . . . . . . . . . . . . . . . . . D ].L L L L L L L L L L L L L -@P@Q@{.L L L L R@S@T@5+L L L L L L L M y . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . U@j@V@s@. . . . . . . . . . . . . . . . . . . . . . . . . . . . > W L L L L L L L L L L L L L +@W@X@5+L L L L Y@Z@`@L L L L L L L L u > . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . !@ #.#:@. . . . . . . . . . . . . . . . . . . . . . . . . . . . . ` R L L L L L L L L L L L L +#@###L L L L 5+$#%#R@L L L L L L L ].Z . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . &#)@*#:@. . . . . . . . . . . . . . . . . . . . . . . . . . . . . > W L L L L L L L L L L L L ;@=#-#L L L L ;#>#,#5+L L L L L L L X <.. . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . &@'#$@'.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Z Q L L L L L L L 5+)#!#!#~#{#]#!#!#!#!#~#^#/#(#L L L L L L t G . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . `+_#:#@ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > V L L L L L L L <#[#}#}#|#1#}#}#}#}#}#2#1#3#4#L L L L L Q ,.. . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . Q+5#O+> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y P L L L L L L 0@6#7#7#7#7#7#7#7#7#7#7#7#8#9#L L L L L w > . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . D+0#a#> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > u L L L L L L 0@6#7#7#7#7#7#7#7#7#7#7#7#8#9#L L L L s E . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . q+b#o+> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ,.O L L L L L 0@6#7#7#7#7#7#7#7#7#7#7#7#8#9#L L L O :.. . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . 8+c#c+> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > -.L L L L L 0@6#7#7#7#7#7#7#7#7#7#7#7#8#9#L L L W > . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . d#7+6+> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . A e#L L L L 0@6#7#7#7#7#7#7#7#7#7#7#7#8#9#L L 4. .. . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . a.b.f#> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > t L L L L 0@6#7#7#7#7#7#7#7#7#7#7#7#8#9#L M y . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . 2+1+i.> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . z M L L L 0@6#7#7#7#7#7#7#7#7#7#7#7#8#9#L u > . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . }+[+<+> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . G =.L L L 0@6#7#7#7#7#7#7#7#7#7#7#7#8#9#S C . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . g#o._+> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . _.M L L 0@6#7#7#7#7#7#7#7#7#7#7#7#8#h#x . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . u.s.i#> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + j#L L 0@k#l#l#l#l#l#l#l#l#l#l#l#m#n#G . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . o#v.p#> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ;.L L q#r#s#s#s#s#s#s#s#s#s#s#s#t#u#. . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . v#w#x#> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E 4.L L y#y#y#y#y#y#y#y#y#y#y#b+z#> . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . > > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . x L L L L L L L L L L L L L s E . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . E T L L L L L L L L L L L O A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . <.X L L L L L L L L L L L W > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .S L L L L L L L L L 4. .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > 5.L L L L L L L L N _.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ` ~+L L L L L L L u > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > W L L L L L L S C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C R L L L L L ;.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > V L L L L -.> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . B &.L L R Y . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > V L L (.> . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Y O s + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . > W A . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . + > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ", -". . . . . . . . . > > @ '.> > > . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . "}; +". c #C3C3C3", +"+ c #A1A1A1", +"@ c #737373", +"# c #6A6A6A", +"$ c #898989", +"% c #B5B5B5", +"& c #C6C6C6", +"* c #585858", +"= c #0E0E0E", +"- c #050505", +"; c #000000", +"> c #111111", +", c #616161", +"' c #7C7C7C", +") c #A4A4A4", +"! c #EBEBEB", +"~ c #B4B4B4", +"{ c #3D3D3D", +"] c #383838", +"^ c #E7E7E7", +"/ c #D4D4D4", +"( c #8C8C8C", +"_ c #7B7B7B", +": c #9A9A9A", +"< c #E3E3E3", +"[ c #B1B1B1", +"} c #313131", +"| c #FFFFFF", +"1 c #E0E0E0", +"2 c #969696", +"3 c #7A7A7A", +"4 c #909090", +"5 c #D8D8D8", +"6 c #434343", +"7 c #030303", +"8 c #8F8F8F", +"9 c #E8E8E8", +"0 c #888888", +"a c #CCCCCC", +"b c #A6A6A6", +"c c #404040", +"d c #1E1E1E", +"e c #0F0F0F", +"f c #BDBDBD", +"g c #ACACAC", +"h c #6C6C6C", +"i c #878787", +"j c #727272", +"k c #BBBBBB", +"l c #BABABA", +"m c #565656", +"n c #060606", +"o c #252525", +"p c #DEDEDE", +"q c #2D2D2D", +"r c #6F6F6F", +"s c #686868", +"t c #E9E9E9", +"u c #8E8E8E", +"v c #2A2A2A", +"w c #4B4B4B", +"x c #0C0C0C", +"y c #020202", +"z c #999999", +"A c #777777", +"B c #C7C7C7", +"C c #626262", +"D c #454545", +"E c #8B8B8B", +"F c #979797", +"G c #7D7D7D", +"H c #040404", +"I c #757575", +"J c #9B9B9B", +"K c #989898", +"L c #CBCBCB", +"M c #212121", +"N c #CDCDCD", +"O c #343434", +"P c #E6E6E6", +"Q c #A5A5A5", +"R c #353535", +"S c #7E7E7E", +"T c #171717", +"U c #CECECE", +"V c #CACACA", +"W c #D1D1D1", +"X c #C5C5C5", +"Y c #242424", +"Z c #090909", +"` c #B7B7B7", +" . c #393939", +".. c #9D9D9D", +"+. c #6D6D6D", +"@. c #B2B2B2", +"#. c #929292", +"$. c #181818", +"%. c #5A5A5A", +"&. c #1F1F1F", +"*. c #0D0D0D", +"=. c #D7D7D7", +"-. c #080808", +";. c #828282", +">. c #1C1C1C", +",. c #E8ECEA", +"'. c #E1E5E6", +"). c #E2E6E8", +"!. c #EDEFF1", +"~. c #ADADAD", +"{. c #717171", +"]. c #131313", +"^. c #3A3A3A", +"/. c #CBD2D4", +"(. c #BBC3C6", +"_. c #B5BDBF", +":. c #B7BEC0", +"<. c #B1BABF", +"[. c #ACB6C0", +"}. c #B4BFCA", +"|. c #D1D8E1", +"1. c #070707", +"2. c #AAAAAA", +"3. c #484848", +"4. c #010101", +"5. c #787878", +"6. c #E2E6E3", +"7. c #C5CCCA", +"8. c #C7CBC4", +"9. c #DEDCCD", +"0. c #E3E0D0", +"a. c #E2E0D2", +"b. c #E0DED2", +"c. c #DBDAD1", +"d. c #CBCDCA", +"e. c #B1B9C2", +"f. c #BBC7D2", +"g. c #141414", +"h. c #4D4D4D", +"i. c #EAEAEA", +"j. c #414141", +"k. c #D0D0D0", +"l. c #E5E8E4", +"m. c #C8CECA", +"n. c #D8D9CA", +"o. c #EAE7D1", +"p. c #EFECD4", +"q. c #F2EED7", +"r. c #F1EED9", +"s. c #EFECDB", +"t. c #EBE9DB", +"u. c #E3E2D9", +"v. c #D9D9D3", +"w. c #B2BAC2", +"x. c #BCC5D1", +"y. c #D2D2D2", +"z. c #818181", +"A. c #2C2D2F", +"B. c #000001", +"C. c #121212", +"D. c #B0B0B0", +"E. c #9F9F9F", +"F. c #CAD0CC", +"G. c #DAD9CB", +"H. c #EEEBD3", +"I. c #F5F1D5", +"J. c #F8F4D6", +"K. c #F9F5D7", +"L. c #F9F5D9", +"M. c #F8F4DC", +"N. c #F4F2DF", +"O. c #EFEDE1", +"P. c #E7E6DE", +"Q. c #DDDCD7", +"R. c #B4BDC4", +"S. c #C3CED9", +"T. c #8CA3BF", +"U. c #294669", +"V. c #262D35", +"W. c #656565", +"X. c #DFDFDF", +"Y. c #6E6E6E", +"Z. c #D4DAD9", +"`. c #CACEC6", +" + c #ECE9D2", +".+ c #F5F1D4", +"++ c #FAF6D4", +"@+ c #FCF7D4", +"#+ c #FDF8D4", +"$+ c #FDF8D7", +"%+ c #FCF8DB", +"&+ c #FAF7E0", +"*+ c #F6F3E4", +"=+ c #EFEEE4", +"-+ c #E6E5DF", +";+ c #D6D7D5", +">+ c #B4BECA", +",+ c #ECF1F7", +"'+ c #7099C9", +")+ c #5585BF", +"!+ c #BAC7D6", +"~+ c #535353", +"{+ c #E1E1E1", +"]+ c #ABABAB", +"^+ c #797979", +"/+ c #C7CECC", +"(+ c #E2E0CF", +"_+ c #F2EED5", +":+ c #F9F5D6", +"<+ c #FDF8D3", +"[+ c #FEF8D1", +"}+ c #FEF9D2", +"|+ c #FEF9D5", +"1+ c #FDF9DA", +"2+ c #FCF9E0", +"3+ c #FAF7E5", +"4+ c #F5F3E8", +"5+ c #EEEDE6", +"6+ c #E2E1DE", +"7+ c #BBC2CA", +"8+ c #CFD7E0", +"9+ c #BBCEE5", +"0+ c #4D80BC", +"a+ c #81A5CF", +"b+ c #AFAFAF", +"c+ c #8D8D8D", +"d+ c #C0C0C0", +"e+ c #EFF2EE", +"f+ c #C3C9C7", +"g+ c #E8E6D4", +"h+ c #F4F1D7", +"i+ c #FBF6D6", +"j+ c #FEF8D3", +"k+ c #FEF9D0", +"l+ c #FEF9D4", +"m+ c #FEF9D9", +"n+ c #FEFAE1", +"o+ c #FCFAE7", +"p+ c #F9F7EB", +"q+ c #F1F0E9", +"r+ c #E7E6E3", +"s+ c #D0D2D3", +"t+ c #BDC8D4", +"u+ c #86A8D1", +"v+ c #4C80BC", +"w+ c #B6CBE3", +"x+ c #CFCFCF", +"y+ c #DADADA", +"z+ c #E7EAE9", +"A+ c #C6CBC8", +"B+ c #EAE8D6", +"C+ c #F5F2DA", +"D+ c #FBF7D9", +"E+ c #FEF9D3", +"F+ c #FEF9D6", +"G+ c #FEFADC", +"H+ c #FEFBE2", +"I+ c #FDFAE9", +"J+ c #FAF9ED", +"K+ c #F4F3ED", +"L+ c #EAEAE6", +"M+ c #D9D9DA", +"N+ c #B8C3CF", +"O+ c #D0DDED", +"P+ c #5787C0", +"Q+ c #6C96C7", +"R+ c #E9EFF6", +"S+ c #E5E8E8", +"T+ c #C2C7C7", +"U+ c #E7E5D7", +"V+ c #F4F1DB", +"W+ c #FAF6DB", +"X+ c #FDF9D9", +"Y+ c #FEF9D8", +"Z+ c #FEFAD8", +"`+ c #FFFADB", +" @ c #FFFBDF", +".@ c #FEFBE6", +"+@ c #FDFAEC", +"@@ c #FAF9EF", +"#@ c #F4F3EE", +"$@ c #EAEAE7", +"%@ c #D9DADA", +"&@ c #B7C2CF", +"*@ c #9BB8D9", +"=@ c #4A7EBB", +"-@ c #A1BBDB", +";@ c #EAECED", +">@ c #BDC5C7", +",@ c #E5E4D8", +"'@ c #F1EFDE", +")@ c #F9F6E0", +"!@ c #FCF9DF", +"~@ c #FDFADE", +"{@ c #FEFADF", +"]@ c #FEFBE5", +"^@ c #FEFCEB", +"/@ c #FCFBEF", +"(@ c #FAF9F1", +"_@ c #F4F3EF", +":@ c #EAE9E7", +"<@ c #D6D8D8", +"[@ c #BDC7D4", +"}@ c #E5ECF5", +"|@ c #6793C6", +"1@ c #5A89C1", +"2@ c #D5E1EF", +"3@ c #B9C3C9", +"4@ c #DDDDD5", +"5@ c #ECEADE", +"6@ c #F4F2E3", +"7@ c #FCFAE5", +"8@ c #FDFBE6", +"9@ c #FDFBE8", +"0@ c #FDFBEC", +"a@ c #FDFBF0", +"b@ c #FBFAF2", +"c@ c #F7F7F2", +"d@ c #F0EFEC", +"e@ c #E5E5E4", +"f@ c #C8CDD1", +"g@ c #C7D0DB", +"h@ c #ECECEC", +"i@ c #B1C7E1", +"j@ c #4B7FBB", +"k@ c #8AACD3", +"l@ c #C3CCD5", +"m@ c #C7CACB", +"n@ c #E5E4DC", +"o@ c #F5F4E7", +"p@ c #F9F7EA", +"q@ c #FBF9EC", +"r@ c #FCFAEE", +"s@ c #FBFAF0", +"t@ c #FAF9F2", +"u@ c #F8F7F1", +"v@ c #F3F2EF", +"w@ c #EBEBEA", +"x@ c #DFDFDE", +"y@ c #B7C0CB", +"z@ c #E0E5EC", +"A@ c #9C9C9C", +"B@ c #696969", +"C@ c #7CA2CD", +"D@ c #4F82BD", +"E@ c #C0D2E7", +"F@ c #E2E6EB", +"G@ c #ABB7C3", +"H@ c #D9D8D5", +"I@ c #EEEDE5", +"J@ c #F3F2EA", +"K@ c #F6F5ED", +"L@ c #F8F7EF", +"M@ c #F6F5F1", +"N@ c #F1F1EE", +"O@ c #E2E2E1", +"P@ c #C4C9CF", +"Q@ c #BDC7D5", +"R@ c #BEBEBE", +"S@ c #C8C8C8", +"T@ c #C3D3E5", +"U@ c #5284BE", +"V@ c #759CCB", +"W@ c #A5BEDB", +"X@ c #668CB6", +"Y@ c #AAB6C2", +"Z@ c #DADAD7", +"`@ c #E4E4E0", +" # c #EBEAE6", +".# c #EEEEE9", +"+# c #EDEDEB", +"@# c #E9E9E8", +"## c #CDD0D4", +"$# c #BBC4CF", +"%# c #E6EBF0", +"&# c #575757", +"*# c #767676", +"=# c #161616", +"-# c #364250", +";# c #335680", +"># c #9EB6D2", +",# c #97B5D8", +"'# c #638FC4", +")# c #9AB0C9", +"!# c #B0BAC5", +"~# c #CFD1D1", +"{# c #DDDDDB", +"]# c #E3E2E1", +"^# c #E4E4E3", +"/# c #DCDCDB", +"(# c #C1C7CD", +"_# c #B8C2CE", +":# c #D8DFE7", +"<# c #C9C9C9", +"[# c #C4C4C4", +"}# c #222222", +"|# c #030609", +"1# c #494B4D", +"2# c #E4ECF5", +"3# c #8EAED4", +"4# c #B9CDE4", +"5# c #CBD3DE", +"6# c #B2BDCB", +"7# c #B0B9C5", +"8# c #C1C6CC", +"9# c #C8CCCF", +"0# c #C8CBCF", +"a# c #BBC1CA", +"b# c #B0BAC6", +"c# c #BBC6D3", +"d# c #E5E9F0", +"e# c #666666", +"f# c #636363", +"g# c #838383", +"h# c #DBDBDB", +"i# c #DCE5F1", +"j# c #85A8D1", +"k# c #C2D3E7", +"l# c #D3DBE4", +"m# c #BFCAD7", +"n# c #B8C3D2", +"o# c #BAC6D4", +"p# c #C6D0DC", +"q# c #E1E6ED", +"r# c #707070", +"s# c #B8B8B8", +"t# c #808080", +"u# c #D3DFEE", +"v# c #7DA2CE", +"w# c #749CCA", +"x# c #CAD9EB", +"y# c #4E4E4E", +"z# c #545454", +"A# c #868686", +"B# c #B3B3B3", +"C# c #D3E0EE", +"D# c #E7DCDC", +"E# c #5C5C5C", +"F# c #BCBCBC", +"G# c #9E9E9E", +"H# c #E4E4E4", +"I# c #C1D3E7", +"J# c #6B95C7", +"K# c #86A9D1", +"L# c #DCE6F1", +"M# c #EDE0E1", +"N# c #AB534B", +"O# c #AA443D", +"P# c #A03D2C", +"Q# c #C2C2C2", +"R# c #939393", +"S# c #628FC4", +"T# c #B0685E", +"U# c #B73B27", +"V# c #A94230", +"W# c #B14333", +"X# c #BFBFBF", +"Y# c #0B0B0B", +"Z# c #4F4F4F", +"`# c #EDF0EF", +" $ c #B0C6E1", +".$ c #5A89C0", +"+$ c #D5BEB4", +"@$ c #A92B1F", +"#$ c #B1402E", +"$$ c #A73A28", +"%$ c #663D37", +"&$ c #747474", +"*$ c #D5DAD9", +"=$ c #C4CCCD", +"-$ c #BEC6C8", +";$ c #BBC2C6", +">$ c #B6BFC6", +",$ c #B6C1CB", +"'$ c #C6CFD9", +")$ c #A7C0DD", +"!$ c #5283BE", +"~$ c #A0BBDB", +"{$ c #AB453C", +"]$ c #B84935", +"^$ c #B25C50", +"/$ c #985A4E", +"($ c #616568", +"_$ c #5B5B5B", +":$ c #858585", +"<$ c #202020", +"[$ c #848484", +"}$ c #8A8A8A", +"|$ c #E3E6E1", +"1$ c #CFD4CF", +"2$ c #D3D6CB", +"3$ c #E3E2D3", +"4$ c #E8E6D7", +"5$ c #E6E4D8", +"6$ c #E3E2D8", +"7$ c #D8D9D4", +"8$ c #BEC4C8", +"9$ c #B7C1CB", +"0$ c #D0D8E2", +"a$ c #9EBADA", +"b$ c #4C7FBB", +"c$ c #5385BE", +"d$ c #A9C1DE", +"e$ c #CCA09E", +"f$ c #AE3122", +"g$ c #B14E3E", +"h$ c #AD5C50", +"i$ c #977671", +"j$ c #8E8E90", +"k$ c #B6B6B6", +"l$ c #555555", +"m$ c #E1E5DF", +"n$ c #D5D8CF", +"o$ c #E5E4D1", +"p$ c #F1EED7", +"q$ c #F3F0D9", +"r$ c #F2F0DD", +"s$ c #F0EEDF", +"t$ c #EAE9DE", +"u$ c #E3E2DB", +"v$ c #D1D2D1", +"w$ c #B3BDC8", +"x$ c #8AA6C7", +"y$ c #5183BD", +"z$ c #5B8AC1", +"A$ c #B2C8E2", +"B$ c #C1BEBB", +"C$ c #A43026", +"D$ c #B8422E", +"E$ c #A03A27", +"F$ c #A4392B", +"G$ c #7E4D43", +"H$ c #5D5F61", +"I$ c #656465", +"J$ c #F1F2E9", +"K$ c #D6D9D0", +"L$ c #EAE7D2", +"M$ c #F5F1D6", +"N$ c #FAF6D8", +"O$ c #FBF7DA", +"P$ c #FAF6DC", +"Q$ c #F8F5E1", +"R$ c #F3F1E3", +"S$ c #EEECE3", +"T$ c #E4E3DD", +"U$ c #D4D4D3", +"V$ c #91A6BD", +"W$ c #7095C2", +"X$ c #B77169", +"Y$ c #B63F2E", +"Z$ c #A73927", +"`$ c #A23826", +" % c #A43527", +".% c #963629", +"+% c #483C36", +"@% c #444347", +"#% c #919191", +"$% c #191919", +"%% c #D3D3D3", +"&% c #D6DBD5", +"*% c #DFDFCF", +"=% c #FAF6D6", +"-% c #FCF7D5", +";% c #FDF9D6", +">% c #FCF8DF", +",% c #F9F7E5", +"'% c #F4F3E7", +")% c #ECEBE4", +"!% c #E1E1DD", +"~% c #C1C6CB", +"{% c #A7B7CC", +"]% c #E6D8D3", +"^% c #A93223", +"/% c #B34234", +"(% c #A33825", +"_% c #A23728", +":% c #A13727", +"<% c #A13A28", +"[% c #9C3626", +"}% c #793027", +"|% c #572727", +"1% c #E3E3E2", +"2% c #D3D7CE", +"3% c #EFECD5", +"4% c #F8F4D7", +"5% c #FEF8D2", +"6% c #FEF9D1", +"7% c #FDFADF", +"8% c #FCF9E5", +"9% c #F8F6E9", +"0% c #F2F1E9", +"a% c #E8E7E3", +"b% c #DADAD8", +"c% c #B0BAC7", +"d% c #E9EDF2", +"e% c #AB5047", +"f% c #B9402C", +"g% c #A43728", +"h% c #A13627", +"i% c #A03727", +"j% c #A43627", +"k% c #9F3625", +"l% c #9A3726", +"m% c #963628", +"n% c #5D5D5D", +"o% c #C1C1C1", +"p% c #7F7F7F", +"q% c #686767", +"r% c #737370", +"s% c #92918C", +"t% c #E5E7E3", +"u% c #D6D8CE", +"v% c #F3EFD8", +"w% c #FAF5D7", +"x% c #FEFADE", +"y% c #FDFAE6", +"z% c #FAF9EB", +"A% c #F6F4EC", +"B% c #EDECE8", +"C% c #E0E0DE", +"D% c #B6BEC8", +"E% c #D2DAE3", +"F% c #D2A7A0", +"G% c #AD3426", +"H% c #AF3E2E", +"I% c #A23726", +"J% c #A13527", +"K% c #A03626", +"L% c #9E3424", +"M% c #9E3727", +"N% c #9C3623", +"O% c #983723", +"P% c #933525", +"Q% c #232323", +"R% c #494949", +"S% c #878784", +"T% c #908F8A", +"U% c #DBE1DD", +"V% c #DBDCD0", +"W% c #FAF6D9", +"X% c #FDF8D6", +"Y% c #FFF9D5", +"Z% c #FFFADA", +"`% c #FEFAE0", +" & c #FDFBE7", +".& c #F7F6EE", +"+& c #EEEEEA", +"@& c #E2E1E0", +"#& c #C2C7CC", +"$& c #C7D1DC", +"%& c #A94339", +"&& c #B94532", +"*& c #A23625", +"=& c #A13626", +"-& c #A03523", +";& c #9E3622", +">& c #9E3524", +",& c #9B3426", +"'& c #963527", +")& c #903329", +"!& c #893328", +"~& c #282828", +"{& c #91918F", +"]& c #9E9D99", +"^& c #D6DCDC", +"/& c #D8D9D1", +"(& c #F1EEDB", +"_& c #F9F5DC", +":& c #FDF8DA", +"<& c #FFFADD", +"[& c #FEFBE4", +"}& c #FDFBEB", +"|& c #FBF9EF", +"1& c #F7F6EF", +"2& c #EEEDEA", +"3& c #E1E1E0", +"4& c #C5C8CD", +"5& c #C4CED9", +"6& c #BD837F", +"7& c #B33825", +"8& c #AB3C2B", +"9& c #A23523", +"0& c #A03525", +"a& c #A03322", +"b& c #A13323", +"c& c #A03223", +"d& c #A03323", +"e& c #9D3323", +"f& c #9C3222", +"g& c #9A3324", +"h& c #973228", +"i& c #913125", +"j& c #8C3327", +"k& c #8A3329", +"l& c #B3B3B4", +"m& c #505D6C", +"n& c #676D73", +"o& c #AEAEAE", +"p& c #151515", +"q& c #949494", +"r& c #3F3F3F", +"s& c #3E3E3E", +"t& c #7A7A79", +"u& c #898988", +"v& c #9C9B98", +"w& c #D8DDE0", +"x& c #D1D4CF", +"y& c #EDEBDC", +"z& c #F6F3DF", +"A& c #FBF7DF", +"B& c #FDF9DE", +"C& c #FDFBE9", +"D& c #FCFBEE", +"E& c #FAF9F0", +"F& c #F5F4EF", +"G& c #ECEBE9", +"H& c #BFC4CA", +"I& c #C9D2DD", +"J& c #E5E5E5", +"K& c #EADBD7", +"L& c #AB3124", +"M& c #B84532", +"N& c #A23422", +"O& c #9E3522", +"P& c #9F3424", +"Q& c #A03222", +"R& c #9F3222", +"S& c #9F3223", +"T& c #9E3122", +"U& c #9C3121", +"V& c #9A3020", +"W& c #9B3122", +"X& c #9A3323", +"Y& c #9A3123", +"Z& c #963125", +"`& c #923326", +" * c #8D3127", +".* c #D7E2EF", +"+* c #5A88BE", +"@* c #4F7199", +"#* c #73787D", +"$* c #6B6B6B", +"%* c #545453", +"&* c #535250", +"** c #C2C8C9", +"=* c #E6E4DA", +"-* c #F1EFE0", +";* c #F8F5E3", +">* c #FBF8E4", +",* c #FDFAEA", +"'* c #FBF9F0", +")* c #F7F6F0", +"!* c #F1F0ED", +"~* c #E6E6E5", +"{* c #DADAD9", +"]* c #B0B9C3", +"^* c #D5DDE6", +"/* c #676767", +"(* c #DDD0D0", +"_* c #CAA6A2", +":* c #D9B8B5", +"<* c #B5685F", +"[* c #B74330", +"}* c #A93625", +"|* c #A13322", +"1* c #A03221", +"2* c #9F3122", +"3* c #9D3222", +"4* c #9B3120", +"5* c #9A2F20", +"6* c #992F21", +"7* c #992F1F", +"8* c #983120", +"9* c #992F22", +"0* c #942F21", +"a* c #903125", +"b* c #A2BCDB", +"c* c #9AB7D8", +"d* c #88342C", +"e* c #D6D6D6", +"f* c #363636", +"g* c #D3D3D0", +"h* c #BDC6CD", +"i* c #DAD9D4", +"j* c #EAE8DF", +"k* c #F1F0E4", +"l* c #F6F4E7", +"m* c #FAF9EE", +"n* c #F9F8EF", +"o* c #F2F1ED", +"p* c #ADB8C6", +"q* c #A0A0A0", +"r* c #DDAFAA", +"s* c #B34D40", +"t* c #B0483E", +"u* c #AA4435", +"v* c #A33A2F", +"w* c #CFAFAD", +"x* c #E2C5BD", +"y* c #AA2D1D", +"z* c #B4402D", +"A* c #9E3021", +"B* c #9A301F", +"C* c #9A2E22", +"D* c #9A2E21", +"E* c #9A2D20", +"F* c #972E20", +"G* c #972C20", +"H* c #982E20", +"I* c #6D97C8", +"J* c #5686BF", +"K* c #CFDCEC", +"L* c #8C3127", +"M* c #8C362C", +"N* c #8F3124", +"O* c #4A4A4A", +"P* c #4C4C4C", +"Q* c #C7D1DA", +"R* c #B8BFC5", +"S* c #DEDED8", +"T* c #E8E7E0", +"U* c #EFEEE6", +"V* c #F5F4EC", +"W* c #F3F2EE", +"X* c #EFEEEB", +"Y* c #E0E0DF", +"Z* c #D7D7D6", +"`* c #AEB6C0", +" = c #BCC7D5", +".= c #646464", +"+= c #E3E0E0", +"@= c #B84533", +"#= c #C5462D", +"$= c #BC4130", +"%= c #9E4337", +"&= c #A44638", +"*= c #A5544D", +"== c #A84237", +"-= c #BD4431", +";= c #A23123", +">= c #A13324", +",= c #9D2F22", +"'= c #9C2E21", +")= c #9B2D1F", +"!= c #9A2B20", +"~= c #992C20", +"{= c #992D21", +"]= c #972B1F", +"^= c #982D21", +"/= c #972D20", +"(= c #B8CCE4", +"_= c #84A7D0", +":= c #8E2C1E", +"<= c #8B2E22", +"[= c #8C2E23", +"}= c #8B352A", +"|= c #832A21", +"1= c #DFCBC9", +"2= c #DFE7F0", +"3= c #95A9C1", +"4= c #BFC4C8", +"5= c #DCDBD8", +"6= c #E4E3DF", +"7= c #DEDEDD", +"8= c #D6D6D5", +"9= c #BBC0C6", +"0= c #515151", +"a= c #595959", +"b= c #5F6564", +"c= c #8F5D59", +"d= c #C1412C", +"e= c #CA422E", +"f= c #A54336", +"g= c #A33F36", +"h= c #9F3F37", +"i= c #9A3A2A", +"j= c #D7BCBA", +"k= c #CE9E98", +"l= c #B53927", +"m= c #AC3B28", +"n= c #A33123", +"o= c #9E3022", +"p= c #9D2F21", +"q= c #9D2F23", +"r= c #9B2C20", +"s= c #9B2D21", +"t= c #9A2C20", +"u= c #982A1F", +"v= c #982C20", +"w= c #982B1F", +"x= c #962A1E", +"y= c #952A1D", +"z= c #83A6D0", +"A= c #90291F", +"B= c #8D281E", +"C= c #8B281B", +"D= c #8A291D", +"E= c #872718", +"F= c #A66863", +"G= c #E5D6D9", +"H= c #D8E3F0", +"I= c #84A7CF", +"J= c #5583B9", +"K= c #8AA2BC", +"L= c #B4BBC3", +"M= c #D5D5D3", +"N= c #D8D8D7", +"O= c #D1D1D0", +"P= c #B1B8C1", +"Q= c #AEBAC8", +"R= c #DFE5EB", +"S= c #A8A8A8", +"T= c #424242", +"U= c #3C3C3C", +"V= c #959595", +"W= c #868788", +"X= c #B8473A", +"Y= c #C5432A", +"Z= c #BD4434", +"`= c #A24036", +" - c #9F4236", +".- c #9E4036", +"+- c #9E3E35", +"@- c #9B4A43", +"#- c #C4C0BB", +"$- c #A63226", +"%- c #BA422E", +"&- c #A12E22", +"*- c #A33023", +"=- c #9D2F20", +"-- c #9B2C21", +";- c #992A1F", +">- c #CDDBEC", +",- c #5586BF", +"'- c #6E98C8", +")- c #EAF0F7", +"!- c #912920", +"~- c #8F281F", +"{- c #8A281E", +"]- c #932D1D", +"^- c #932C1E", +"/- c #96352B", +"(- c #9D5A52", +"_- c #BA8A87", +":- c #D9C2C2", +"<- c #ECE5E5", +"[- c #CFDDED", +"}- c #79A0CC", +"|- c #7A9FCC", +"1- c #C6D4E4", +"2- c #B6C2CF", +"3- c #A6B2C0", +"4- c #B4BAC3", +"5- c #C5C7CA", +"6- c #C8C9CC", +"7- c #B4BBC2", +"8- c #A3AFBD", +"9- c #B2BECD", +"0- c #E7EBF0", +"a- c #525252", +"b- c #444444", +"c- c #949594", +"d- c #969595", +"e- c #9D746B", +"f- c #C2432E", +"g- c #C94531", +"h- c #A84230", +"i- c #A43F36", +"j- c #9F4135", +"k- c #9F4036", +"l- c #9B3B2F", +"m- c #CCA8A4", +"n- c #B76A63", +"o- c #B73C2B", +"p- c #A83426", +"q- c #A12F22", +"r- c #9B2B21", +"s- c #9A2A20", +"t- c #972C1F", +"u- c #95291D", +"v- c #98B6D8", +"w- c #A3BDDC", +"x- c #932820", +"y- c #922820", +"z- c #912A20", +"A- c #8F271D", +"B- c #912B1D", +"C- c #8E2D1D", +"D- c #962C1F", +"E- c #97271C", +"F- c #922619", +"G- c #93261B", +"H- c #943126", +"I- c #A04A3F", +"J- c #AC6A64", +"K- c #BA9088", +"L- c #D4C0BB", +"M- c #F2E9E7", +"N- c #C7D7E9", +"O- c #7199C9", +"P- c #80A4CF", +"Q- c #D6E2EF", +"R- c #DCE2EA", +"S- c #A9B7C8", +"T- c #A2B1C3", +"U- c #A7B6C7", +"V- c #B7C3D2", +"W- c #D8DFE8", +"X- c #5D5D5E", +"Y- c #797775", +"Z- c #878688", +"`- c #8B8F90", +" ; c #B24E3D", +".; c #C2432D", +"+; c #BF4532", +"@; c #A24435", +"#; c #A24139", +"$; c #A04236", +"%; c #9D3F34", +"&; c #9C423B", +"*; c #A35145", +"=; c #E3CFCB", +"-; c #AD3629", +";; c #B74031", +">; c #A02F21", +",; c #A22F21", +"'; c #9F3022", +"); c #9D2E20", +"!; c #9B2D20", +"~; c #E2EAF4", +"{; c #6491C5", +"]; c #5C8BC1", +"^; c #972721", +"/; c #942821", +"(; c #90281F", +"_; c #84271B", +":; c #86271B", +"<; c #8B281D", +"[; c #942D1F", +"}; c #922B1D", +"|; c #942A1D", +"1; c #952C1F", +"2; c #962E21", +"3; c #962D21", +"4; c #982F22", +"5; c #922E24", +"6; c #984740", +"7; c #AF7570", +"8; c #CAADA8", +"9; c #BED0E6", +"0; c #6893C6", +"a; c #89ABD2", +"b; c #DFE8F3", +"c; c #D9D9D9", +"d; c #3F4343", +"e; c #5F4240", +"f; c #C7432F", +"g; c #C7452C", +"h; c #AF4434", +"i; c #A44237", +"j; c #A34136", +"k; c #9D3F35", +"l; c #993E36", +"m; c #943226", +"n; c #D4B5B3", +"o; c #AF5349", +"p; c #BC4430", +"q; c #A63123", +"r; c #A13123", +"s; c #982921", +"t; c #972820", +"u; c #972A1F", +"v; c #AEC5E0", +"w; c #4B7EBB", +"x; c #8DADD4", +"y; c #962A1F", +"z; c #96291F", +"A; c #95291F", +"B; c #932A1E", +"C; c #A32C24", +"D; c #992B20", +"E; c #962B1E", +"F; c #91291E", +"G; c #952B1D", +"H; c #962D20", +"I; c #972A1D", +"J; c #982C21", +"K; c #982D20", +"L; c #98291E", +"M; c #96271A", +"N; c #B5CAE3", +"O; c #5F8DC3", +"P; c #92B1D5", +"Q; c #E7EEF6", +"R; c #C7ADA9", +"S; c #E7DADA", +"T; c #B75246", +"U; c #C94630", +"V; c #C54832", +"W; c #A84234", +"X; c #A5463C", +"Y; c #A74C41", +"Z; c #AC6157", +"`; c #AD716B", +" > c #9D3F36", +".> c #983F36", +"+> c #9C4032", +"@> c #933F39", +"#> c #D2A4A0", +"$> c #B23423", +"%> c #B23E2E", +"&> c #A12D21", +"*> c #9E2F20", +"=> c #9D3021", +"-> c #9A2B1F", +";> c #97281D", +">> c #972821", +",> c #962920", +"'> c #962A20", +")> c #5082BD", +"!> c #C2D3E8", +"~> c #992D20", +"{> c #98281E", +"]> c #B03125", +"^> c #9E2D22", +"/> c #96281D", +"(> c #902A1C", +"_> c #9B2A20", +":> c #ACC4E0", +"<> c #5687BF", +"[> c #9AB7D9", +"}> c #9B2F23", +"|> c #9E2E21", +"1> c #9B291D", +"2> c #953B30", +"3> c #A7635F", +"4> c #C29693", +"5> c #DBC3C1", +"6> c #EEE4E5", +"7> c #BCBAAF", +"8> c #D0CEC7", +"9> c #E5E4DF", +"0> c #E3CCC8", +"a> c #BF3F29", +"b> c #CA4833", +"c> c #B34536", +"d> c #A44338", +"e> c #B7746D", +"f> c #C4BDBC", +"g> c #9F9C9B", +"h> c #988F8E", +"i> c #8F6661", +"j> c #A35650", +"k> c #9A423B", +"l> c #9E3E33", +"m> c #C9A8A4", +"n> c #A93C30", +"o> c #C34B38", +"p> c #A13022", +"q> c #9B2E20", +"r> c #962B1F", +"s> c #C4D5E8", +"t> c #779ECC", +"u> c #982822", +"v> c #9B3123", +"w> c #963021", +"x> c #A73B2C", +"y> c #BC6B5B", +"z> c #97221B", +"A> c #9B2A1F", +"B> c #992B1F", +"C> c #932B1E", +"D> c #9B2C1F", +"E> c #972A1E", +"F> c #9B2B20", +"G> c #4F81BD", +"H> c #A3BEDC", +"I> c #982D1F", +"J> c #982A1D", +"K> c #98291C", +"L> c #99281C", +"M> c #992C1E", +"N> c #9D372B", +"O> c #A1493E", +"P> c #A86761", +"Q> c #BC9490", +"R> c #D9CAC7", +"S> c #C6C3BD", +"T> c #CACBBB", +"U> c #ACB095", +"V> c #96987E", +"W> c #C8786C", +"X> c #C4432D", +"Y> c #C84734", +"Z> c #A74333", +"`> c #A84A40", +" , c #AE8F8B", +"., c #A2A2A2", +"+, c #9E8D8B", +"@, c #A9A2A2", +"#, c #A88B88", +"$, c #A25349", +"%, c #9A4136", +"&, c #9C4D48", +"*, c #C58981", +"=, c #B43C28", +"-, c #AF3C2C", +";, c #A12D23", +">, c #9A2E20", +",, c #972B1E", +"', c #99291F", +"), c #95291E", +"!, c #992923", +"~, c #8FAFD4", +"{, c #ACC4DF", +"], c #972822", +"^, c #AF3D2F", +"/, c #AE5345", +"(, c #62302E", +"_, c #852E21", +":, c #9F2C21", +"<, c #9C2C20", +"[, c #9D2C20", +"}, c #9D2A20", +"|, c #9A2C21", +"1, c #9BB7D9", +"2, c #9A2A1F", +"3, c #992C1F", +"4, c #992D22", +"5, c #9D2E23", +"6, c #A13023", +"7, c #A02A1E", +"8, c #97271B", +"9, c #973125", +"0, c #A05148", +"a, c #B68279", +"b, c #CFADA8", +"c, c #E4D5D5", +"d, c #807E7E", +"e, c #CBCAC0", +"f, c #A1A586", +"g, c #ACB78B", +"h, c #A4B37C", +"i, c #B1B59A", +"j, c #F5EAE8", +"k, c #B53824", +"l, c #C64531", +"m, c #BB4633", +"n, c #A6463A", +"o, c #C0847D", +"p, c #ADA6A5", +"q, c #9A8C8A", +"r, c #9E5249", +"s, c #A8615A", +"t, c #969190", +"u, c #9F8F8D", +"v, c #A15C53", +"w, c #983E37", +"x, c #9D5852", +"y, c #BAAEAB", +"z, c #AC3023", +"A, c #C14F3D", +"B, c #A42F22", +"C, c #992E21", +"D, c #982C1F", +"E, c #952A21", +"F, c #952A22", +"G, c #952A20", +"H, c #952B1E", +"I, c #942921", +"J, c #952821", +"K, c #DAE4F0", +"L, c #5D8CC2", +"M, c #E0E9F3", +"N, c #982922", +"O, c #8F291F", +"P, c #A42E23", +"Q, c #A32A1F", +"R, c #323E3E", +"S, c #864137", +"T, c #9C281C", +"U, c #A12D22", +"V, c #A02B21", +"W, c #9F2E22", +"X, c #A12C22", +"Y, c #A22D23", +"Z, c #9E2D21", +"`, c #9D2D21", +" ' c #E8EEF6", +".' c #92B1D6", +"+' c #5F8CC2", +"@' c #9C2C21", +"#' c #9A291E", +"$' c #9A2B1E", +"%' c #9D2A1F", +"&' c #9E3125", +"*' c #9D4032", +"=' c #A3554A", +"-' c #B07C74", +";' c #CEB4B5", +">' c #ECE4E3", +",' c #C2C0B6", +"'' c #ADAF97", +")' c #ADB58F", +"!' c #ADBC86", +"~' c #C3D69A", +"{' c #BED097", +"]' c #A6AA8C", +"^' c #C47C70", +"/' c #C6412E", +"(' c #CB4932", +"_' c #AA4737", +":' c #A84339", +"<' c #C5847E", +"[' c #925850", +"}' c #9F4238", +"|' c #A04238", +"1' c #9E7E7B", +"2' c #9D9B9B", +"3' c #8C7270", +"4' c #7F7574", +"5' c #A7A7A7", +"6' c #B43726", +"7' c #B74537", +"8' c #93281E", +"9' c #91271B", +"0' c #94291E", +"a' c #952921", +"b' c #93281F", +"c' c #93291E", +"d' c #942920", +"e' c #942820", +"f' c #A5BFDD", +"g' c #96B4D7", +"h' c #972922", +"i' c #96291E", +"j' c #8F281E", +"k' c #9C2D21", +"l' c #862D23", +"m' c #9C2C22", +"n' c #A22E23", +"o' c #A22C22", +"p' c #A02E20", +"q' c #9D2D22", +"r' c #9F2D22", +"s' c #9D2B20", +"t' c #9D2B21", +"u' c #9D2B22", +"v' c #9B2C22", +"w' c #9A2B21", +"x' c #9A2D22", +"y' c #9A2D1F", +"z' c #A6483E", +"A' c #A13E35", +"B' c #A03023", +"C' c #A13326", +"D' c #AD5950", +"E' c #A86C61", +"F' c #A48571", +"G' c #A8AE89", +"H' c #B2C18D", +"I' c #BBCE93", +"J' c #C2D69A", +"K' c #C6DA9E", +"L' c #B2C28B", +"M' c #848A6A", +"N' c #777575", +"O' c #9D9D9E", +"P' c #B3AFAC", +"Q' c #AB473A", +"R' c #C94935", +"S' c #BB4934", +"T' c #A7433A", +"U' c #AB4D43", +"V' c #99483F", +"W' c #7F7B7B", +"X' c #A04237", +"Y' c #A04138", +"Z' c #9E5048", +"`' c #8B635E", +" ) c #979291", +".) c #979393", +"+) c #826865", +"@) c #A0716C", +"#) c #CEADAA", +"$) c #B13826", +"%) c #B33F2F", +"&) c #AD3A27", +"*) c #AE3C2B", +"=) c #AE3A2E", +"-) c #A73326", +";) c #9D2C21", +">) c #92271F", +",) c #91251D", +"') c #90251D", +")) c #932720", +"!) c #5485BF", +"~) c #CBDAEB", +"{) c #85281B", +"]) c #A12B21", +"^) c #962D1E", +"/) c #A42E24", +"() c #C6D6E9", +"_) c #A43027", +":) c #A22F25", +"<) c #A33228", +"[) c #B55B51", +"}) c #9D3126", +"|) c #BE736B", +"1) c #B96F67", +"2) c #A54A43", +"3) c #A3463F", +"4) c #A04139", +"5) c #C2989A", +"6) c #A05C5C", +"7) c #9D5151", +"8) c #A96A6C", +"9) c #BEACB5", +"0) c #9E6B72", +"a) c #9D727C", +"b) c #AFA7B8", +"c) c #A18998", +"d) c #9E95AB", +"e) c #979AAB", +"f) c #A3A097", +"g) c #B1B89B", +"h) c #A9B486", +"i) c #B6C98E", +"j) c #C4D89C", +"k) c #C3D69B", +"l) c #C4D79C", +"m) c #C7DA9D", +"n) c #ADBC85", +"o) c #999D84", +"p) c #A2A19F", +"q) c #B3B3B5", +"r) c #9D9D9C", +"s) c #8A6D67", +"t) c #BA5E4F", +"u) c #AA4437", +"v) c #B76960", +"w) c #BA9794", +"x) c #947A77", +"y) c #A99A98", +"z) c #B7726B", +"A) c #9E4237", +"B) c #9C4136", +"C) c #9A4035", +"D) c #9A4338", +"E) c #9C5149", +"F) c #93423A", +"G) c #963E35", +"H) c #964C43", +"I) c #AC3829", +"J) c #B44130", +"K) c #AD3A2B", +"L) c #AC3E2C", +"M) c #AD3F2E", +"N) c #AE3D2D", +"O) c #AF3B2B", +"P) c #AB3829", +"Q) c #A63325", +"R) c #93261F", +"S) c #8E241D", +"T) c #8E241C", +"U) c #912521", +"V) c #8E271D", +"W) c #8F271E", +"X) c #8F261E", +"Y) c #4E80BC", +"Z) c #80A5CF", +"`) c #932921", +" ! c #942922", +".! c #8A291B", +"+! c #7D2D20", +"@! c #89281C", +"#! c #8A2A1D", +"$! c #852A1A", +"%! c #932C1F", +"&! c #A12C21", +"*! c #A53228", +"=! c #AB3C34", +"-! c #AA352D", +";! c #A23025", +">! c #CEDCEC", +",! c #789ECC", +"'! c #799FCC", +")! c #CB9B99", +"!! c #A75857", +"~! c #B57777", +"{! c #D5B8BC", +"]! c #C6AEB6", +"^! c #A87980", +"/! c #B2939C", +"(! c #D2DCEA", +"_! c #A3818E", +":! c #BFCCE1", +"~ c #5E8DC2", +",~ c #5083BE", +"'~ c #5686C0", +")~ c #5E8CC3", +"!~ c #5887C0", +"~~ c #5183BE", +"{~ c #4F81BC", +"]~ c #6390C4", +"^~ c #5583BC", +"/~ c #789FCC", +"(~ c #7BA1CE", +"_~ c #7CA1CE", +":~ c #7082AB", +"<~ c #83A4CD", +"[~ c #8DABCF", +"}~ c #979595", +"|~ c #968364", +"1~ c #AAB589", +"2~ c #B9C994", +"3~ c #C0D397", +"4~ c #C4D89D", +"5~ c #B6C691", +"6~ c #B1B09B", +"7~ c #983D30", +"8~ c #A13D2D", +"9~ c #C44836", +"0~ c #AF8F8A", +"a~ c #7C6664", +"b~ c #908B8A", +"c~ c #A85B52", +"d~ c #A24438", +"e~ c #A04235", +"f~ c #9D4136", +"g~ c #9B4136", +"h~ c #993F34", +"i~ c #984034", +"j~ c #963D35", +"k~ c #953E35", +"l~ c #98413B", +"m~ c #91453F", +"n~ c #AD3B2A", +"o~ c #B94432", +"p~ c #AC3A29", +"q~ c #AF3F31", +"r~ c #AE3E2F", +"s~ c #AF3D2D", +"t~ c #AE3F2E", +"u~ c #AE3D2B", +"v~ c #AE3E2D", +"w~ c #B03E2C", +"x~ c #B43E2D", +"y~ c #B44436", +"z~ c #B4584E", +"A~ c #B87876", +"B~ c #7E6E88", +"C~ c #839BC0", +"D~ c #DCDFEA", +"E~ c #916874", +"F~ c #B3B4C7", +"G~ c #AEC0D9", +"H~ c #AAB5CD", +"I~ c #8583A0", +"J~ c #95ACCD", +"K~ c #A5BFDE", +"L~ c #94B3D7", +"M~ c #789CC7", +"N~ c #769CC8", +"O~ c #7FA4CF", +"P~ c #6F99CA", +"Q~ c #749BCB", +"R~ c #608DC2", +"S~ c #BCCFE5", +"T~ c #6692C5", +"U~ c #8BACD3", +"V~ c #4F82BC", +"W~ c #5485BE", +"X~ c #5A8AC1", +"Y~ c #6592C5", +"Z~ c #6F98C9", +"`~ c #759CCC", +" { c #7199C8", +".{ c #7295C3", +"+{ c #97B5D9", +"@{ c #869CC2", +"#{ c #848EAF", +"${ c #A0B1CD", +"%{ c #B0C7E1", +"&{ c #A298AE", +"*{ c #9C7A89", +"={ c #AFA8BA", +"-{ c #ADA0B0", +";{ c #B1878D", +">{ c #B07F84", +",{ c #BE9FA7", +"'{ c #AA6D6E", +"){ c #A85D58", +"!{ c #C9A1A1", +"~{ c #AA524A", +"{{ c #9E4238", +"]{ c #984231", +"^{ c #946B57", +"/{ c #9D9578", +"({ c #ACB88B", +"_{ c #B9CA91", +":{ c #BED194", +"<{ c #C1D599", +"[{ c #C5D99D", +"}{ c #ABB985", +"|{ c #A28F77", +"1{ c #8F2A1C", +"2{ c #B84231", +"3{ c #C6452D", +"4{ c #D9A69F", +"5{ c #AEACAC", +"6{ c #9F6863", +"7{ c #BC7D76", +"8{ c #A6493E", +"9{ c #A14237", +"0{ c #9F4037", +"a{ c #973F33", +"b{ c #973E36", +"c{ c #963F36", +"d{ c #95403A", +"e{ c #943C34", +"f{ c #AB3D2D", +"g{ c #BC4633", +"h{ c #AB3926", +"i{ c #AE3E30", +"j{ c #B23E2F", +"k{ c #B13D2E", +"l{ c #B03F2F", +"m{ c #AF3C2D", +"n{ c #AE3C2C", +"o{ c #AD3D2B", +"p{ c #AE3E2A", +"q{ c #AF3F2B", +"r{ c #B13F2B", +"s{ c #AE4132", +"t{ c #9F4E4C", +"u{ c #8B5B69", +"v{ c #6D6484", +"w{ c #5977A8", +"x{ c #5384BE", +"y{ c #6591C5", +"z{ c #618FC3", +"A{ c #668EC1", +"B{ c #B3C9E2", +"C{ c #93B2D6", +"D{ c #90ADD1", +"E{ c #99ABCA", +"F{ c #A1A3BA", +"G{ c #927E92", +"H{ c #BEC3D4", +"I{ c #BDB8C8", +"J{ c #AD8A95", +"K{ c #A46A72", +"L{ c #C1A8B1", +"M{ c #C1A6AD", +"N{ c #AA4C45", +"O{ c #B3635F", +"P{ c #B26B6A", +"Q{ c #B46765", +"R{ c #AE453C", +"S{ c #BB6158", +"T{ c #B3554D", +"U{ c #A4362D", +"V{ c #AC4439", +"W{ c #B14D43", +"X{ c #A32D21", +"Y{ c #A6362B", +"Z{ c #A83D31", +"`{ c #A32F22", +" ] c #A22E21", +".] c #A12D20", +"+] c #A32F23", +"@] c #A12F1F", +"#] c #9E2F21", +"$] c #96493C", +"%] c #9A826F", +"&] c #A5A88D", +"*] c #AEB890", +"=] c #B5C590", +"-] c #B6C592", +";] c #B0A492", +">] c #A0473A", +",] c #C5452D", +"'] c #CA4733", +")] c #B34833", +"!] c #AB564F", +"~] c #C1908B", +"{] c #A74439", +"]] c #A14236", +"^] c #9C4338", +"/] c #974034", +"(] c #943F38", +"_] c #913E37", +":] c #AB4031", +"<] c #BD4734", +"[] c #AA3825", +"}] c #AF3F30", +"|] c #B04032", +"1] c #AF3F32", +"2] c #B33F30", +"3] c #AE3F2D", +"4] c #AE402F", +"5] c #B23D2D", +"6] c #B23F2C", +"7] c #AF3E2B", +"8] c #AE3F2B", +"9] c #B03E2B", +"0] c #B1402D", +"a] c #B4402A", +"b] c #B53F2E", +"c] c #B23F2D", +"d] c #AE463D", +"e] c #A05A58", +"f] c #996B73", +"g] c #A298AA", +"h] c #AEB3C7", +"i] c #988798", +"j] c #B9BECF", +"k] c #A492A2", +"l] c #A892A1", +"m] c #ABC3DF", +"n] c #9CB8D9", +"o] c #C09DA1", +"p] c #B17978", +"q] c #9C4842", +"r] c #8F352F", +"s] c #B0716C", +"t] c #A4514A", +"u] c #A22D21", +"v] c #A93529", +"w] c #A83228", +"x] c #AB3C31", +"y] c #A52D24", +"z] c #AB3D34", +"A] c #A82E23", +"B] c #A52F23", +"C] c #A53126", +"D] c #A62E23", +"E] c #A72E23", +"F] c #A62D22", +"G] c #A52D22", +"H] c #A32D24", +"I] c #A32C21", +"J] c #A22D24", +"K] c #9F2F20", +"L] c #9D2D1F", +"M] c #9A2C1F", +"N] c #9A4A3B", +"O] c #A28471", +"P] c #ABB092", +"Q] c #ACB88A", +"R] c #9FAA7D", +"S] c #916851", +"T] c #B24737", +"U] c #C6422B", +"V] c #C84934", +"W] c #A74638", +"X] c #AB453B", +"Y] c #A54D40", +"Z] c #A54339", +"`] c #A24337", +" ^ c #A14337", +".^ c #9E4338", +"+^ c #9B4138", +"@^ c #9A4036", +"#^ c #994135", +"$^ c #994035", +"%^ c #963F37", +"&^ c #913E36", +"*^ c #AD4539", +"=^ c #BE4836", +"-^ c #AD3E2F", +";^ c #AF4031", +">^ c #AF4132", +",^ c #AF4130", +"'^ c #AE4130", +")^ c #AF402F", +"!^ c #B23F30", +"~^ c #B13F2F", +"{^ c #B03E2F", +"]^ c #AF412D", +"^^ c #AF3F2D", +"/^ c #AF402D", +"(^ c #AE402C", +"_^ c #AF412C", +":^ c #B04030", +"<^ c #AE3F30", +"[^ c #AF412F", +"}^ c #B13F2C", +"|^ c #B33F2D", +"1^ c #BA402E", +"2^ c #B53B29", +"3^ c #AD3728", +"4^ c #A74335", +"5^ c #A7554A", +"6^ c #9F4E3F", +"7^ c #913029", +"8^ c #6D536C", +"9^ c #5975A7", +"0^ c #8C231D", +"a^ c #90241B", +"b^ c #8E251F", +"c^ c #912621", +"d^ c #922620", +"e^ c #92251F", +"f^ c #8E251E", +"g^ c #89261C", +"h^ c #88281C", +"i^ c #92291E", +"j^ c #9E2A21", +"k^ c #A02D22", +"l^ c #A72C22", +"m^ c #A72E25", +"n^ c #A52F22", +"o^ c #A62C21", +"p^ c #A72E22", +"q^ c #A82D22", +"r^ c #A22F22", +"s^ c #A32E23", +"t^ c #9E2E22", +"u^ c #9E2F22", +"v^ c #994034", +"w^ c #A36E63", +"x^ c #A9998A", +"y^ c #ADAF9A", +"z^ c #B5A397", +"A^ c #C55D4F", +"B^ c #CB482E", +"C^ c #B64837", +"D^ c #A8473B", +"E^ c #A5443A", +"F^ c #A6433A", +"G^ c #A44236", +"H^ c #A14338", +"I^ c #9F4137", +"J^ c #9A4037", +"K^ c #9A4138", +"L^ c #984036", +"M^ c #984037", +"N^ c #964034", +"O^ c #903D33", +"P^ c #AB4A3D", +"Q^ c #C04937", +"R^ c #AF4131", +"S^ c #B04232", +"T^ c #B13F30", +"U^ c #AF4231", +"V^ c #B04130", +"W^ c #B1402F", +"X^ c #B0412E", +"Y^ c #B0412D", +"Z^ c #B0412C", +"`^ c #AF402B", +" / c #B4402F", +"./ c #B03F2C", +"+/ c #B2402D", +"@/ c #B4422E", +"#/ c #B4422D", +"$/ c #B5412D", +"%/ c #B83E2C", +"&/ c #B63E2F", +"*/ c #B24131", +"=/ c #AC3C31", +"-/ c #9C4234", +";/ c #9A4235", +">/ c #913A2D", +",/ c #8C2721", +"'/ c #8A1D19", +")/ c #86221A", +"!/ c #8B251E", +"~/ c #8E2520", +"{/ c #91241F", +"]/ c #90251F", +"^/ c #912720", +"// c #8F241D", +"(/ c #90261D", +"_/ c #8D271D", +":/ c #91271D", +"( c #BB4836", +",( c #A5473A", +"'( c #A44539", +")( c #A34438", +"!( c #A34338", +"~( c #9A4238", +"{( c #994039", +"]( c #984138", +"^( c #943F36", +"/( c #933E37", +"(( c #933F38", +"_( c #903A33", +":( c #B35A51", +"<( c #BE4835", +"[( c #A63324", +"}( c #AF3E30", +"|( c #AD4131", +"1( c #AE4031", +"2( c #B04132", +"3( c #AC4131", +"4( c #AD4231", +"5( c #B04131", +"6( c #B13E2F", +"7( c #AE402E", +"8( c #B5422F", +"9( c #B4422F", +"0( c #B84431", +"a( c #B84330", +"b( c #B94331", +"c( c #BA422C", +"d( c #B6412F", +"e( c #A73C2D", +"f( c #A14335", +"g( c #9A423A", +"h( c #92342A", +"i( c #8C231C", +"j( c #8D211B", +"k( c #8F231E", +"l( c #8F2620", +"m( c #8F251C", +"n( c #93251D", +"o( c #8E251B", +"p( c #8D271B", +"q( c #AC2E25", +"r( c #A52C23", +"s( c #A32E24", +"t( c #A43E2C", +"u( c #C4442B", +"v( c #CA4A32", +"w( c #AA4639", +"x( c #974035", +"y( c #984139", +"z( c #933F35", +"A( c #913F37", +"B( c #903B34", +"C( c #B2635B", +"D( c #BF4A38", +"E( c #A73324", +"F( c #AC4031", +"G( c #AC4030", +"H( c #AD4031", +"I( c #AB412E", +"J( c #AC4230", +"K( c #AD3F2F", +"L( c #AF3F2F", +"M( c #B33D2F", +"N( c #B23D2E", +"O( c #B33E2F", +"P( c #AF3F2E", +"Q( c #B1422D", +"R( c #B4412E", +"S( c #B64430", +"T( c #B74431", +"U( c #B74532", +"V( c #BB4533", +"W( c #B93F2E", +"X( c #B63B28", +"Y( c #B23F32", +"Z( c #AA4738", +"`( c #95382E", +" _ c #923028", +"._ c #902722", +"+_ c #8D211F", +"@_ c #8E211C", +"#_ c #8E231D", +"$_ c #8F251F", +"%_ c #91261E", +"&_ c #95271F", +"*_ c #95251F", +"=_ c #92241D", +"-_ c #8B251C", +";_ c #8A251A", +">_ c #902A1D", +",_ c #97291E", +"'_ c #A42C22", +")_ c #9C2D20", +"!_ c #992C21", +"~_ c #922E1E", +"{_ c #BC4230", +"]_ c #C7452D", +"^_ c #BF4935", +"/_ c #A6453C", +"(_ c #A3453B", +"__ c #A2443A", +":_ c #9C4237", +"<_ c #9B4035", +"[_ c #994134", +"}_ c #973F37", +"|_ c #964036", +"1_ c #944036", +"2_ c #934037", +"3_ c #934039", +"4_ c #8F3B31", +"5_ c #B66E67", +"6_ c #BD4834", +"7_ c #A53223", +"8_ c #AA3E2D", +"9_ c #A9412F", +"0_ c #AA4030", +"a_ c #A93F2F", +"b_ c #AB4131", +"c_ c #AB4030", +"d_ c #AA3F2F", +"e_ c #AA3F2E", +"f_ c #AA3E2C", +"g_ c #AB402E", +"h_ c #AC3E2D", +"i_ c #AA3F2D", +"j_ c #AF402E", +"k_ c #B3402D", +"l_ c #B44531", +"m_ c #B34430", +"n_ c #B74634", +"o_ c #BA452F", +"p_ c #BC4530", +"q_ c #BC4433", +"r_ c #BA402C", +"s_ c #AE3B2B", +"t_ c #A54034", +"u_ c #9D463B", +"v_ c #984131", +"w_ c #922D27", +"x_ c #8E201C", +"y_ c #8E201B", +"z_ c #91251F", +"A_ c #92261D", +"B_ c #90241F", +"C_ c #91261F", +"D_ c #91251E", +"E_ c #8D251D", +"F_ c #84261B", +"G_ c #872619", +"H_ c #8E291D", +"I_ c #982C22", +"J_ c #9C2B21", +"K_ c #A23828", +"L_ c #C0422C", +"M_ c #CA4930", +"N_ c #AC4738", +"O_ c #A4473B", +"P_ c #A7453D", +"Q_ c #A3443A", +"R_ c #A14339", +"S_ c #994136", +"T_ c #943E35", +"U_ c #934137", +"V_ c #914037", +"W_ c #904039", +"X_ c #92433C", +"Y_ c #8E3C32", +"Z_ c #BD7871", +"`_ c #BB4834", +" : c #A43122", +".: c #A93E30", +"+: c #A73E2F", +"@: c #A93F30", +"#: c #A73D2D", +"$: c #A83D2D", +"%: c #AA3E2E", +"&: c #A93E2D", +"*: c #A73D2B", +"=: c #A93F2D", +"-: c #AA3D2D", +";: c #A93C2C", +">: c #A93D2C", +",: c #AA3D2C", +"': c #AA3C2C", +"): c #AA3C2B", +"!: c #A93B2B", +"~: c #AC3E2E", +"{: c #AB3D2C", +"]: c #B3412E", +"^: c #B3412F", +"/: c #B1412F", +"(: c #B4432F", +"_: c #B64330", +":: c #B4432E", +"<: c #B74533", +"[: c #B64532", +"}: c #BA4533", +"|: c #B84737", +"1: c #BE4935", +"2: c #C04430", +"3: c #BD3D2B", +"4: c #B04434", +"5: c #A74535", +"6: c #9C4034", +"7: c #94342B", +"8: c #902F27", +"9: c #8C2722", +"0: c #8B201C", +"a: c #8C211D", +"b: c #8F231C", +"c: c #8F251E", +"d: c #93231E", +"e: c #8E241F", +"f: c #88221D", +"g: c #812218", +"h: c #7F2318", +"i: c #7F251A", +"j: c #87271C", +"k: c #8C2A1E", +"l: c #952A1F", +"m: c #952A1E", +"n: c #B83F2B", +"o: c #C2432B", +"p: c #C14835", +"q: c #A5453D", +"r: c #A34539", +"s: c #A2463C", +"t: c #A14238", +"u: c #A04339", +"v: c #9A4137", +"w: c #983F38", +"x: c #963F35", +"y: c #964037", +"z: c #954138", +"A: c #92413A", +"B: c #93433D", +"C: c #8E3D33", +"D: c #BD867C", +"E: c #A53122", +"F: c #A83E30", +"G: c #A63C2C", +"H: c #A73F2D", +"I: c #A53D2C", +"J: c #A53C2A", +"K: c #A73E2B", +"L: c #A53C29", +"M: c #A73C2C", +"N: c #A63B2B", +"O: c #A93B2C", +"P: c #AA3C2D", +"Q: c #B5412F", +"R: c #B34530", +"S: c #B54532", +"T: c #B54633", +"U: c #B94735", +"V: c #B94733", +"W: c #BB4734", +"X: c #C04636", +"Y: c #BF4334", +"Z: c #B33D29", +"`: c #AE3829", +" < c #A54434", +".< c #A14537", +"+< c #963B33", +"@< c #8C2A22", +"#< c #8C1F1A", +"$< c #8C211B", +"%< c #88251C", +"&< c #8B221C", +"*< c #8A221B", +"=< c #85231A", +"-< c #84231A", +";< c #84241A", +">< c #7E2318", +",< c #7B2219", +"'< c #762215", +")< c #762213", +"!< c #80251A", +"~< c #973120", +"{< c #BE412C", +"]< c #C7472E", +"^< c #B04739", +"/< c #A3463A", +"(< c #A04439", +"_< c #9F453A", +":< c #9D4237", +"<< c #9B4135", +"[< c #994038", +"}< c #954137", +"|< c #96413A", +"1< c #953F38", +"2< c #923F37", +"3< c #923F39", +"4< c #924039", +"5< c #8F3F36", +"6< c #93443E", +"7< c #8F4139", +"8< c #C19089", +"9< c #B74434", +"0< c #A63E30", +"a< c #A53C2D", +"b< c #A63C2B", +"c< c #A53B2B", +"d< c #A43A2A", +"e< c #A53A2B", +"f< c #A53C2C", +"g< c #A53A2A", +"h< c #A83C2B", +"i< c #AA3B2A", +"j< c #AD3E2A", +"k< c #B6432F", +"l< c #B5412E", +"m< c #B84531", +"n< c #B94633", +"o< c #BD4837", +"p< c #BD4933", +"q< c #BD422E", +"r< c #BA3E2D", +"s< c #B83E2F", +"t< c #B04334", +"u< c #A34036", +"v< c #9B3C31", +"w< c #95362D", +"x< c #8D2C25", +"y< c #84211A", +"z< c #811C17", +"A< c #831E17", +"B< c #84221C", +"C< c #81221B", +"D< c #7F2119", +"E< c #7F2219", +"F< c #7E2317", +"G< c #7D211A", +"H< c #741F15", +"I< c #AC3A27", +"J< c #C2412A", +"K< c #C54634", +"L< c #A14639", +"M< c #A5443B", +"N< c #A04537", +"O< c #9E4439", +"P< c #9D4338", +"Q< c #9B4137", +"R< c #954237", +"S< c #97413A", +"T< c #95413A", +"U< c #954139", +"V< c #90403A", +"W< c #90413A", +"X< c #91413A", +"Y< c #94453F", +"Z< c #93463D", +"`< c #C59E96", +" [ c #B44231", +".[ c #A13526", +"+[ c #A2392D", +"@[ c #A73B2D", +"#[ c #A53A2F", +"$[ c #A33C2A", +"%[ c #A13B2A", +"&[ c #A23B29", +"*[ c #A23B28", +"=[ c #A33A29", +"-[ c #A33929", +";[ c #A23927", +">[ c #A43929", +",[ c #A53A29", +"'[ c #A73C2A", +")[ c #A93B2A", +"![ c #AB3E29", +"~[ c #AD3E29", +"{[ c #AE402B", +"][ c #B1422E", +"^[ c #B4412F", +"/[ c #B3402E", +"([ c #B84633", +"_[ c #B84632", +":[ c #BB4835", +"<[ c #BB4832", +"[[ c #BD4833", +"}[ c #B03B2A", +"|[ c #A93B2E", +"1[ c #A44437", +"2[ c #8B3227", +"3[ c #7F211A", +"4[ c #7A1F18", +"5[ c #7B2019", +"6[ c #7B1F16", +"7[ c #7A2016", +"8[ c #792017", +"9[ c #842719", +"0[ c #BE3E2A", +"a[ c #C6422D", +"b[ c #B04632", +"c[ c #9F443B", +"d[ c #A2453A", +"e[ c #9A4236", +"f[ c #9C4339", +"g[ c #9A4139", +"h[ c #954039", +"i[ c #964039", +"j[ c #944139", +"k[ c #94423A", +"l[ c #92423B", +"m[ c #94443D", +"n[ c #91423B", +"o[ c #91433C", +"p[ c #944940", +"q[ c #944843", +"r[ c #B3ADAB", +"s[ c #9B807C", +"t[ c #8C4E41", +"u[ c #963225", +"v[ c #A33321", +"w[ c #A83B2A", +"x[ c #A13C2A", +"y[ c #A03A28", +"z[ c #A33928", +"A[ c #A03728", +"B[ c #A0382A", +"C[ c #A13929", +"D[ c #A33828", +"E[ c #A53929", +"F[ c #A63829", +"G[ c #A43928", +"H[ c #A83A2A", +"I[ c #AB3D2B", +"J[ c #AE3F2C", +"K[ c #B1412D", +"L[ c #B74531", +"M[ c #B74432", +"N[ c #BA4634", +"O[ c #BA4530", +"P[ c #BC412F", +"Q[ c #BB3D2E", +"R[ c #AA4131", +"S[ c #9C3C2C", +"T[ c #90382D", +"U[ c #88342A", +"V[ c #7C281E", +"W[ c #6F1C13", +"X[ c #A03020", +"Y[ c #BE3C29", +"Z[ c #C2462E", +"`[ c #A14638", +" } c #A0463B", +".} c #9F4439", +"+} c #994239", +"@} c #954037", +"#} c #944039", +"$} c #93423B", +"%} c #94443C", +"&} c #93443B", +"*} c #93433C", +"=} c #91453C", +"-} c #944941", +";} c #945046", +">} c #BDC6C4", +",} c #968D8A", +"'} c #8F554E", +")} c #9E3427", +"!} c #A03524", +"~} c #A03828", +"{} c #9F3829", +"]} c #A0392A", +"^} c #9F3828", +"/} c #A73829", +"(} c #A83A29", +"_} c #AD3E2B", +":} c #B74332", +"<} c #B54531", +"[} c #B64832", +"}} c #BD4332", +"|} c #B73B2A", +"1} c #AE382A", +"2} c #A83F2E", +"3} c #983F2F", +"4} c #B83525", +"5} c #BE472F", +"6} c #B34235", +"7} c #9D4737", +"8} c #A1443B", +"9} c #9B4337", +"0} c #984136", +"a} c #974339", +"b} c #964238", +"c} c #96413B", +"d} c #93433B", +"e} c #94453B", +"f} c #92463C", +"g} c #91463D", +"h} c #94473F", +"i} c #93463E", +"j} c #944B43", +"k} c #96564C", +"l} c #B4A8A5", +"m} c #A1756F", +"n} c #8F4235", +"o} c #942D21", +"p} c #A33423", +"q} c #9F3929", +"r} c #9E3827", +"s} c #A2372B", +"t} c #A53728", +"u} c #A43727", +"v} c #A63729", +"w} c #A43927", +"x} c #A63B29", +"y} c #A53B29", +"z} c #A73928", +"A} c #AA3B28", +"B} c #AB3F2C", +"C} c #B0402D", +"D} c #AE402D", +"E} c #B0422E", +"F} c #B3432F", +"G} c #B64230", +"H} c #B5432F", +"I} c #B54230", +"J} c #B64431", +"K} c #B84331", +"L} c #BB4631", +"M} c #A73929", +"N} c #BA402A", +"O} c #C65B4A", +"P} c #A54A3E", +"Q} c #9C4438", +"R} c #9B4236", +"S} c #9A4436", +"T} c #984335", +"U} c #984137", +"V} c #954238", +"W} c #95423A", +"X} c #95453E", +"Y} c #92473F", +"Z} c #93453E", +"`} c #93473F", +" | c #9B6259", +".| c #C0C2BD", +"+| c #A37E7A", +"@| c #965046", +"#| c #9A3C2E", +"$| c #9C331F", +"%| c #9D3623", +"&| c #A03926", +"*| c #9E3828", +"=| c #A03827", +"-| c #A13927", +";| c #A23727", +">| c #AD3E2C", +",| c #B74430", +"'| c #A63A2A", +")| c #BB4731", +"!| c #C14F3B", +"~| c #A04438", +"{| c #9D4539", +"]| c #994436", +"^| c #994238", +"/| c #984334", +"(| c #974137", +"_| c #964338", +":| c #954338", +"<| c #93443A", +"[| c #92473D", +"}| c #954840", +"|| c #914A40", +"1| c #944B42", +"2| c #A86D6C", +"3| c #B49EA0", +"4| c #985E58", +"5| c #913228", +"6| c #9D3020", +"7| c #A3382B", +"8| c #A1392A", +"9| c #A13928", +"0| c #A13827", +"a| c #A33927", +"b| c #B0402C", +"c| c #A23928", +"d| c #BA4532", +"e| c #C04F3B", +"f| c #9C4235", +"g| c #9A4337", +"h| c #984235", +"i| c #974237", +"j| c #954136", +"k| c #974238", +"l| c #944237", +"m| c #944338", +"n| c #954439", +"o| c #93453B", +"p| c #93473D", +"q| c #93483E", +"r| c #91463E", +"s| c #934840", +"t| c #954A41", +"u| c #92493F", +"v| c #B38280", +"w| c #B0A09C", +"x| c #996459", +"y| c #964236", +"z| c #9B3225", +"A| c #A03424", +"B| c #A53828", +"C| c #A23A28", +"D| c #A33A28", +"E| c #A13728", +"F| c #A33827", +"G| c #A5392A", +"H| c #AC3D28", +"I| c #AD3F2B", +"J| c #B03E2A", +"K| c #AF3D2A", +"L| c #B2412D", +"M| c #B13E2B", +"N| c #AF3E2A", +"O| c #B33F2C", +"P| c #9F3728", +"Q| c #B74230", +"R| c #BC4C39", +"S| c #9A4034", +"T| c #994235", +"U| c #934237", +"V| c #944439", +"W| c #95463E", +"X| c #94473D", +"Y| c #92483D", +"Z| c #934941", +"`| c #944A41", +" 1 c #954B43", +".1 c #954D44", +"+1 c #B99190", +"@1 c #C0B8B8", +"#1 c #9C7D74", +"$1 c #904232", +"%1 c #A02F22", +"&1 c #A53B26", +"*1 c #A53C2B", +"=1 c #A13A2B", +"-1 c #A43828", +";1 c #A53A28", +">1 c #AB3E28", +",1 c #AC3D29", +"'1 c #AB3C28", +")1 c #AD3F2A", +"!1 c #B03D2A", +"~1 c #AF3C29", +"{1 c #9E3629", +"]1 c #B5422C", +"^1 c #BB4A36", +"/1 c #963E33", +"(1 c #974134", +"_1 c #954133", +":1 c #954134", +"<1 c #944035", +"[1 c #924337", +"}1 c #934338", +"|1 c #95453F", +"11 c #94463C", +"21 c #93493F", +"31 c #91473E", +"41 c #944A40", +"51 c #954B42", +"61 c #974C45", +"71 c #98514A", +"81 c #924D47", +"91 c #A5807F", +"01 c #9B544B", +"a1 c #9A3628", +"b1 c #9E3121", +"c1 c #A83624", +"d1 c #A63B2D", +"e1 c #A73C2B", +"f1 c #A63A28", +"g1 c #A93B29", +"h1 c #AA3D28", +"i1 c #B03C29", +"j1 c #AD3D29", +"k1 c #AC3F2A", +"l1 c #9E382A", +"m1 c #BA4938", +"n1 c #963D34", +"o1 c #933F36", +"p1 c #934031", +"q1 c #933F34", +"r1 c #934032", +"s1 c #95453A", +"t1 c #96483E", +"u1 c #964941", +"v1 c #954940", +"w1 c #954A42", +"x1 c #974D44", +"y1 c #95463D", +"z1 c #B19E9D", +"A1 c #965952", +"B1 c #9D352A", +"C1 c #A53A25", +"D1 c #AA3D2A", +"E1 c #A73E2C", +"F1 c #AA3C29", +"G1 c #A93C28", +"H1 c #A73B29", +"I1 c #A83D2A", +"J1 c #AB3C2A", +"K1 c #AA3B27", +"L1 c #AC3C28", +"M1 c #B64735", +"N1 c #923C32", +"O1 c #923E34", +"P1 c #923E33", +"Q1 c #94443A", +"R1 c #96463D", +"S1 c #97473E", +"T1 c #96493D", +"U1 c #94483F", +"V1 c #984C44", +"W1 c #954E43", +"X1 c #B5A4A2", +"Y1 c #A36E67", +"Z1 c #9B4737", +"`1 c #9F3327", +" 2 c #A93425", +".2 c #AA3B2C", +"+2 c #A93C2A", +"@2 c #AA3D29", +"#2 c #9F3727", +"$2 c #B5402C", +"%2 c #B54635", +"&2 c #913C33", +"*2 c #913E33", +"=2 c #943F35", +"-2 c #934035", +";2 c #95453B", +">2 c #974840", +",2 c #984A44", +"'2 c #994B43", +")2 c #994F45", +"!2 c #94443E", +"~2 c #C3C0BE", +"{2 c #9C7B73", +"]2 c #964437", +"^2 c #AB3D28", +"/2 c #A63D2A", +"(2 c #A93A29", +"_2 c #AC3D2A", +":2 c #A93A26", +"<2 c #A83925", +"[2 c #A73C27", +"}2 c #A13726", +"|2 c #B4412C", +"12 c #B14533", +"22 c #8F3B33", +"32 c #913D33", +"42 c #934136", +"52 c #97473C", +"62 c #96463C", +"72 c #98493F", +"82 c #974A43", +"92 c #984C40", +"02 c #97503F", +"a2 c #AF8C87", +"b2 c #9E5A50", +"c2 c #99382A", +"d2 c #AB3523", +"e2 c #AE3D2C", +"f2 c #AC402E", +"g2 c #AA3C27", +"h2 c #AA3A2C", +"i2 c #AA3C28", +"j2 c #A23825", +"k2 c #B4402C", +"l2 c #AD4332", +"m2 c #923D34", +"n2 c #934036", +"o2 c #924136", +"p2 c #96463E", +"q2 c #994940", +"r2 c #964B41", +"s2 c #9B4F44", +"t2 c #95483D", +"u2 c #A89892", +"v2 c #965D53", +"w2 c #A33D30", +"x2 c #AC3C30", +"y2 c #A73D29", +"z2 c #AB3C2C", +"A2 c #AB3C29", +"B2 c #A63928", +"C2 c #A03825", +"D2 c #B4412D", +"E2 c #AB422F", +"F2 c #8F3E34", +"G2 c #913F34", +"H2 c #924338", +"I2 c #96463B", +"J2 c #984741", +"K2 c #974A40", +"L2 c #994D43", +"M2 c #964C40", +"N2 c #BBACAA", +"O2 c #A17367", +"P2 c #924030", +"Q2 c #A73322", +"R2 c #AE3A28", +"S2 c #AB3F2A", +"T2 c #AC3D2B", +"U2 c #AB3C27", +"V2 c #AA3927", +"W2 c #A93B27", +"X2 c #A93A27", +"Y2 c #A63827", +"Z2 c #A33B28", +"`2 c #B2402E", +" 3 c #A8442F", +".3 c #984942", +"+3 c #994D44", +"@3 c #987067", +"#3 c #9C483C", +"$3 c #A93927", +"%3 c #AB3B2A", +"&3 c #AA3B29", +"*3 c #A83C28", +"=3 c #A93C27", +"-3 c #A64232", +";3 c #914035", +">3 c #96473B", +",3 c #994A3F", +"'3 c #984C3F", +")3 c #A68E87", +"!3 c #924F45", +"~3 c #9B3224", +"{3 c #AF3728", +"]3 c #AF3E29", +"^3 c #AC3E30", +"/3 c #A9392A", +"(3 c #AB3A28", +"_3 c #A63C28", +":3 c #A83C27", +"<3 c #AA3B26", +"[3 c #A43A27", +"}3 c #A73D2A", +"|3 c #B7422F", +"13 c #A74232", +"23 c #944238", +"33 c #924237", +"43 c #984A3C", +"53 c #994B42", +"63 c #9C4C42", +"73 c #9C8C87", +"83 c #995852", +"93 c #9D3D30", +"03 c #A63927", +"a3 c #A93B25", +"b3 c #AA3A27", +"c3 c #AB3E2C", +"d3 c #B5442D", +"e3 c #A64436", +"f3 c #924339", +"g3 c #97453A", +"h3 c #98463B", +"i3 c #98483D", +"j3 c #99493D", +"k3 c #946B61", +"l3 c #8D3D2D", +"m3 c #A93727", +"n3 c #B33E2C", +"o3 c #AB3F2B", +"p3 c #AB3E2A", +"q3 c #AC3E28", +"r3 c #AA3C2A", +"s3 c #AD3F2D", +"t3 c #B74630", +"u3 c #A44537", +"v3 c #95463B", +"w3 c #98483F", +"x3 c #984A3B", +"y3 c #994C43", +"z3 c #98736A", +"A3 c #9B5042", +"B3 c #A33B2B", +"C3 c #AC3724", +"D3 c #B03D2B", +"E3 c #AD402C", +"F3 c #AD3D2A", +"G3 c #B94832", +"H3 c #A6483B", +"I3 c #99493E", +"J3 c #9C4E46", +"K3 c #A58D89", +"L3 c #894D43", +"M3 c #9D392C", +"N3 c #B53E2A", +"O3 c #B14430", +"P3 c #AE422E", +"Q3 c #A63E2E", +"R3 c #B24533", +"S3 c #BC4A35", +"T3 c #A34A3B", +"U3 c #994B40", +"V3 c #9A635C", +"W3 c #9D4434", +"X3 c #9E3A28", +"Y3 c #B24630", +"Z3 c #BB4936", +"`3 c #A44D3E", +" 4 c #9E5045", +".4 c #B64634", +"+4 c #BD503E", +" . + @ # $ % ", +" & * = - ; ; > , ' ) ! ", +" ~ { ; ; ; ; ; ] ^ / ( _ : < ", +" [ } ; ; ; ; ; ; , | | | 1 2 3 4 5 ", +" < 6 ; ; ; ; ; ; 7 8 | | | | | 9 + _ 0 a ", +" b c d ; ; ; ; ; e f | | | | | | | | g h i ", +" j k l m n ; ; ; o p | | | | | | | | | a q r ! ", +" / s | t u v ; ; w | | | | | | | | | | + x y i ", +" z A | | | | B C x A | | | | | | | | | ^ D ; ; q a ", +" E 4 | | | | | | F G | | | | | | | | | 8 H ; ; ; I ", +" J K | | | | | | L M s N | | | | | | 5 ] ; ; ; ; O P ", +" Q ' | | | | | | : y ; R : | | | | | S ; ; ; ; ; T U ", +" V r | | | | | | # ; ; ; x h W | | X Y ; ; ; ; ; Z ` ", +" A p | | | | ! .; ; ; ; ; ] ..| +.; ; ; ; ; ; n @. ", +" F #.| | | | N $.; ; ; ; ; ; > %.&.; ; ; ; ; ; *.. ", +" < _ =.| | | Q -.; ; ; ; ; ; y ;.: .; ; ; ; ; >.=. ,.'.).!. ", +" ~.$ ^ | | {.; ; ; ; ; ; ; .p | / {.].; ; ; ^.! /.(._.:.<.[.}.|. ", +" #._ B 6 ; ; ; ; ; ; 1.2 | | | | 2.3.4.; 5. 6.7.8.9.0.a.b.c.d.e.f. ", +" X z G g.; ; ; ; ; ; h.i.| | | | | 1 G j.k. l.m.n.o.p.q.r.s.t.u.v.w.x. ", +" y.z.A.B.; ; ; C.D.| | | | | | ;.E. F.G.H.I.J.K.L.M.N.O.P.Q.R.S. ", +" T.U.V.H ; W.| | | | | | X.# Y. Z.`. +.+++@+#+$+%+&+*+=+-+;+>+ ", +" ,+'+)+!+J ~+;.^ | | | {+]+h ^+t /+(+_+:+<+[+}+|+1+2+3+4+5+6+7+8+ ", +" 9+0+a+ b+( r c+5.%._ d+ e+f+g+h+i+j+k+k+l+m+n+o+p+q+r+s+t+ ", +" u+v+w+ U x+X y+ z+A+B+C+D+|+E+E+F+G+H+I+J+K+L+M+N+ ", +" O+P+Q+R+ S+T+U+V+W+X+Y+Z+`+ @.@+@@@#@$@%@&@ ", +" *@=@-@ ;@>@,@'@)@!@~@{@n+]@^@/@(@_@:@<@[@ ", +" }@|@1@2@ 3@4@5@6@3+7@8@9@0@a@b@c@d@e@f@g@ ", +" 9 h@P i@j@k@ l@m@n@=+o@p@q@r@s@t@u@v@w@x@y@z@ ", +" ^ A@W.B@G Y.: k. C@D@E@ F@G@H@-+I@J@K@L@u@M@N@w@O@P@Q@ ", +" + Y.z.R@ | 9 S@$ @ d+T@U@V@ W@X@Y@Z@`@ #.#d@d@+#@#O@##$#%# ", +" 8 &#l | | | | | | *#4.=#-#;#># ,#j@'#)#!#~#{#]#^#^#O@/#(#_#:# ", +" ` {.<#| | | | | | [#}#; ; ; |#1#E.^ 2#3#=@'#4# 5#6#7#8#9#0#a#b#c#d# ", +" e#4 | | | | | | | f#; ; ; ; ; ; > g#) h# i#j#=@Q+k# l#m#n#o#p#q# ", +" F H ].r#y.| | | | ~.].; ; ; ; ; ; ] {+s#t#.. u#v#=@w#x# ", +" y#; ; 4.R K | | | z#; ; ; ; ; ; ; f#| | h#A#B# x#w#=@v#C# ", +" D#< v ; ; ; ; 1.E#F#G#-.; ; ; ; ; ; H 2 | | | y.G H# I#J#=@K#L# ", +" M#N#O#P#W T ; ; ; ; ; ; }#z#7 ; ; ; ; ; ; = Q#| | | | R#F 4#S#=@3#}@ ", +" T#U#V#W#X#Y#; ; ; ; ; ; Z#h#z.&.; ; ; ; ; v H#| | | | X.A `# $.$=@,# ", +" +$@$#$$$%$R@x ; ; ; ; ; *.b | | ` z#y ; ; ; &#| | | | | | &$Q# *$=$-$;$>$,$'$ )$!$0+~$ ", +" {$]$^$/$($x+T ; ; ; ; ; _$| | | | ! :$<$; ; [$| | | | | | }$: |$1$2$3$4$5$6$7$8$9$0$ a$b$c$d$ ", +" e$f$g$h$i$j$t R ; ; ; ; $.k$| | | | | | s#l$C.% | | | | | | Q E m$n$o$p$q$V+r$s$t$u$v$w$x$y$z$A$ ", +" B$C$D$E$F$G$H$I$Y.; ; ; ; # | | | | | | | | i.t#J | | | | | | ) G J$K$L$M$K.N$O$P$Q$R$S$T$U$V$W$9+ ", +" X$Y$Z$`$ %.%+%@%R@M ; ; M & | | | | | | | | | #%$%r#%%| | | | c+:$ &%*%M$=%-%#+;%1+>%,%'%)%!%~%{% ", +" ]%^%/%(%_%:%<%[%}%|%_ ; ; ^+| | | | | | | | | | e#; ; R K {.| | r#X#u Q [#1% 2%3%4%-%5%6%E+Y+7%8%9%0%a%b%c%d% ", +" e%f%g%(%h%i%j%k%l%m%h#* $%. | | | | | | | | | h@{ ; ; ; Y#n%o%%%B@A#p%&$+.q%r%s%t%u%v%w%#+6%k+}+Y+x%y%z%A%B%C%D%E% ", +" F%G%H%I%J%K%L%K%M%N%O%P%1 h r#a | | | | | | | | =.<$; ; ; ; ; Q%R%c+u 4 8 c+0 S%T%U%V%q$W%X%E+}+Y%Z%`% &q@.&+&@&#&$& ", +" %&&&*&=&-&-&;&;&L%>&,&'&)&!&) ^+t#X#| | | | | | [ Z ; ; ; ; ; ; ~&N g#}$8 u 4 {&]&^&/&(&_&:&Y+Y+Z%<&[&}&|&1&2&3&4&5& ", +" 6&7&8&9&0&a&b&c&d&e&f&e&g&h&i&j&k&l&m&n&o&| | | | [$; ; ; ; ; ; p&q&n%r&s&Z#s t&u&v&w&x&y&z&A&B&x%`%[&C&D&E&F&G&x@H&I&) [#J& ", +" K&L&M&N&O&P&Q&R&S&T&U&V&W&X&Y&Z&`& *.*+*@*#*A E.P | m ; ; ; ; ; d q& X.` $ $*%*&*).**=*-*;*>*7@y%,*D&'*)*!*~*{*]*^*j /*f## S : s#k.^ (*_*:* ", +" <*[*}*|*1*c&2*T&3*4*U&5*6*7*8*9*0*a*b*=@c*d*e*u *#5.Y ; ; ; y f*Q g*h*i*j*k*l*p@z%m*n*)*o*:@x@W p*K #.c+0 t#_ *#Y.$*$*r t#q*[#H# r*s*t*u*v*w* ", +" x*y*z*A*c&c&2*A*A*B*C*D*D*E*F*G*H*F*R+I*J*K*L*M*N*< J e#O*P*' ) y+ Q*R*S*T*U*0%V*K+W*X*:@Y*Z*`* =z F q&#%#.R#q&R#u $ ;.A r .=C /*p%z D.a += @=#=$=%=&=*= ", +" ==-=;=>=c&2*,=,='='=)=!=~={=]=^=/=/=(=0+_=:=<=[=}=|=1= 2=3=4=5=6=a% #L+:@^#7=8=9=6#0=a=+.t#8 F F R#R##.2 F K q&u $ g#_ @ Y.B@b=c=d=e=f=g=h=i=j= ", +" k=l=m=n=o=A*p=q=r=s=t=D*u=v=v=]=w=x=y=z=0+4#A=B=C=D=E=F=G= H=I=J=K=L=M=b%{#/#/#N=O=P=Q=R=V S=z._$T=U=h.B@p%( 2 : A@2 V=R#q&2 K V=8 W=X=Y=Z=`= -.-+-@- ", +" #-$-%-&-*-A*=-,=--!=;-;-G*v=v=x=]=x=x=>-,-'-)-!-~-B={-]-v=^-/-(-_-:-<- [-}-=@|-1-2-3-4-5-6-5-7-8-9-0- H#~.I a-T=b-~+C A E K ..K V=c-d-e-f-g-h-i-j-k-.-l-m- ", +" n-o-p-2*q-o='=r-!=;-!=s-t-t-]=u-v=u-x=v-=@w-x-y-z-A-{-B-C-G*D-E-F-G-H-I-J-K-L-M- N-O-=@P-Q- R-o#S-T-U-V-W- 5 % 8 .=r&R D X-Y-Z-`- ;.;+;@;#;$;%;%;&;*; ", +" =;-;;;>;,;';);!;!=!=!=;-;-;-;-u=]=x=x=~;{;];H=^;/;(;_;:;<;[;};|;|;1;/=2;3;4;9*]=5;6;7;8;9;0;=@a;b; c;k ;.&#d;e;f;g;h;i;j;$;k;k;l;m;n; ", +" o;p;q;r;A*,=!;!=;-!=;-;-;-s;t;u;]=x=x=v;w;x;y;z;A;B;C;D;E;F;G;u-]=t-H;x=I;t-D-J;K;L;M;N;O;=@P;Q;R;S; T;U;V;W;X;Y;Z;`; >.>+>@> ", +" #>$>%>&>*>=>r=->u=!=;-!=L;;>>>s;,>x=u;'>}-)>!>x=~>{>]>^>/>K;(>_>v=v=]=D-v=G*G*t-u;/=v=:><>j@[>}>|>1>y;2>3>4>5>6> 7>8>9> 0>a>b>c>d>e>f>g>h>i>j>k>l>m> ", +" n>o>r;p>q>t-;-w=v=!=!=;-!=;-r>x=u-x=>>s>y$t>u>v>w>x>y>z>A>B>C>D>!=v=E>v=v=v=B>F>r-]=w-D@G>H>]=G*]=r>I>J>K>L>M>N>O>P>Q>R> S>T>U>V> W>X>Y>Z>`> ,.,+,@,z #,$,%,&, ", +"*,=,-,;,>,,,',]=v=y;u-]=x=x=x=x=u-),x=!,~,=@{,],D>u-^,/,(,_,A>E;:,<,[,<,r-},t=|,~=!=1,j@<>{,;-;-;-2,!=;-t=3,{=G*4,5,6,7,8,9,0,a,b,c,d, e,f,g,h,i, j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,:$E ", +"z,A,B,C,D,L;L;E,F,G,D-H,E,I,I,F,J,J,J,K,L,'#M,N,w=O,P,Q,R,S,T,w=U,V,W,W,X,Y,Z,`, '.'=@+'N;@'F>2,F>!=->!=;-!=;-t=!=--!=B>!=->#'$'%'&'*'='-';'>' ,''')'!'~'{']' ^'/'('_':'<'z ['}'|'1'2'l 3'4'5'R#r ", +"6'7'&-s-8'9'0'F,a'b'c'0'd'd'I,x-e'a'/;f'=@g''>h'i'j'k'*-l'2,m'~>n'V,o'Y,Y,X,p'b;a;=@|@9;q'r'k's't'u'k'r-v'w'r=F>!=!=!=;-!=x'!=t=y'z'A'B'C'D'E'F'G'H'I'J'K'L'M'N'O'P'Q'R'S'T'U'V'W'X'Y'}'Z'`' ).)+)@)#) ", +"$)%)&)*)=)-);)>),)')x->)x-x->)x-x-)),+'+!)~)J,J,,,J,{)])B>_>`,^)U,o'Y,X,/)Y,Q-P-=@'+()X,_):)o'Y,<)[)})|>|)1)2)3)q'4)5)6)7)8)9)0)a)b)c)d)e)f)g)h)i)j)k)l)m)n)o)p)q)r)s)t)u)v)w)x)y)z).-A)B)C)D)E)F)G)H) ", +"I)J)K)-,L)M)N)O)P)Q)|,R)S)T)U)V)W)X)9+Y)Z)`)I,F, !x=.!+!@!#!$!%!&!*!=!-!;!>!,!=@'![-)!!!~!{!]!^!/!(!_!:!~,~'~)~!~~~{~P+]~I*P+^~/~(~_~:~<~[~}~|~1~2~3~~'4~l)j)5~6~7~8~9~0~p%a~b~@.c~d~e~f~g~g~h~i~j~u!k~l~m~", +"n~o~p~q~r~r~H%s~N)t~D!u~v~w~x~y~z~A~B~C~D~E~F~G~H~I~J~K~L~M~N~O~P~Q~R~S~T~=@U~M,V~W~S#P+U@X~Y~Z~`~ {.{x;+{@{#{${%{&{*{={-{;{>{,{'{){!{~{{{]{^{/{({_{:{<{[{}{|{1{2{3{4{5{[ 6{7{8{9{X'0{B)C)C)a{b{u!c{d{e{", +"f{g{h{i{q~i{j{k{l{D!t~t~m{n{E!o{p{q{r{s{t{u{v{w{x{,-S#U@=@X~y{Y~z{A{B{L,=@C{R+D{E{N;F{G{H{I{J{K{L{M{N{O{P{Q{R{S{T{U{V{W{X{X{Y{Z{`{ ].]+]@]#]E*$]%]&]*]=]I'-];]>],]'])]!]~]{]d>]]j-|'^]C)h~h~/]b{G)c{(]_]", +":]<][]}]}]|]1]j{2]j{j{3]4]M)M)5]6]7]8]9]0]a]b]c]d]e]f]g]h]i]j]k]l]m],-j@n]o]p]q]r]s]t]u]v]w]x]y]z]A]B]C]D]E]F]E]F]F]G]u]X{X{X{H]I]P,])J].]K]L]M]s-N]O]P]Q]R]S]T]U]V]W]X]Y]Z]`] ^j-.^+^@^C)#^$^%^k~k~(]&^", +"*^=^[]-^;^>^>^,^'^)^k{j{!^~^{^]^^^/^(^_^/^:^<^[^}^|^1^2^3^4^5^6^7^8^9^f'0^a^b^c^d^e^f^g^h^i^j^k^l^m^n^o^F]E]E]D]o^A]E]p^q^E]F]o^r^s^Y,;,o't^u^q>;-^=v^w^x^y^z^A^B^C^D^E^F^G^`]H^I^A)J^K^L^M^N^c{k~k~(]O^", +"P^Q^}*;^>^>^>^R^S^R^T^l{4]U^,^V^~^W^X^Y^/^Y^Z^`^ /./+/@/#/$/%/&/*/=/-/;/>/,/'/)/!/~/{/]/^///(/_/:/A-9/0/a/b/c/d/e/f/g/h/i/j/j/A)B)k/l/m/n/o/p/q/(]r/s/", +"t/u/v/w/>^>^x/y/s{z/A/B/,^C/C/)^j{D/E/Y^Y^F/F/E/./+/+/0]G/H/I/J/K/L/M/N/-,O/P/Q/R/S/T/U/V/W/X/Y/R)/;Z/`/ (.(~>+(@(|/#(}/D]6/E]$(G]%(o'o'&(`,t^*(~>K;G*D-B;=(-(;(>(,('()(!(|'|'A)B)C)~(l/{(](k~p/^(/(((_(", +":(<([(}(|(1(2(3(3(4(5(,^,^,^,^:^6(T^Z^8]F/Y^Y^F/t~)^7([^)^F/+/8(8(K/9(0(a(b(c(d(5]e(f(g(h(i(j(k(]/l(m(R),)n(X/X)o(p(^-&>q(E]F]r(s(X,o'V,r't^<,!;^=/=/=H,e^t(u(v(w({$)( ^j-}'A)B)C)#^L^x(y(c{k~z(q/r/A(B(", +"C(D(E(F(G(3(3(3(H(1(I(J(,^t~4]4]7(4]K(M)L(4]4])^M(k{2]N(O(P(Q(Y^]^R(8(R(S(T(z!T(U(V(W(X(Y(Z(9{`( _._+_@_#_$_%_%_&_*_=_-_;_>_,_r=k^G]'_&![,)_|,v'~>!_]=x=~_{_]_^_X;/_(___|'H^:_<_C)#^[_}_|_1_z(1_2_2_3_4_", +"5_6_7_8_9_0_a_b_c_c_d_3(e_f_g_h_M)M)h_i_h_h_h_f{D!t~D!D!4]j_8]F/Y^6]8(k_k_R(8(I/l_m_0(n_o_p_q_r_s_t_u_v_w_x_y_z_,)A_B_e^C_%_D_E_F_G_H_I_m'J_F>!=D-D-D-9/K_L_M_N_O_P_Q_R_i/<_g~S_{(o/c{c{T_z((]U_V_W_X_Y_", +"Z_`_ :.:+:@:a_#:$:%:d_#:&:*:=:-:;:>:,:*:':f{):!:~:':~:{:{:t~/^/^(^0]+/0]+/]:]:^:/:(:_:::<:[:}:|:1:2:3:o-4:5:6:7:8:9:0:a:b:c:X)d:$_e:f:g:h:i:j:k:l:/=K;m:n:o:p:q:r:s:t:u:g~J^v:@^w:x:y:v!y:z:((3_A:W_B:C:", +"D:}:E:.:F:F:#:G:H:I:G:G:J:K:L:x>M:N:M:N:O:P:P:O:P:P:':):):{:D!t~8]8]F/8]Y^Y^^:k_k_8(k_Q:m_R:T(S:T:U:V(V:W:X:Y:Z:`: <.<+<@<#<$<%<&<*<*<=<-<;<><,<'<)[g[g<>[,['[)[):{:{:~:![F!~[{[`^F/F/][X^^[/[^[8(8(8(8(8(T(T(T(T(T(M&([_[&&:[<[[[r_}[|[1[[_2[3[4[5[6[7[8[9[0[a[b[c[d[_[-[D[E[F[>[G[G[H[)[)[)[)[I[):D!E!D!/^J[Y^Y^K[+/6]R(R(8(8(8(_:_:T(T(T(T(L[U([:T(M[n},}'}v<)}!}~}{}]}^}-[:%-[-[K_:%:%~}:%D[>[>[/})[(})[)[)[8&8&D!C!_}8]8]Y^8]}^6]+/k_k_k__:8(_:_:_:_:_:T(8(8(8(T(_:_:R:[*:}<}[}p_}}|}1}2}3}4}5}6}7}8}P<^]9}e[0}](n/a}b}c}j[X_l[d}e}f}g}h}i}j}k}", +" l}m}n}o}p},[q}^}r}s}K_K_:%t}K_K_u}D[v}w}w}x}y}z})[8&8&8&A}_}_}B}C}D}D}F/E}+/F}][l[-[D[>[g|j[G|z}(})[)[):):(})[)[8&E!H|j1j<,1j<,1j<'1j2,2'2)2!2 ", +" ~2{2]2D[^2/2h_{:h_h_):(2i<(2_2'1j<,1,1'1'1:2K1K1:2K1'1:2K1K1K1<2'1K1'1:2[2}2|2122232O1z(1_=242n|V|V|526272829202 ", +" a2b2c2d2e2f2>:D1g2h2i2'1'1,1j352,3'3 ", +" )3!3~3{3]3^3/3(3_3:3'1'1K1:2'1:2<3&3,1[3}3|3132333V|V|I252435363 ", +" 73839303a3}[j<'1A2,1'1'1b3_2i2j #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_TrackingTimer = new QTimer(this); + 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_TrackingTimer->stop(); +m_TrackingLoggingTimer->stop(); +m_TrackingRenderTimer->stop(); m_TimeoutTimer->stop(); -delete m_TrackingTimer; +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_TrackingTimer, SIGNAL(timeout()), this, SLOT(UpdateTrackingTimer())); + 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())); //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); //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::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::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_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; } - m_TrackingTimer->start(1000/(m_Controls->m_UpdateRate->value())); + if(m_Controls->m_UseDifferentUpdateRates->isChecked()) + { + 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->SetOperationMode(mitk::NavigationDataToIGTLMessageFilter::ModeSendTDataMsg); + m_IGTLConversionFilter->ConnectTo(m_ToolVisualizationFilter); + 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"); this->GlobalReinit(); } void QmitkMITKIGTTrackingToolboxView::OnStopTracking() { if (!m_tracking) return; - m_TrackingTimer->stop(); + 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); + //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::UpdateTrackingTimer() +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 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::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() +{ + MITK_INFO << "tooooooggle"; + if(m_Controls->m_UseDifferentUpdateRates->isChecked()) + { + 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_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); + } + + return; +} + 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; } 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; } } } void QmitkMITKIGTTrackingToolboxView::OnAddSingleTool() { QString Identifier = "Tool#"; if (m_toolStorage.IsNotNull()) Identifier += QString::number(m_toolStorage->GetToolCount()); else Identifier += "0"; m_Controls->m_NavigationToolCreationWidget->Initialize(GetDataStorage(),Identifier.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_UpdateRate->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); } void QmitkMITKIGTTrackingToolboxView::EnableOptionsButtons() { m_Controls->m_ShowTrackingVolume->setEnabled(true); - m_Controls->m_UpdateRate->setEnabled(true); m_Controls->m_ShowToolQuaternions->setEnabled(true); - m_Controls->m_OptionsUpdateRateLabel->setEnabled(true); + m_Controls->m_UseDifferentUpdateRates->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 bda4538556..1040efd66e 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxView.h @@ -1,283 +1,295 @@ /*=================================================================== 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); virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); virtual void StdMultiWidgetNotAvailable(); 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(); /** @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 UpdateTrackingTimer(); + void UpdateRenderTrackingTimer(); + void UpdateLoggingTrackingTimer(); /** @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 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_TrackingTimer; + 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 f3efcbc667..dd5ac69955 100644 --- a/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui +++ b/Plugins/org.mitk.gui.qt.igttracking/src/internal/QmitkMITKIGTTrackingToolboxViewControls.ui @@ -1,615 +1,741 @@ QmitkMITKIGTTrackingToolboxViewControls 0 0 - 292 - 592 + 312 + 516 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 120 0 Connect Qt::Horizontal 40 20 120 0 Start Tracking Qt::Vertical 20 40 Options - + - - - true - - - Show Tracking Volume - - - true - - - - - - - Select Model: - - - - - - - - - - Qt::Horizontal - - - - - - - - - Update Rate (Times Per Second) - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - 999 - - - 10 - - - - - - - - - Show Tool Quaternions + + + Tracking Volume Options + + + + + true + + + Show Tracking Volume + + + true + + + + + + + Select Model: + + + + + + + - - - Caution, only for backward compatibility: + + + 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 + + + + + + - - - Inverse mode (Quaternions are stored inverse) + + + Other Options + + + + + Show Tool Quaternions + + + + + + + Enable Open IGT Link MicroService + + + true + + + + + + + Caution, only for backward compatibility: + + + + + + + Inverse mode (Quaternions are stored inverse) + + + + Qt::Vertical 20 - 597 + 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