diff --git a/Modules/IGT/Algorithms/mitkNavigationDataEvaluationFilter.cpp b/Modules/IGT/Algorithms/mitkNavigationDataEvaluationFilter.cpp index 4fcef91f9c..89ec5d87a7 100644 --- a/Modules/IGT/Algorithms/mitkNavigationDataEvaluationFilter.cpp +++ b/Modules/IGT/Algorithms/mitkNavigationDataEvaluationFilter.cpp @@ -1,314 +1,302 @@ /*=================================================================== The Medical Imaging Interaction Toolkit (MITK) Copyright (c) German Cancer Research Center, Division of Medical and Biological Informatics. All rights reserved. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See LICENSE.txt or http://www.mitk.org for details. ===================================================================*/ #include "mitkNavigationDataEvaluationFilter.h" #include #define _USE_MATH_DEFINES #include mitk::NavigationDataEvaluationFilter::NavigationDataEvaluationFilter() -: mitk::NavigationDataToNavigationDataFilter() + : mitk::NavigationDataToNavigationDataFilter() { - } - mitk::NavigationDataEvaluationFilter::~NavigationDataEvaluationFilter() { - } void mitk::NavigationDataEvaluationFilter::GenerateData() { + this->CreateOutputsForAllInputs(); // make sure that we have the same number of outputs as inputs + this->CreateMembersForAllInputs(); - this->CreateOutputsForAllInputs(); // make sure that we have the same number of outputs as inputs - this->CreateMembersForAllInputs(); - - /* update outputs with tracking data from tools */ - for (unsigned int i = 0; i < this->GetNumberOfOutputs() ; ++i) + /* update outputs with tracking data from tools */ + for (unsigned int i = 0; i < this->GetNumberOfOutputs(); ++i) + { + //first copy outputs to inputs + mitk::NavigationData* output = this->GetOutput(i); + assert(output); + const mitk::NavigationData* input = this->GetInput(i); + assert(input); + if (input->IsDataValid() == false) { output->SetDataValid(false); } + else { output->Graft(input); } + + //then save statistics + if (input->IsDataValid()) { - //first copy outputs to inputs - mitk::NavigationData* output = this->GetOutput(i); - assert(output); - const mitk::NavigationData* input = this->GetInput(i); - assert(input); - if (input->IsDataValid() == false) {output->SetDataValid(false);} - else {output->Graft(input);} - - //then save statistics - if(input->IsDataValid()) - { - m_LoggedPositions[i].push_back(input->GetPosition()); - m_LoggedQuaternions[i].push_back(input->GetOrientation()); - } - else - { - m_InvalidSamples[i]++; - } + m_LoggedPositions[i].push_back(input->GetPosition()); + m_LoggedQuaternions[i].push_back(input->GetOrientation()); } - + else + { + m_InvalidSamples[i]++; + } + } } void mitk::NavigationDataEvaluationFilter::CreateMembersForAllInputs() { - while(this->m_LoggedPositions.size() < this->GetNumberOfInputs()) - { - std::pair > newElement(m_LoggedPositions.size(),std::vector()); + while (this->m_LoggedPositions.size() < this->GetNumberOfInputs()) + { + std::pair > newElement(m_LoggedPositions.size(), std::vector()); m_LoggedPositions.insert(newElement); - } - while(this->m_LoggedQuaternions.size() < this->GetNumberOfInputs()) - { - std::pair > newElement(m_LoggedQuaternions.size(),std::vector()); + } + while (this->m_LoggedQuaternions.size() < this->GetNumberOfInputs()) + { + std::pair > newElement(m_LoggedQuaternions.size(), std::vector()); m_LoggedQuaternions.insert(newElement); - } - while(this->m_InvalidSamples.size() < this->GetNumberOfInputs()) - { - std::pair newElement(m_InvalidSamples.size(),0); + } + while (this->m_InvalidSamples.size() < this->GetNumberOfInputs()) + { + std::pair newElement(m_InvalidSamples.size(), 0); m_InvalidSamples.insert(newElement); - } - - + } } void mitk::NavigationDataEvaluationFilter::ResetStatistic() { -for (unsigned int i = 0; i < m_LoggedPositions.size(); i++) m_LoggedPositions[i] = std::vector(); -for (unsigned int i = 0; i < m_LoggedQuaternions.size(); i++) m_LoggedQuaternions[i] = std::vector(); -for (unsigned int i = 0; i < m_InvalidSamples.size(); i++) m_InvalidSamples[i] = 0; + for (unsigned int i = 0; i < m_LoggedPositions.size(); i++) m_LoggedPositions[i] = std::vector(); + for (unsigned int i = 0; i < m_LoggedQuaternions.size(); i++) m_LoggedQuaternions[i] = std::vector(); + for (unsigned int i = 0; i < m_InvalidSamples.size(); i++) m_InvalidSamples[i] = 0; } int mitk::NavigationDataEvaluationFilter::GetNumberOfAnalysedNavigationData(int input) { -return this->m_LoggedPositions[input].size(); + return this->m_LoggedPositions[input].size(); } - mitk::Point3D mitk::NavigationDataEvaluationFilter::GetPositionMean(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionMean(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionMean(); } mitk::Vector3D mitk::NavigationDataEvaluationFilter::GetPositionStandardDeviation(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionStandardDeviation(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionStandardDeviation(); } mitk::Vector3D mitk::NavigationDataEvaluationFilter::GetPositionSampleStandardDeviation(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionSampleStandardDeviation(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionSampleStandardDeviation(); } mitk::Quaternion mitk::NavigationDataEvaluationFilter::GetQuaternionMean(int input) { -return GetMean(m_LoggedQuaternions[input]); + return GetMean(m_LoggedQuaternions[input]); } mitk::Quaternion mitk::NavigationDataEvaluationFilter::GetQuaternionStandardDeviation(int input) { -mitk::Quaternion returnValue; -std::vector list1 = std::vector(); -std::vector list2 = std::vector(); -std::vector list3 = std::vector(); -std::vector list4 = std::vector(); -for (unsigned int i=0; i list1 = std::vector(); + std::vector list2 = std::vector(); + std::vector list3 = std::vector(); + std::vector list4 = std::vector(); + for (unsigned int i = 0; i < m_LoggedQuaternions[input].size(); i++) { - list1.push_back(m_LoggedQuaternions[input].at(i)[0]); - list2.push_back(m_LoggedQuaternions[input].at(i)[1]); - list3.push_back(m_LoggedQuaternions[input].at(i)[2]); - list4.push_back(m_LoggedQuaternions[input].at(i)[3]); + list1.push_back(m_LoggedQuaternions[input].at(i)[0]); + list2.push_back(m_LoggedQuaternions[input].at(i)[1]); + list3.push_back(m_LoggedQuaternions[input].at(i)[2]); + list4.push_back(m_LoggedQuaternions[input].at(i)[3]); } -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(); -returnValue[0] = myCalculator->GetStabw(list1); -returnValue[1] = myCalculator->GetStabw(list2); -returnValue[2] = myCalculator->GetStabw(list3); -returnValue[3] = myCalculator->GetStabw(list4); -return returnValue; + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(); + returnValue[0] = myCalculator->GetStabw(list1); + returnValue[1] = myCalculator->GetStabw(list2); + returnValue[2] = myCalculator->GetStabw(list3); + returnValue[3] = myCalculator->GetStabw(list4); + return returnValue; } mitk::Vector3D mitk::NavigationDataEvaluationFilter::GetEulerAnglesMean(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(QuaternionsToEulerAngles(m_LoggedQuaternions[input]))); -mitk::Vector3D returnValue; -returnValue[0] = myCalculator->GetPositionMean()[0]; -returnValue[1] = myCalculator->GetPositionMean()[1]; -returnValue[2] = myCalculator->GetPositionMean()[2]; -return returnValue; + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(QuaternionsToEulerAngles(m_LoggedQuaternions[input]))); + mitk::Vector3D returnValue; + returnValue[0] = myCalculator->GetPositionMean()[0]; + returnValue[1] = myCalculator->GetPositionMean()[1]; + returnValue[2] = myCalculator->GetPositionMean()[2]; + return returnValue; } double mitk::NavigationDataEvaluationFilter::GetEulerAnglesRMS(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(QuaternionsToEulerAngles(m_LoggedQuaternions[input]))); -return myCalculator->GetPositionErrorRMS(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(QuaternionsToEulerAngles(m_LoggedQuaternions[input]))); + return myCalculator->GetPositionErrorRMS(); } double mitk::NavigationDataEvaluationFilter::GetEulerAnglesRMSDegree(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(QuaternionsToEulerAnglesGrad(m_LoggedQuaternions[input]))); -return myCalculator->GetPositionErrorRMS(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(QuaternionsToEulerAnglesGrad(m_LoggedQuaternions[input]))); + return myCalculator->GetPositionErrorRMS(); } - - double mitk::NavigationDataEvaluationFilter::GetPositionErrorMean(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionErrorMean(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionErrorMean(); } double mitk::NavigationDataEvaluationFilter::GetPositionErrorStandardDeviation(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionErrorStandardDeviation(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionErrorStandardDeviation(); } double mitk::NavigationDataEvaluationFilter::GetPositionErrorSampleStandardDeviation(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionErrorSampleStandardDeviation(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionErrorSampleStandardDeviation(); } - double mitk::NavigationDataEvaluationFilter::GetPositionErrorRMS(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionErrorRMS(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionErrorRMS(); } double mitk::NavigationDataEvaluationFilter::GetPositionErrorMedian(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionErrorMedian(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionErrorMedian(); } double mitk::NavigationDataEvaluationFilter::GetPositionErrorMax(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionErrorMax(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionErrorMax(); } double mitk::NavigationDataEvaluationFilter::GetPositionErrorMin(int input) { -mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); -return myCalculator->GetPositionErrorMin(); + mitk::PointSetStatisticsCalculator::Pointer myCalculator = mitk::PointSetStatisticsCalculator::New(VectorToPointSet(m_LoggedPositions[input])); + return myCalculator->GetPositionErrorMin(); } int mitk::NavigationDataEvaluationFilter::GetNumberOfInvalidSamples(int input) { -return m_InvalidSamples[input]; + return m_InvalidSamples[input]; } double mitk::NavigationDataEvaluationFilter::GetPercentageOfInvalidSamples(int input) { -return (m_InvalidSamples[input]/(m_InvalidSamples[input]+((double)m_LoggedPositions[input].size())))*100.0; + return (m_InvalidSamples[input] / (m_InvalidSamples[input] + ((double)m_LoggedPositions[input].size())))*100.0; } mitk::Quaternion mitk::NavigationDataEvaluationFilter::GetMean(std::vector list) { -//calculate mean -mitk::Quaternion mean; -mean[0] = 0; -mean[1] = 0; -mean[2] = 0; -mean[3] = 0; - -for (unsigned int i=0; i pSet) { mitk::PointSet::Pointer returnValue = mitk::PointSet::New(); - for (unsigned int i=0; iInsertPoint(i,pSet.at(i)); + for (unsigned int i = 0; i < pSet.size(); i++) returnValue->InsertPoint(i, pSet.at(i)); return returnValue; } mitk::PointSet::Pointer mitk::NavigationDataEvaluationFilter::VectorToPointSet(std::vector pSet) { mitk::PointSet::Pointer returnValue = mitk::PointSet::New(); - for (unsigned int i=0; iInsertPoint(i,thisPoint); - } + returnValue->InsertPoint(i, thisPoint); + } return returnValue; } std::vector mitk::NavigationDataEvaluationFilter::QuaternionsToEulerAngles(std::vector quaterions) { std::vector returnValue = std::vector(); - for (unsigned int i=0; i mitk::NavigationDataEvaluationFilter::QuaternionsToEulerAnglesGrad(std::vector quaterions) { double PI = M_PI; std::vector returnValue = std::vector(); std::vector eulerAnglesRadians = QuaternionsToEulerAngles(quaterions); - for (unsigned int i=0; i + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/resources/QmitkIGTTrackingSemiAutomaticMeasurementView.qrc b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/resources/QmitkIGTTrackingSemiAutomaticMeasurementView.qrc new file mode 100644 index 0000000000..4222814e5c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/resources/QmitkIGTTrackingSemiAutomaticMeasurementView.qrc @@ -0,0 +1,8 @@ + + + icon.xpm + + + icon-eval.xpm + + diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/resources/icon-eval.xpm b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/resources/icon-eval.xpm new file mode 100644 index 0000000000..dd04f91df1 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/resources/icon-eval.xpm @@ -0,0 +1,107 @@ +/* XPM */ +static char * icon_xpm[] = { +"100 100 4 1", +" c None", +". c #FFFFFF", +"+ c #000000", +"@ c #22B14C", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +".............................++++...................................................................", +"...........................++++++...................................................................", +"..........................+++++++...................................................................", +".........................+++.++++...................................................................", +".........................++..++++...................................................................", +".............................++++...................................................................", +".............................++++...........................+++++++.................................", +".............................++++.........................++++++++++................................", +".............................++++.........................+++++++++++...............................", +".............................++++.........................++....+++++...............................", +".............................++++................................++++...............................", +".............................++++................................++++...............................", +".............................++++...............................++++................................", +".............................++++...........................+++++++.................................", +".............................++++...........................+++++++.................................", +".........................++++++++++++.......................+++++++++...............................", +".........................++++++++++++............................+++++..............................", +".........................++++++++++++.............................++++..............................", +"..................................................................++++..............................", +"..................................................................++++..............................", +"..........................................................++.....+++++..............................", +"..........................................................+++++++++++...............................", +"..........................................................++++++++++................................", +"............................................................++++++..................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"..........................................++++++....................................................", +"........................................++++++++++..................................................", +"........................................++++++++++..................................................", +"........................................++....+++++.................................................", +"...............................................++++.................................................", +"...............................................++++.................................................", +"...............................................++++.................................................", +"..............................................++++..................................................", +"..............................................++++..................................................", +".............................................++++...................................................", +"............................................++++....................................................", +"...........................................++++.....................................................", +"..........................................++++......................................................", +".........................................++++.......................................................", +".........................................+++........................................................", +"........................................++++++++++++................................................", +"........................................++++++++++++................................................", +"........................................++++++++++++................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................+++.............................................", +"...................................................+++++++..........................................", +"...................................................++++++++++.......................................", +"...................................................++++++++++++.....................................", +"...................................................+++++++++++++++..................................", +"........................+++++++++++++++++++++++++++++++++++++++++++++...............................", +".......................+++++++++++++++++++++++++++++++++@++++++++++++++.............................", +".......................+++++++++++++++++++++++++++++++++@@@@++++++++++++++..........................", +".......................+++++++++++++++++++++++++++++++++@@@@@@+++++++++++++++.......................", +".......................++++++++++++++++++++++++++++++++@@@@@@@@@@++++++++++++++.....................", +".......................+++++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++++++++++++++..................", +".......................+++++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+++++++++++++.................", +".......................+++++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+++++++++++................", +".......................+++++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+++++++++++................", +".......................+++++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@+++++++++++++.................", +".......................+++++@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@++++++++++++++..................", +".......................++++++++++++++++++++++++++++++++@@@@@@@@@@++++++++++++++.....................", +".......................+++++++++++++++++++++++++++++++++@@@@@@+++++++++++++++.......................", +".......................+++++++++++++++++++++++++++++++++@@@@++++++++++++++..........................", +".......................+++++++++++++++++++++++++++++++++@++++++++++++++.............................", +"........................+++++++++++++++++++++++++++++++++++++++++++++...............................", +"...................................................+++++++++++++++..................................", +"...................................................++++++++++++.....................................", +"...................................................++++++++++.......................................", +"...................................................+++++++..........................................", +"....................................................+++.............................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"....................................................................................................", +"...................................................................................................."}; diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/resources/icon.xpm b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/resources/icon.xpm new file mode 100644 index 0000000000..76b97458fd --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/resources/icon.xpm @@ -0,0 +1,6640 @@ +/* XPM */ +static char * icon_xpm[] = { +"130 130 6507 2", +" c None", +". c #FFFFFF", +"+ c #FCFCFC", +"@ c #FDFDFD", +"# c #FDFFFF", +"$ c #FDFDFF", +"% c #FFFDFF", +"& c #FCFDFC", +"* c #FBFBFB", +"= c #FAFAFA", +"- c #FAF9F9", +"; c #FBF9FB", +"> c #FCFAFB", +", c #F9F7F9", +"' c #F8F7F9", +") c #F6F6F6", +"! c #F8F7F7", +"~ c #F8F8F8", +"{ c #F9F9F9", +"] c #F7F8F8", +"^ c #F9FAF9", +"/ c #F9F8F8", +"( c #F9F7F8", +"_ c #F7F6F6", +": c #F5F5F4", +"< c #F6F5F5", +"[ c #F8FAF9", +"} c #F7F9F8", +"| c #F8F7F8", +"1 c #FAF8F9", +"2 c #FAFBFB", +"3 c #F9F8FA", +"4 c #F8F8FA", +"5 c #F6F6F7", +"6 c #F6F6F8", +"7 c #F5F5F6", +"8 c #F3F3F5", +"9 c #F2F2F2", +"0 c #F3F4F3", +"a c #E7E9E8", +"b c #E6E7E7", +"c c #E5E6E6", +"d c #E6E8E7", +"e c #E5E6E5", +"f c #E2E3E3", +"g c #DCDEDE", +"h c #DFE1E0", +"i c #E1E2E0", +"j c #E1E1E1", +"k c #E3E3E3", +"l c #E2E4E3", +"m c #E1E3E2", +"n c #E3E5E4", +"o c #DEDFDE", +"p c #DCDEDD", +"q c #DDDEDD", +"r c #DADCD9", +"s c #DCDEDB", +"t c #DBDCDA", +"u c #DADBDA", +"v c #E0E2E1", +"w c #E5E7E6", +"x c #E4E6E4", +"y c #E1E3E1", +"z c #E3E4E4", +"A c #E0E1E1", +"B c #E0E1E0", +"C c #E9EBEB", +"D c #E7EAE9", +"E c #E7E8E8", +"F c #E6E6E6", +"G c #F1F1F1", +"H c #F5F5F5", +"I c #F3F3F3", +"J c #F7F7F7", +"K c #FFFFFD", +"L c #FDFFFD", +"M c #F8F9F9", +"N c #F3F5F4", +"O c #EFF0EF", +"P c #EEEEEE", +"Q c #F0F0F0", +"R c #EDEDED", +"S c #ECECEC", +"T c #EBEBEB", +"U c #EBEAEB", +"V c #E8E9E8", +"W c #E2E4E1", +"X c #E7E9E6", +"Y c #DBDCDB", +"Z c #D8DAD9", +"` c #DBDDDC", +" . c #DEE0DF", +".. c #DCDEDC", +"+. c #DDDFDE", +"@. c #E1E2E1", +"#. c #E4E6E5", +"$. c #E3E5E3", +"%. c #E2E3E2", +"&. c #E2E2E2", +"*. c #E1E4E3", +"=. c #E3E6E4", +"-. c #E3E5E2", +";. c #E1E3E0", +">. c #E2E3E0", +",. c #E2E4E2", +"'. c #E4E6E3", +"). c #E2E3E1", +"!. c #E0E4E0", +"~. c #E2E5E2", +"{. c #E4E5E3", +"]. c #E4E5E4", +"^. c #E4E4E4", +"/. c #E3E3E1", +"(. c #E1E1DF", +"_. c #E0E0DF", +":. c #E0E0DE", +"<. c #E2E2E0", +"[. c #E4E4E2", +"}. c #E8E8E6", +"|. c #E9E9E7", +"1. c #ECECEA", +"2. c #EDEDEB", +"3. c #F0F0EE", +"4. c #F1F1F0", +"5. c #F4F4F4", +"6. c #F5F7F6", +"7. c #EFF1F0", +"8. c #EDEFED", +"9. c #EBEDE9", +"0. c #E5E7E5", +"a. c #E0E2DE", +"b. c #DDE0DE", +"c. c #DCDDDC", +"d. c #DCDCDC", +"e. c #DEDEDE", +"f. c #DDDEDE", +"g. c #DEE1DE", +"h. c #DFE1DE", +"i. c #DEE0DC", +"j. c #E0E2E0", +"k. c #E0E3E1", +"l. c #E4E6E6", +"m. c #E4E6E2", +"n. c #E5E7E4", +"o. c #E5E6E4", +"p. c #E6E8E5", +"q. c #E5E9E7", +"r. c #E2E6E5", +"s. c #E5E8E7", +"t. c #E7E7E6", +"u. c #E8E9E4", +"v. c #E6E6E4", +"w. c #E8E8EA", +"x. c #E9E7E8", +"y. c #E7E8E6", +"z. c #E7EAE8", +"A. c #E7E7E7", +"B. c #E7E7E5", +"C. c #E8E7E7", +"D. c #E9E8E9", +"E. c #EAECE9", +"F. c #E6E7E5", +"G. c #E7E8E5", +"H. c #E7E6E4", +"I. c #E7E7E4", +"J. c #E8EAE9", +"K. c #E8EAE8", +"L. c #EAEAE7", +"M. c #E8E8E5", +"N. c #E5E5E3", +"O. c #E0E0E0", +"P. c #E1E1DE", +"Q. c #EAEAE8", +"R. c #F1F1EF", +"S. c #F9F9F7", +"T. c #FAFAF8", +"U. c #DDDFDD", +"V. c #DEE0DD", +"W. c #DCDFDB", +"X. c #DFE1DF", +"Y. c #DEE0DB", +"Z. c #E1E2DF", +"`. c #E4E7E6", +" + c #E7E6E6", +".+ c #E6E9E7", +"++ c #E4E8E7", +"@+ c #E7E9E7", +"#+ c #E7E8E7", +"$+ c #E8EAE7", +"%+ c #E9E9E6", +"&+ c #E6E8E6", +"*+ c #E9EBE7", +"=+ c #E8E8E9", +"-+ c #EAEAE9", +";+ c #E8E8E7", +">+ c #E9E9E9", +",+ c #E8EBEA", +"'+ c #E9EBE9", +")+ c #E9EAE9", +"!+ c #E9E9EA", +"~+ c #E7EAE6", +"{+ c #EAEAEA", +"]+ c #E9EAEA", +"^+ c #E9EBEA", +"/+ c #EAECEB", +"(+ c #E9E9E8", +"_+ c #E9E9EB", +":+ c #E7E7E8", +"<+ c #EAEBEB", +"[+ c #E8E9E7", +"}+ c #E8EAE6", +"|+ c #E7EBEA", +"1+ c #E8E8E8", +"2+ c #EBECEB", +"3+ c #EAEBE7", +"4+ c #E8E9E5", +"5+ c #EBEBE9", +"6+ c #ECEAEA", +"7+ c #E8E9E6", +"8+ c #E6E7E4", +"9+ c #E4E4E1", +"0+ c #E2E2E1", +"a+ c #EFEFEF", +"b+ c #FAFAF9", +"c+ c #E6E7E6", +"d+ c #E4E7E4", +"e+ c #EAEBE9", +"f+ c #E3E4E2", +"g+ c #E8E9E9", +"h+ c #E7EBE8", +"i+ c #EDEBEA", +"j+ c #E6E9E8", +"k+ c #E7E7E2", +"l+ c #E9EBE8", +"m+ c #E9ECE8", +"n+ c #EBEDEB", +"o+ c #EBEDEA", +"p+ c #EAECEA", +"q+ c #E9ECE9", +"r+ c #ECEBED", +"s+ c #E9E8E8", +"t+ c #EAEBE8", +"u+ c #ECEBEB", +"v+ c #EBECED", +"w+ c #ECF0F0", +"x+ c #ECECED", +"y+ c #EAEAEB", +"z+ c #E8ECEA", +"A+ c #EAEDEB", +"B+ c #EBECE9", +"C+ c #EDEEEE", +"D+ c #ECF0EE", +"E+ c #EDEEED", +"F+ c #EAE9EA", +"G+ c #ECEAEB", +"H+ c #ECECEB", +"I+ c #EDEFEF", +"J+ c #EFEEEF", +"K+ c #ECEDED", +"L+ c #ECEEEE", +"M+ c #EDEDEF", +"N+ c #EAEDED", +"O+ c #EEEFEC", +"P+ c #EDECED", +"Q+ c #EDEBED", +"R+ c #EAEEEC", +"S+ c #EAEDEC", +"T+ c #EDECE9", +"U+ c #EDF0EE", +"V+ c #ECEFEC", +"W+ c #EBEEED", +"X+ c #ECEDEB", +"Y+ c #EEECEF", +"Z+ c #ECEDEC", +"`+ c #ECEFEE", +" @ c #EBEBEC", +".@ c #EBEAEA", +"+@ c #E9EAE8", +"@@ c #EBECEA", +"#@ c #EEEDEE", +"$@ c #EBECEC", +"%@ c #EBEEEE", +"&@ c #EBE8EB", +"*@ c #EBEDE8", +"=@ c #ECEDEA", +"-@ c #ECEEEB", +";@ c #EEEEEB", +">@ c #E7E8E4", +",@ c #E5E5E4", +"'@ c #EBEBE8", +")@ c #F4F3F2", +"!@ c #F4F4F3", +"~@ c #FCFCFD", +"{@ c #EBEAE9", +"]@ c #E9EAEB", +"^@ c #EBEDEC", +"/@ c #E8E7E9", +"(@ c #ECEEED", +"_@ c #E9EDEB", +":@ c #ECEBE9", +"<@ c #EAEEE9", +"[@ c #E9ECEA", +"}@ c #E8ECED", +"|@ c #E8EDEC", +"1@ c #E9ECEC", +"2@ c #EBEEF0", +"3@ c #ECEBEA", +"4@ c #ECEDEF", +"5@ c #EEF1ED", +"6@ c #EEEFF0", +"7@ c #EEEFEE", +"8@ c #EFEFEE", +"9@ c #EEF0F1", +"0@ c #F0F0EF", +"a@ c #F2F3F1", +"b@ c #F0F2F0", +"c@ c #F0F3F2", +"d@ c #F1F2F1", +"e@ c #F1F3F1", +"f@ c #F1F2F0", +"g@ c #EFF0EE", +"h@ c #F0EFEE", +"i@ c #F1EFEC", +"j@ c #EFEEEE", +"k@ c #EFF0EC", +"l@ c #EDF1EE", +"m@ c #ECEEEA", +"n@ c #EAE8E7", +"o@ c #ECEBE8", +"p@ c #EBEAE7", +"q@ c #EEEDEC", +"r@ c #ECECE9", +"s@ c #ECEBEC", +"t@ c #EDECEB", +"u@ c #ECEEEC", +"v@ c #EDEFEA", +"w@ c #EFEEED", +"x@ c #ECF0ED", +"y@ c #EFEFEC", +"z@ c #EEEFEB", +"A@ c #EEEDED", +"B@ c #EDECEA", +"C@ c #EEEEEC", +"D@ c #EEEDEB", +"E@ c #EFEDED", +"F@ c #EDF1EC", +"G@ c #F8F8F7", +"H@ c #EBEBED", +"I@ c #ECEEEF", +"J@ c #EDEFEE", +"K@ c #E9EDEA", +"L@ c #EEEDEF", +"M@ c #EDEFF0", +"N@ c #EBEEEA", +"O@ c #EEEEED", +"P@ c #EEEEEF", +"Q@ c #EEF0ED", +"R@ c #EEF0EF", +"S@ c #F0F1EF", +"T@ c #EEF0F0", +"U@ c #F1F3EF", +"V@ c #EFEEF0", +"W@ c #EEF2F0", +"X@ c #F0F2EF", +"Y@ c #F2F2F1", +"Z@ c #F2F2EF", +"`@ c #EFF0EB", +" # c #EDEEEC", +".# c #EDEDEA", +"+# c #EEECE9", +"@# c #EEEDE9", +"## c #E9EAE6", +"$# c #EAEBE6", +"%# c #EAECE7", +"&# c #EBEAE8", +"*# c #E9EAE7", +"=# c #EAEAE6", +"-# c #E9EBE5", +";# c #EDEDEC", +"># c #F0EFF0", +",# c #EDF0F1", +"'# c #EEEFEF", +")# c #EEF1EF", +"!# c #F1F1ED", +"~# c #ECEFED", +"{# c #EFF0F0", +"]# c #EEF0EE", +"^# c #EEF0EC", +"/# c #EDEEE9", +"(# c #EFF0ED", +"_# c #F0F1EE", +":# c #EDEEEB", +"<# c #EDEFEC", +"[# c #EEF1EE", +"}# c #EFF2EF", +"|# c #EFEFED", +"1# c #EEEFED", +"2# c #FDFDFC", +"3# c #EDEDEE", +"4# c #EDEEEF", +"5# c #ECEDEE", +"6# c #F0F0F1", +"7# c #EFEFF1", +"8# c #F0F1F1", +"9# c #F2F2F3", +"0# c #EDF0ED", +"a# c #F2F0EE", +"b# c #F0F0ED", +"c# c #E9EAE5", +"d# c #E7E9E5", +"e# c #E9ECE4", +"f# c #E9ECE7", +"g# c #E8ECE8", +"h# c #EAEBEA", +"i# c #E8E7E8", +"j# c #EBEBEA", +"k# c #EEEEEA", +"l# c #F0EEEF", +"m# c #EEF0EB", +"n# c #F0EFEC", +"o# c #EFF1ED", +"p# c #EFEFF0", +"q# c #EEEFEA", +"r# c #EFF1EE", +"s# c #EFF1EF", +"t# c #F0EFEF", +"u# c #F0F1F3", +"v# c #EEF1F0", +"w# c #F1EEEE", +"x# c #F1F0F0", +"y# c #F2F3F3", +"z# c #F1F4F3", +"A# c #EDF0EF", +"B# c #F2F2F0", +"C# c #F0F2ED", +"D# c #F2F4EF", +"E# c #F1F2EE", +"F# c #F2F3EF", +"G# c #EFF2F0", +"H# c #F1F0EF", +"I# c #DFDFDD", +"J# c #F1F1F2", +"K# c #F0F1F0", +"L# c #F3F2F1", +"M# c #F1F3F0", +"N# c #E6EAE4", +"O# c #F0F4F1", +"P# c #F0F2F1", +"Q# c #F5F1F2", +"R# c #F0F4F3", +"S# c #F1F3F2", +"T# c #F0F0F2", +"U# c #F1F0F3", +"V# c #F0EFF2", +"W# c #F0F1F2", +"X# c #EFF1F2", +"Y# c #EFF0F1", +"Z# c #F1F0F1", +"`# c #EFEFF2", +" $ c #EFF2F1", +".$ c #EFF1F1", +"+$ c #F0EFF1", +"@$ c #F1F2F2", +"#$ c #EFEEEA", +"$$ c #F1EFF2", +"%$ c #F2F3F2", +"&$ c #EFF0F3", +"*$ c #F1F2F3", +"=$ c #F2F0EF", +"-$ c #F0F3F0", +";$ c #EFF3F0", +">$ c #F1F4F2", +",$ c #F2F1EF", +"'$ c #F2F2F4", +")$ c #F3F3F1", +"!$ c #F1F3EE", +"~$ c #F2F4F0", +"{$ c #F1F4F1", +"]$ c #D9D9D7", +"^$ c #E8EAE5", +"/$ c #E9E9E5", +"($ c #E6E8E4", +"_$ c #E9EBE6", +":$ c #ECEEE9", +"<$ c #F0F2F3", +"[$ c #F2F4F3", +"}$ c #F2F5F5", +"|$ c #F3F6F6", +"1$ c #F5F4F4", +"2$ c #F3F4F1", +"3$ c #F3F5F1", +"4$ c #F2F4F4", +"5$ c #F3F4F5", +"6$ c #EFF0F2", +"7$ c #F2F1F2", +"8$ c #F2F4F2", +"9$ c #F3F2F3", +"0$ c #F1F2EF", +"a$ c #F0F2F2", +"b$ c #F2F4F1", +"c$ c #F2F3F0", +"d$ c #EFF3EF", +"e$ c #F3F3F2", +"f$ c #EFF3F1", +"g$ c #F3F4F4", +"h$ c #EEF2F1", +"i$ c #F3F6F3", +"j$ c #F0F3F3", +"k$ c #F1F3F3", +"l$ c #F4F5F5", +"m$ c #DBDBDA", +"n$ c #E9EBEC", +"o$ c #F4F6F4", +"p$ c #F5F7F5", +"q$ c #F3F5F5", +"r$ c #F0F4F5", +"s$ c #F6F7F7", +"t$ c #F3F4F2", +"u$ c #F2F5F4", +"v$ c #F2F6F4", +"w$ c #F2F1F1", +"x$ c #F0F4F2", +"y$ c #F4F6F5", +"z$ c #F2F1F3", +"A$ c #F1F2F4", +"B$ c #F1F3F4", +"C$ c #EFF3F4", +"D$ c #F3F4F0", +"E$ c #F0F4F0", +"F$ c #F1F5F2", +"G$ c #F1F5F3", +"H$ c #F2F5F3", +"I$ c #F2F5F1", +"J$ c #F3F5F2", +"K$ c #F4F4F1", +"L$ c #F4F5F2", +"M$ c #F4F2F3", +"N$ c #F4F3F4", +"O$ c #F3F5F3", +"P$ c #F4F5F3", +"Q$ c #F1F0EE", +"R$ c #F3F4F7", +"S$ c #F3F5F7", +"T$ c #F1F4F0", +"U$ c #F1F1F3", +"V$ c #F3F3F0", +"W$ c #F3F2F2", +"X$ c #F3F3F4", +"Y$ c #F2F5F2", +"Z$ c #F3F4EF", +"`$ c #F6F4F4", +" % c #F4F2F2", +".% c #F4F5F6", +"+% c #F5F3F4", +"@% c #F6F4F2", +"#% c #F5F4F3", +"$% c #F5F6F7", +"%% c #F1F6F3", +"&% c #F2F6F2", +"*% c #F4F5F1", +"=% c #F5F5F2", +"-% c #F7F5F4", +";% c #F2F5EF", +">% c #F3F5F0", +",% c #F4F6F1", +"'% c #F4F7F2", +")% c #F4F6F3", +"!% c #F4F5F0", +"~% c #EAECE5", +"{% c #E4E5E1", +"]% c #D8D9D3", +"^% c #F0F3EF", +"/% c #F4F4F2", +"(% c #F3F2F4", +"_% c #F4F3F1", +":% c #F1F5F5", +"<% c #F4F3F6", +"[% c #F2F3F5", +"}% c #F5F4F6", +"|% c #F3F5EF", +"1% c #F2F3F4", +"2% c #F4F3F3", +"3% c #EFF3F3", +"4% c #F0F3F1", +"5% c #EFF2ED", +"6% c #E8EAE4", +"7% c #E1E2DE", +"8% c #D6D7D3", +"9% c #F5F5F3", +"0% c #F6F7F5", +"a% c #F6F5F3", +"b% c #F3F2EF", +"c% c #F2F1F4", +"d% c #F5F6F4", +"e% c #F5F6F2", +"f% c #F3F6F5", +"g% c #F3F7F5", +"h% c #F4F5F4", +"i% c #F5F6F5", +"j% c #F3F6F2", +"k% c #F7F7F6", +"l% c #F5F7F3", +"m% c #F4F6F8", +"n% c #F1F5F6", +"o% c #F5F5F7", +"p% c #F5F7F4", +"q% c #F3F4F6", +"r% c #F6F7F9", +"s% c #F6F8F9", +"t% c #F8F7FB", +"u% c #F7F8FB", +"v% c #FAFDFA", +"w% c #FBFDF9", +"x% c #FBFCFF", +"y% c #FCFDFF", +"z% c #FDFDFA", +"A% c #FCFCFB", +"B% c #FDFCFC", +"C% c #FAFCFC", +"D% c #FCFDFB", +"E% c #FCFBFC", +"F% c #FBFDFC", +"G% c #FBFCFB", +"H% c #FDFCFD", +"I% c #FCFDFD", +"J% c #FDFBFD", +"K% c #EDEFEB", +"L% c #E5E5E5", +"M% c #E1E2DD", +"N% c #D5D6D1", +"O% c #F5F4F9", +"P% c #F4F3F8", +"Q% c #F6F5F6", +"R% c #F5F7F7", +"S% c #F3F5F6", +"T% c #F4F6F6", +"U% c #F6F7F4", +"V% c #F5F3F6", +"W% c #F6F6F5", +"X% c #F3F6F4", +"Y% c #F4F8F6", +"Z% c #F5F6F9", +"`% c #F4F5F7", +" & c #F7F8FA", +".& c #F9F9FA", +"+& c #FAFCFB", +"@& c #FBFCFA", +"#& c #FBFBFA", +"$& c #F9F9F6", +"%& c #F8F8F5", +"&& c #EBEBE7", +"*& c #E7E9E4", +"=& c #E6E8E2", +"-& c #E7E8E2", +";& c #E6E7E3", +">& c #E5E6E1", +",& c #E7E8E3", +"'& c #E4E6E1", +")& c #E6E7E2", +"!& c #E2E3DE", +"~& c #E5E6E0", +"{& c #E4E7E1", +"]& c #E5E8E2", +"^& c #E3E5E0", +"/& c #E1E3DD", +"(& c #E4E5E2", +"_& c #E5E8E6", +":& c #E5E6E3", +"<& c #DCDBD9", +"[& c #F4F7F5", +"}& c #F6F7F6", +"|& c #F6F7F8", +"1& c #F4F6F7", +"2& c #F5F7F8", +"3& c #F2F4F5", +"4& c #F5F6F8", +"5& c #F2F4F6", +"6& c #F4F4F5", +"7& c #F6F8F6", +"8& c #F5F7F9", +"9& c #F6F8F8", +"0& c #F7F8F7", +"a& c #F8FAFA", +"b& c #F9FBFB", +"c& c #F9FAFC", +"d& c #F9F9FC", +"e& c #FBFBFF", +"f& c #FCFFFD", +"g& c #FFFDFD", +"h& c #EFEFEB", +"i& c #ECEDE9", +"j& c #DDDEDB", +"k& c #DBDDD5", +"l& c #D5D7D1", +"m& c #D0D1CB", +"n& c #CBCCC5", +"o& c #CAC9C7", +"p& c #C6C8BF", +"q& c #C1C3BC", +"r& c #BEBEBB", +"s& c #B8BAB6", +"t& c #BAB8B2", +"u& c #B5B5AD", +"v& c #B4B5B3", +"w& c #A9A7A6", +"x& c #AFB0A6", +"y& c #D0D0CA", +"z& c #D6D7D0", +"A& c #DDDFD9", +"B& c #E0E0DB", +"C& c #E3E3DE", +"D& c #E0E4DB", +"E& c #DEE2DB", +"F& c #E1E5DD", +"G& c #DEE0DA", +"H& c #E0E3DB", +"I& c #E3E5DD", +"J& c #E1E2DB", +"K& c #DEDED9", +"L& c #DFE0DA", +"M& c #DFE0DB", +"N& c #DFE2DB", +"O& c #DBDFD7", +"P& c #DDDFDA", +"Q& c #E2E4DC", +"R& c #DEE2D7", +"S& c #DFE3DB", +"T& c #E0E2DB", +"U& c #DFE2DA", +"V& c #DEE3DA", +"W& c #DDE1D8", +"X& c #DEE1D9", +"Y& c #E0E2D9", +"Z& c #C2C6C0", +"`& c #F9F7F7", +" * c #E6EAE5", +".* c #E5E4E2", +"+* c #F4F5F8", +"@* c #F6F5FB", +"#* c #F3F5F9", +"$* c #F3F6F7", +"%* c #F3F2F5", +"&* c #F6F7FA", +"** c #F4F4FA", +"=* c #F6F8FB", +"-* c #F8F9FA", +";* c #F7F9F9", +">* c #F8F8F9", +",* c #FBFBFC", +"'* c #FAFBFC", +")* c #FBFBFD", +"!* c #FDFCFB", +"~* c #F8F7F6", +"{* c #F5F4F2", +"]* c #E8E8E4", +"^* c #E5E5E1", +"/* c #E2E3DF", +"(* c #DEDFDB", +"_* c #DBDBD8", +":* c #D9DBD5", +"<* c #D4D6CE", +"[* c #CCCEC8", +"}* c #C5C7C1", +"|* c #C0C1BB", +"1* c #C2C3BC", +"2* c #BDBEB7", +"3* c #BCBEB4", +"4* c #B8BCB1", +"5* c #B6B7B3", +"6* c #B6B6B3", +"7* c #B4B5AC", +"8* c #B2B4AE", +"9* c #B3B6AF", +"0* c #B3B5AE", +"a* c #B2B4B0", +"b* c #B4B4B0", +"c* c #B2B3AD", +"d* c #B4B4AF", +"e* c #B5B4B6", +"f* c #B4B5B2", +"g* c #B6B8B1", +"h* c #B5B7B3", +"i* c #B9B7B4", +"j* c #B3B6B1", +"k* c #B7B7B7", +"l* c #A9A8A7", +"m* c #BAC0BB", +"n* c #918E86", +"o* c #5E6057", +"p* c #676863", +"q* c #646464", +"r* c #63645F", +"s* c #636461", +"t* c #656664", +"u* c #646462", +"v* c #676764", +"w* c #676765", +"x* c #666663", +"y* c #646562", +"z* c #676763", +"A* c #676662", +"B* c #676663", +"C* c #666563", +"D* c #656461", +"E* c #666463", +"F* c #686765", +"G* c #696765", +"H* c #686866", +"I* c #6B6B69", +"J* c #696A68", +"K* c #666664", +"L* c #656563", +"M* c #656561", +"N* c #696A64", +"O* c #6A6B67", +"P* c #666662", +"Q* c #70716C", +"R* c #CDCDCC", +"S* c #BABEB4", +"T* c #F7F7F5", +"U* c #E6E6E2", +"V* c #E5E6E2", +"W* c #E3E8E2", +"X* c #F7F9F7", +"Y* c #F6F8F5", +"Z* c #F5F6F3", +"`* c #F2F2F5", +" = c #F2F6F3", +".= c #F5F8F7", +"+= c #F9FAFA", +"@= c #FBFCF9", +"#= c #F4F6F2", +"$= c #F2F3EE", +"%= c #DEE0D9", +"&= c #D8DBD3", +"*= c #CECECA", +"== c #CDCDC7", +"-= c #CBCCC7", +";= c #C5C7C2", +">= c #C2C3BE", +",= c #C1C3B9", +"'= c #C0C3BB", +")= c #BEC1B9", +"!= c #C0C2BB", +"~= c #BBBDB5", +"{= c #BABCB4", +"]= c #BBBAB5", +"^= c #BABBB5", +"/= c #BBBCB8", +"(= c #B7B9B2", +"_= c #BCBDB7", +":= c #BCBDB9", +"<= c #BEC0BB", +"[= c #C0C2BC", +"}= c #C1C3BE", +"|= c #C0C1BC", +"1= c #C2C3BD", +"2= c #C0C2BE", +"3= c #C4C5C0", +"4= c #C5C5C3", +"5= c #C3C4C1", +"6= c #C0C2BD", +"7= c #C3C4BD", +"8= c #C3C3BF", +"9= c #C0C0BE", +"0= c #BFC1BE", +"a= c #C1C2BE", +"b= c #BFC3BC", +"c= c #BAC0B9", +"d= c #BFC0BD", +"e= c #C1C1BD", +"f= c #B1B3AB", +"g= c #C9CAC6", +"h= c #676766", +"i= c #000000", +"j= c #020202", +"k= c #000100", +"l= c #1F1E21", +"m= c #A5A3A5", +"n= c #E5E7E2", +"o= c #AFB5AC", +"p= c #E3E4E1", +"q= c #E3E8E1", +"r= c #F4F5F9", +"s= c #F3F5F8", +"t= c #FBFDFB", +"u= c #F9FCFB", +"v= c #FBFCFC", +"w= c #FDFDFB", +"x= c #FFFFFC", +"y= c #FBFCF8", +"z= c #FBFBF7", +"A= c #F6F6F4", +"B= c #DEDFD9", +"C= c #D8DAD5", +"D= c #D6D7D2", +"E= c #D0D1CD", +"F= c #CDCEC8", +"G= c #C7C7C4", +"H= c #C2C4C1", +"I= c #C1C5BC", +"J= c #C2C4BD", +"K= c #BCBEBB", +"L= c #BCBFB7", +"M= c #BDC0B7", +"N= c #BEBFBA", +"O= c #BEBFBB", +"P= c #BEC0BE", +"Q= c #BFC1BD", +"R= c #C4C5C2", +"S= c #C5C5C1", +"T= c #C7CAC1", +"U= c #C5C8C2", +"V= c #C4C7C2", +"W= c #C7C9C5", +"X= c #C6C8C6", +"Y= c #C6C6C6", +"Z= c #C8C7C3", +"`= c #C5C8BF", +" - c #C6C8C2", +".- c #C7CBC4", +"+- c #C7C9C6", +"@- c #C9CAC4", +"#- c #C6C9C2", +"$- c #C0C3BF", +"%- c #C2C3BF", +"&- c #C4C4C0", +"*- c #C1C1BE", +"=- c #BFC0BC", +"-- c #C0C0BA", +";- c #BEC0B9", +">- c #BFC0BB", +",- c #BBBFBA", +"'- c #BBBFB7", +")- c #BDBCBE", +"!- c #B9C0B7", +"~- c #BCBFBC", +"{- c #B1B5AD", +"]- c #C8CBC5", +"^- c #FFFDF8", +"/- c #5B5755", +"(- c #1D2019", +"_- c #1D1D18", +":- c #1A1A17", +"<- c #171A14", +"[- c #171C16", +"}- c #1B1D17", +"|- c #191A17", +"1- c #1A1B15", +"2- c #161C15", +"3- c #181B14", +"4- c #161B14", +"5- c #171C15", +"6- c #151910", +"7- c #181B16", +"8- c #151C15", +"9- c #141914", +"0- c #171815", +"a- c #161713", +"b- c #141A15", +"c- c #151B11", +"d- c #171D15", +"e- c #161915", +"f- c #161B16", +"g- c #151917", +"h- c #151916", +"i- c #161917", +"j- c #151A14", +"k- c #131812", +"l- c #141A14", +"m- c #121814", +"n- c #141915", +"o- c #1D201A", +"p- c #090C07", +"q- c #080809", +"r- c #949695", +"s- c #E4E5E0", +"t- c #B6BBB8", +"u- c #EDF0F0", +"v- c #ECEAE9", +"w- c #FAFBFA", +"x- c #FBFBF8", +"y- c #DADAD5", +"z- c #D3D4CF", +"A- c #CECFCA", +"B- c #CDCFC9", +"C- c #CACDC6", +"D- c #C7CAC2", +"E- c #C7CAC4", +"F- c #C5C7C4", +"G- c #C3C6C1", +"H- c #C3C5C0", +"I- c #C3C5BF", +"J- c #C4C6C2", +"K- c #C6C7C4", +"L- c #C5C6C4", +"M- c #C6C6C4", +"N- c #C6C8C5", +"O- c #CACDC7", +"P- c #C8CAC5", +"Q- c #CBCDC9", +"R- c #CACCC9", +"S- c #C9CAC5", +"T- c #CACCC6", +"U- c #CBCDCC", +"V- c #CBCCC9", +"W- c #C9CBC6", +"X- c #C9C9C7", +"Y- c #CBCCC8", +"Z- c #C8C8C5", +"`- c #C5C7C3", +" ; c #C4C7C0", +".; c #C5C6C1", +"+; c #C4C4C2", +"@; c #C3C5C1", +"#; c #C5C6C3", +"$; c #C4C7BF", +"%; c #C5C6C0", +"&; c #C4C6C0", +"*; c #C4C6C1", +"=; c #C2C5BE", +"-; c #C2C5BF", +";; c #C3C5C2", +">; c #C1C3C0", +",; c #C0C2BF", +"'; c #C4C4C1", +"); c #C4C4BF", +"!; c #C1C2BC", +"~; c #BFBEBE", +"{; c #BEC1B7", +"]; c #BDBEB8", +"^; c #BDBDBC", +"/; c #BCBDBA", +"(; c #C2C0BB", +"_; c #B4B5AF", +":; c #C2CDC6", +"<; c #F6F2ED", +"[; c #504A46", +"}; c #1F211B", +"|; c #1C1C15", +"1; c #151713", +"2; c #141612", +"3; c #151614", +"4; c #161813", +"5; c #0E130D", +"6; c #12150F", +"7; c #121915", +"8; c #0F1612", +"9; c #0E140F", +"0; c #101612", +"a; c #0E120F", +"b; c #101510", +"c; c #101615", +"d; c #131614", +"e; c #0F1512", +"f; c #121312", +"g; c #131512", +"h; c #121412", +"i; c #10160F", +"j; c #101513", +"k; c #101516", +"l; c #0E1314", +"m; c #0D1312", +"n; c #0E1413", +"o; c #101313", +"p; c #0F1415", +"q; c #0D1211", +"r; c #101511", +"s; c #10150F", +"t; c #181D18", +"u; c #0C130D", +"v; c #070708", +"w; c #929196", +"x; c #E1E6E0", +"y; c #BCC4BE", +"z; c #E1E1DD", +"A; c #DADBD5", +"B; c #D6D6D2", +"C; c #D2D3CC", +"D; c #CDCECA", +"E; c #C9C9C8", +"F; c #C6C6C3", +"G; c #C6C7C0", +"H; c #C6C7C2", +"I; c #C4C8C4", +"J; c #C2C7C2", +"K; c #C7C9C7", +"L; c #C7C7C7", +"M; c #CACDC8", +"N; c #C9CCC5", +"O; c #CACCCA", +"P; c #CCCECB", +"Q; c #CDD0CD", +"R; c #CDD0CC", +"S; c #CED0CE", +"T; c #CED0CA", +"U; c #CCCFC9", +"V; c #CFD1CC", +"W; c #CDD0CB", +"X; c #CCCDCB", +"Y; c #CDCFCD", +"Z; c #CDCFCC", +"`; c #C7C9C4", +" > c #CBCDC7", +".> c #C7C8C3", +"+> c #C8C9C4", +"@> c #C7CAC6", +"#> c #C8C7C5", +"$> c #C8CAC4", +"%> c #C7C7C3", +"&> c #C7C8C2", +"*> c #C4C5C4", +"=> c #C7C9C2", +"-> c #C3C4C0", +";> c #C6C7C1", +">> c #C2C4C0", +",> c #C6C8C4", +"'> c #C3C3C2", +")> c #C3C4BF", +"!> c #C1C3BD", +"~> c #BFC2BC", +"{> c #C1C3BF", +"]> c #C1C1BF", +"^> c #C0C0BD", +"/> c #C0C1BD", +"(> c #BFC2BE", +"_> c #BDBEBF", +":> c #BEBFB9", +"<> c #BFC0B7", +"[> c #BDC0BA", +"}> c #BDBFBB", +"|> c #B7B7B5", +"1> c #C5C8C4", +"2> c #FCF8F8", +"3> c #5C5652", +"4> c #1A1E14", +"5> c #151414", +"6> c #131312", +"7> c #141513", +"8> c #101611", +"9> c #141611", +"0> c #12160E", +"a> c #131610", +"b> c #0D160E", +"c> c #101311", +"d> c #101613", +"e> c #121713", +"f> c #141613", +"g> c #111512", +"h> c #101210", +"i> c #0E1410", +"j> c #0D1610", +"k> c #0F1411", +"l> c #0E1612", +"m> c #131310", +"n> c #111610", +"o> c #111511", +"p> c #0E1613", +"q> c #0B130E", +"r> c #121611", +"s> c #0F150F", +"t> c #0C1710", +"u> c #0E160F", +"v> c #0C140E", +"w> c #0D1311", +"x> c #0F1513", +"y> c #0F1312", +"z> c #0E1312", +"A> c #0C140D", +"B> c #161B17", +"C> c #060905", +"D> c #111214", +"E> c #BCBEC1", +"F> c #DEE5DB", +"G> c #D3D7D5", +"H> c #CCCECA", +"I> c #C6C8C3", +"J> c #C9CBC7", +"K> c #C7C8C4", +"L> c #CDCFCA", +"M> c #CDCEC9", +"N> c #CFCFCE", +"O> c #D0D2CD", +"P> c #D0D1C9", +"Q> c #D4D5D1", +"R> c #CFD2D1", +"S> c #CED2D0", +"T> c #D0D2D0", +"U> c #D1D2CD", +"V> c #CFD1CA", +"W> c #D1D3CE", +"X> c #D0D2CF", +"Y> c #D2D4D0", +"Z> c #CED1CE", +"`> c #CFD1CD", +" , c #CED0CD", +"., c #CCCECC", +"+, c #CBCECA", +"@, c #CCCEC9", +"#, c #C8CAC7", +"$, c #C9CCC8", +"%, c #C8C8C4", +"&, c #C9CBC5", +"*, c #C5C9C4", +"=, c #C7CBC6", +"-, c #C8C9C5", +";, c #C6C8C7", +">, c #C2C5C2", +",, c #C4C6C5", +"', c #C6C7C3", +"), c #C2C4BF", +"!, c #C3C3C1", +"~, c #C2C3C0", +"{, c #C2C4C2", +"], c #C3C5BE", +"^, c #BDBFBC", +"/, c #C0C1BA", +"(, c #C2C2C1", +"_, c #BFC1BA", +":, c #C0C0BB", +"<, c #BDBDBB", +"[, c #BDC0B8", +"}, c #B9BBB7", +"|, c #BAC2B8", +"1, c #6F6465", +"2, c #181A14", +"3, c #161A15", +"4, c #131515", +"5, c #141414", +"6, c #121310", +"7, c #12140F", +"8, c #131713", +"9, c #121610", +"0, c #111712", +"a, c #101711", +"b, c #0F1511", +"c, c #0E140E", +"d, c #0E1711", +"e, c #0C1410", +"f, c #0E1411", +"g, c #101310", +"h, c #0D130F", +"i, c #111614", +"j, c #0F1310", +"k, c #0D140E", +"l, c #0C1310", +"m, c #101410", +"n, c #111611", +"o, c #111510", +"p, c #0E130E", +"q, c #0F150E", +"r, c #0F160F", +"s, c #121510", +"t, c #161D1A", +"u, c #040503", +"v, c #292B2B", +"w, c #DEE1DD", +"x, c #D6D7D1", +"y, c #D1D3D0", +"z, c #D4D6D2", +"A, c #D2D4D1", +"B, c #D3D5D1", +"C, c #D3D5D2", +"D, c #D1D4D2", +"E, c #D0D0CD", +"F, c #CFCFCC", +"G, c #D0D3CB", +"H, c #CFD0C9", +"I, c #CDCECB", +"J, c #CED0C8", +"K, c #CDD0CA", +"L, c #CDCFCB", +"M, c #CBCDC8", +"N, c #CACCC7", +"O, c #CACBCA", +"P, c #C9CCC9", +"Q, c #CBCBC8", +"R, c #C9CBC8", +"S, c #C8CAC9", +"T, c #C9CAC8", +"U, c #C8C9C7", +"V, c #CACAC7", +"W, c #C8C9C6", +"X, c #C7CEC8", +"Y, c #C4C9C5", +"Z, c #C7C7C5", +"`, c #C6C9C5", +" ' c #C6CAC3", +".' c #C4C5C5", +"+' c #C4C6BF", +"@' c #C5C6C2", +"#' c #C4C6C6", +"$' c #C2C3C1", +"%' c #C1C2BD", +"&' c #BFC1BB", +"*' c #C1C2C1", +"=' c #BBBEBB", +"-' c #BDC0B9", +";' c #BDBEB9", +">' c #BDC1BC", +",' c #BABDB6", +"'' c #BFC1B8", +")' c #B1B0AC", +"!' c #E8F1E7", +"~' c #858181", +"{' c #1C1E16", +"]' c #161B13", +"^' c #13140F", +"/' c #131612", +"(' c #151712", +"_' c #13160F", +":' c #11140F", +"<' c #131313", +"[' c #121614", +"}' c #0E1310", +"|' c #131213", +"1' c #121211", +"2' c #0F1610", +"3' c #121210", +"4' c #11150D", +"5' c #11120F", +"6' c #0F1515", +"7' c #0D130E", +"8' c #11120E", +"9' c #121714", +"0' c #0F140F", +"a' c #10130F", +"b' c #121512", +"c' c #0F1410", +"d' c #0E1510", +"e' c #121712", +"f' c #0F1212", +"g' c #151B15", +"h' c #6C6E74", +"i' c #D1D4D0", +"j' c #D6D8D5", +"k' c #D1D3D1", +"l' c #D2D5D1", +"m' c #CFD1CE", +"n' c #D0D3CD", +"o' c #CED1CB", +"p' c #CFD0CE", +"q' c #CECFC9", +"r' c #CDCFCE", +"s' c #CBCDCA", +"t' c #CCD0C9", +"u' c #CCCFCB", +"v' c #CBCEC8", +"w' c #CBCECB", +"x' c #CBCBC7", +"y' c #C9C8C7", +"z' c #CACBC7", +"A' c #C7CAC3", +"B' c #C9C9C5", +"C' c #C6CAC7", +"D' c #C3C6C2", +"E' c #C4C4BE", +"F' c #C4C4C3", +"G' c #C3C2C0", +"H' c #C2C5C0", +"I' c #BFC1BF", +"J' c #C1C4BD", +"K' c #C1C4BC", +"L' c #C2C4BE", +"M' c #BEC1BB", +"N' c #BEC1BA", +"O' c #C0C2C0", +"P' c #BCBEBC", +"Q' c #BEC0BC", +"R' c #BDBEBA", +"S' c #BDC1BB", +"T' c #B1B1AF", +"U' c #DCDCDB", +"V' c #CBC0BD", +"W' c #040301", +"X' c #171813", +"Y' c #1E1C15", +"Z' c #0F130E", +"`' c #131510", +" ) c #11160F", +".) c #14140F", +"+) c #141510", +"@) c #12130E", +"#) c #101412", +"$) c #101411", +"%) c #12140E", +"&) c #0F1510", +"*) c #111210", +"=) c #0F1311", +"-) c #12120F", +";) c #0F1711", +">) c #111612", +",) c #0D0F0B", +"') c #0D100C", +")) c #141413", +"!) c #151A17", +"~) c #12120E", +"{) c #11110D", +"]) c #0E1211", +"^) c #0E130F", +"/) c #0E1513", +"() c #10120D", +"_) c #141C15", +":) c #0B0F0B", +"<) c #0B0C0E", +"[) c #C5CDC4", +"}) c #D1D4CC", +"|) c #CFD3CE", +"1) c #D0D2D1", +"2) c #D0D1CE", +"3) c #CED1CA", +"4) c #CFD0CD", +"5) c #CED2CD", +"6) c #CED1CC", +"7) c #CFD4CD", +"8) c #CECFCB", +"9) c #CED0CB", +"0) c #CECECD", +"a) c #CDCDCA", +"b) c #C9CBC9", +"c) c #CACDCB", +"d) c #CCCAC6", +"e) c #C9C8C8", +"f) c #C9C9CA", +"g) c #CBCEC9", +"h) c #CBCCC6", +"i) c #C8CAC8", +"j) c #C6CBC5", +"k) c #C5C8C1", +"l) c #C8C8C7", +"m) c #C2C6C2", +"n) c #C5C5BF", +"o) c #C4C5C1", +"p) c #C3C5BD", +"q) c #C2C2C3", +"r) c #C2C2C0", +"s) c #C3C3C0", +"t) c #BDC0BC", +"u) c #BEC0BA", +"v) c #BABAB7", +"w) c #BDC8C1", +"x) c #F5F9F4", +"y) c #2F2B2B", +"z) c #000501", +"A) c #1D221A", +"B) c #16170F", +"C) c #0E120E", +"D) c #121410", +"E) c #101512", +"F) c #10140E", +"G) c #0D140F", +"H) c #111110", +"I) c #111412", +"J) c #111411", +"K) c #111B14", +"L) c #060F0B", +"M) c #020403", +"N) c #030303", +"O) c #010201", +"P) c #000101", +"Q) c #030203", +"R) c #050705", +"S) c #0F120D", +"T) c #10140F", +"U) c #0E150E", +"V) c #0E1311", +"W) c #0B1310", +"X) c #0D140C", +"Y) c #101610", +"Z) c #828E8B", +"`) c #E7E6DF", +" ! c #CDD3D1", +".! c #CCD1CC", +"+! c #D1D2CE", +"@! c #D1D1D1", +"#! c #CECFCE", +"$! c #CFD2CE", +"%! c #CAD0C9", +"&! c #CCD0CD", +"*! c #CBCBC9", +"=! c #CFD0CC", +"-! c #C8CCC7", +";! c #C8CFCC", +">! c #CECECC", +",! c #CCCBCA", +"'! c #C9CAC9", +")! c #CACACA", +"!! c #C8CFCA", +"~! c #C8CDCA", +"{! c #C6C9C8", +"]! c #C8CAC6", +"^! c #C6CBC9", +"/! c #C5CBC4", +"(! c #C5C5C0", +"_! c #C6CAC4", +":! c #C7C9C3", +"~ c #BEC3BB", +",~ c #B3B6B0", +"'~ c #DDE0E1", +")~ c #D7CBC2", +"!~ c #1B1414", +"~~ c #0E190F", +"{~ c #17160F", +"]~ c #0E1210", +"^~ c #121413", +"/~ c #131412", +"(~ c #11140E", +"_~ c #0D120F", +":~ c #0E130C", +"<~ c #111613", +"[~ c #0B100A", +"}~ c #080A05", +"|~ c #080B09", +"1~ c #181C1D", +"2~ c #494544", +"3~ c #5C5754", +"4~ c #2E2F2A", +"5~ c #0D0D0B", +"6~ c #201F1E", +"7~ c #2C2D28", +"8~ c #262522", +"9~ c #1B1C18", +"0~ c #0C100B", +"a~ c #0B150F", +"b~ c #12150E", +"c~ c #0E110E", +"d~ c #0D1413", +"e~ c #0B110C", +"f~ c #121912", +"g~ c #0C100D", +"h~ c #BEC1C2", +"i~ c #CBD0CC", +"j~ c #CDD2CD", +"k~ c #CCCFCA", +"l~ c #CFCECB", +"m~ c #CCCFCC", +"n~ c #CAD0CC", +"o~ c #CCCCC9", +"p~ c #CACDC9", +"q~ c #CACECC", +"r~ c #C8CDC7", +"s~ c #CACCCB", +"t~ c #CAC9C6", +"u~ c #CACBC9", +"v~ c #C8CBC8", +"w~ c #C6CBC7", +"x~ c #C7CBC7", +"y~ c #CACAC4", +"z~ c #C6C9C0", +"A~ c #C1C7C1", +"B~ c #C6C6C0", +"C~ c #C4C7C4", +"D~ c #C0C3BD", +"E~ c #C1C4BE", +"F~ c #BFBFBB", +"G~ c #BEC3BD", +"H~ c #BEC1BC", +"I~ c #C2C2BD", +"J~ c #BEC2BB", +"K~ c #BDC2BA", +"L~ c #BCC0B5", +"M~ c #BCC1BD", +"N~ c #FBF9FA", +"O~ c #5C5450", +"P~ c #141B15", +"Q~ c #0F1211", +"R~ c #101212", +"S~ c #10120E", +"T~ c #141415", +"U~ c #12140D", +"V~ c #0F1110", +"W~ c #131611", +"X~ c #0A0B0C", +"Y~ c #0C0D0C", +"Z~ c #1F2521", +"`~ c #21241E", +" { c #20231E", +".{ c #010805", +"+{ c #060605", +"@{ c #050604", +"#{ c #050704", +"${ c #040502", +"%{ c #0B0C0B", +"&{ c #141917", +"*{ c #141712", +"={ c #0A120F", +"-{ c #0C1511", +";{ c #0C1211", +">{ c #0D1210", +",{ c #0E1611", +"'{ c #101413", +"){ c #111815", +"!{ c #7D878A", +"~{ c #CBCFCA", +"{{ c #CFCFCD", +"]{ c #CACFC9", +"^{ c #C8CECB", +"/{ c #CAD0CA", +"({ c #CECDCD", +"_{ c #CACBC8", +":{ c #CBCCCB", +"<{ c #C7CAC7", +"[{ c #C8C9C9", +"}{ c #C8CAC3", +"|{ c #C6C9C1", +"1{ c #C5C8C3", +"2{ c #C4C5BF", +"3{ c #C1C8C1", +"4{ c #C0C4BF", +"5{ c #C3C5C3", +"6{ c #C1C6C1", +"7{ c #C0C3C2", +"8{ c #C1C5BD", +"9{ c #C2C3C2", +"0{ c #BFC2BA", +"a{ c #BFC3BD", +"b{ c #C1C2BF", +"c{ c #C1C0BD", +"d{ c #BFBEC1", +"e{ c #BFC3BE", +"f{ c #B8B8B5", +"g{ c #DEE0E2", +"h{ c #C4C1BC", +"i{ c #110E0C", +"j{ c #141514", +"k{ c #121613", +"l{ c #10120B", +"m{ c #131517", +"n{ c #141312", +"o{ c #0D0F08", +"p{ c #111410", +"q{ c #12130F", +"r{ c #121816", +"s{ c #060D0A", +"t{ c #151412", +"u{ c #58554F", +"v{ c #272622", +"w{ c #0B0C0A", +"x{ c #070D0D", +"y{ c #0B0F0C", +"z{ c #161A17", +"A{ c #131914", +"B{ c #0D110D", +"C{ c #070D09", +"D{ c #131714", +"E{ c #0D120E", +"F{ c #0D1814", +"G{ c #101011", +"H{ c #0C100E", +"I{ c #071110", +"J{ c #0D110E", +"K{ c #0F120F", +"L{ c #0F110D", +"M{ c #030402", +"N{ c #3C545A", +"O{ c #CCD0CE", +"P{ c #C9CEC9", +"Q{ c #C9CFC9", +"R{ c #CDCDC8", +"S{ c #CBCDCB", +"T{ c #C8CCC9", +"U{ c #CDCECC", +"V{ c #C8CCC6", +"W{ c #C8CBC6", +"X{ c #C6CCC7", +"Y{ c #C8CBC4", +"Z{ c #C6CBC3", +"`{ c #CAC9C5", +" ] c #CACBC6", +".] c #C6C7C5", +"+] c #C8C9C2", +"@] c #C6C8C0", +"#] c #C4CAC3", +"$] c #C3C4C4", +"%] c #C4C6C4", +"&] c #C1C5C0", +"*] c #C1C4C3", +"=] c #C3C6BE", +"-] c #C4C5BE", +";] c #BDC1BA", +">] c #C3C0BD", +",] c #C1C1BC", +"'] c #C0C3BA", +")] c #6D635C", +"!] c #1B1B14", +"~] c #171511", +"{] c #10130D", +"]] c #111212", +"^] c #0E1710", +"/] c #070C0B", +"(] c #171615", +"_] c #5B5652", +":] c #2A2724", +"<] c #030601", +"[] c #0C130C", +"}] c #0C120F", +"|] c #060C08", +"1] c #0A1511", +"2] c #131715", +"3] c #0D120D", +"4] c #0F1210", +"5] c #0E0F11", +"6] c #111312", +"7] c #151A13", +"8] c #1C3132", +"9] c #CCCFD2", +"0] c #CCCDC8", +"a] c #CDCCC9", +"b] c #CACFCC", +"c] c #C8CEC7", +"d] c #C8CBCB", +"e] c #C6CCC8", +"f] c #C5C8C6", +"g] c #C6CDC9", +"h] c #C5CCC5", +"i] c #C5C9C7", +"j] c #C3C7C4", +"k] c #C6C5C1", +"l] c #C6C5C2", +"m] c #C7C6C3", +"n] c #C5C5C2", +"o] c #BFC2BF", +"p] c #C4C5BD", +"q] c #C1C0BF", +"r] c #C1C0BC", +"s] c #BCBDB8", +"t] c #CBD2CA", +"u] c #D9D3CF", +"v] c #1D100D", +"w] c #080E09", +"x] c #161712", +"y] c #11130D", +"z] c #0C110D", +"A] c #0C1312", +"B] c #000601", +"C] c #474541", +"D] c #272723", +"E] c #000205", +"F] c #151716", +"G] c #0C110C", +"H] c #0E160E", +"I] c #0D1511", +"J] c #0B1610", +"K] c #08130D", +"L] c #0D140D", +"M] c #08100D", +"N] c #09130F", +"O] c #0F1913", +"P] c #0B100C", +"Q] c #141919", +"R] c #050607", +"S] c #121D22", +"T] c #CBCAC7", +"U] c #CAD1CB", +"V] c #C9CCC7", +"W] c #CECDCB", +"X] c #C9CBCC", +"Y] c #C8CDCC", +"Z] c #C9CDC9", +"`] c #C7CCC8", +" ^ c #C6CBC6", +".^ c #C3C8C1", +"+^ c #C6C9C9", +"@^ c #C5C6C5", +"#^ c #C4C8C1", +"$^ c #C2C7C1", +"%^ c #C3C7C5", +"&^ c #C5C4BF", +"*^ c #C0C4BE", +"=^ c #C2C6C1", +"-^ c #C1C5BF", +";^ c #C0C1BF", +">^ c #C1C4C0", +",^ c #C1C6C0", +"'^ c #C2C5C3", +")^ c #C1C2C0", +"!^ c #C1C2C3", +"~^ c #BDBCBA", +"{^ c #E1E9E7", +"]^ c #ABA79D", +"^^ c #151813", +"/^ c #16160F", +"(^ c #151410", +"_^ c #111713", +":^ c #11150F", +"<^ c #11110F", +"[^ c #161A13", +"}^ c #0B0B08", +"|^ c #0F1313", +"1^ c #0E1412", +"2^ c #121711", +"3^ c #060F0E", +"4^ c #0D1712", +"5^ c #121914", +"6^ c #111310", +"7^ c #0C1411", +"8^ c #0B130F", +"9^ c #09140C", +"0^ c #0A140F", +"a^ c #0B140F", +"b^ c #181914", +"c^ c #050605", +"d^ c #0C151F", +"e^ c #CBD0CA", +"f^ c #C9CECC", +"g^ c #CCCAC8", +"h^ c #C8CCC8", +"i^ c #C7CFCB", +"j^ c #C7CCC6", +"k^ c #C7CDC6", +"l^ c #C7CEC6", +"m^ c #CBCBC5", +"n^ c #C7C8C8", +"o^ c #C8CDC8", +"p^ c #CBCAC6", +"q^ c #C6C9C4", +"r^ c #C8C9C3", +"s^ c #C5C7C6", +"t^ c #C6C7C9", +"u^ c #C3C7C3", +"v^ c #C3C7C1", +"w^ c #C4C8C3", +"x^ c #C5C4C2", +"y^ c #C4C5C3", +"z^ c #BFBFBD", +"A^ c #71695D", +"B^ c #181916", +"C^ c #141711", +"D^ c #131411", +"E^ c #0C0A10", +"F^ c #110F0C", +"G^ c #171B12", +"H^ c #121511", +"I^ c #0F140D", +"J^ c #0B1314", +"K^ c #0C130E", +"L^ c #10120F", +"M^ c #11130E", +"N^ c #0A0E0F", +"O^ c #08130F", +"P^ c #131A15", +"Q^ c #141714", +"R^ c #0F110E", +"S^ c #0C170F", +"T^ c #09150D", +"U^ c #0E150F", +"V^ c #0C120E", +"W^ c #151A18", +"X^ c #060706", +"Y^ c #0F151A", +"Z^ c #C6CFC7", +"`^ c #CACECA", +" / c #C5CAC2", +"./ c #C7C9CA", +"+/ c #C9CCC3", +"@/ c #C7CAC9", +"#/ c #C6CAC9", +"$/ c #C7C8C9", +"%/ c #C6C7BF", +"&/ c #C6C6C1", +"*/ c #C6C7C6", +"=/ c #C2C7C3", +"-/ c #C1C5BE", +";/ c #C4C7C5", +">/ c #C4C2C1", +",/ c #BEC7BE", +"'/ c #C3C7C2", +")/ c #C0C6BE", +"!/ c #C0C6C0", +"~/ c #C7CAC5", +"{/ c #2A221E", +"]/ c #050905", +"^/ c #191B15", +"// c #161412", +"(/ c #0F130F", +"_/ c #0D120C", +":/ c #11120D", +"( c #060A0C", +",( c #0E0E0E", +"'( c #0C130F", +")( c #0A1009", +"!( c #111911", +"~( c #577076", +"{( c #CDCBC8", +"]( c #C4CBC7", +"^( c #C8CBC2", +"/( c #C2C7C6", +"(( c #CBD0CD", +"_( c #D0D0D0", +":( c #E1E1E2", +"<( c #72746E", +"[( c #656861", +"}( c #EDEFE9", +"|( c #C3C7C6", +"1( c #C9C6C2", +"2( c #C3C8C0", +"3( c #EBF2F1", +"4( c #8A8077", +"5( c #161A12", +"6( c #151514", +"7( c #11150E", +"8( c #13130F", +"9( c #131811", +"0( c #141814", +"a( c #0E110F", +"b( c #0B110B", +"c( c #10110D", +"d( c #0C1110", +"e( c #0C140F", +"f( c #09130E", +"g( c #05130F", +"h( c #111711", +"i( c #060D0D", +"j( c #171915", +"k( c #0D1510", +"l( c #08150E", +"m( c #0A110E", +"n( c #0D100B", +"o( c #9BACAA", +"p( c #CACAC9", +"q( c #C7CCC9", +"r( c #C2C8C1", +"s( c #C0C5C2", +"t( c #C6C9C7", +"u( c #BEC4C2", +"v( c #CECFCD", +"w( c #DFE0D9", +"x( c #DFDFDC", +"y( c #BBBEBD", +"z( c #DEE4DF", +"A( c #D4D8D2", +"B( c #DDDED9", +"C( c #D7D7D5", +"D( c #64665C", +"E( c #878A81", +"F( c #D9DBD7", +"G( c #C5C8C0", +"H( c #C3C8C2", +"I( c #EFF4F1", +"J( c #776451", +"K( c #000200", +"L( c #151C14", +"M( c #131311", +"N( c #0F130D", +"O( c #111211", +"P( c #090E0D", +"Q( c #09110E", +"R( c #0A110F", +"S( c #08120E", +"T( c #0B1212", +"U( c #0A130F", +"V( c #0C150F", +"W( c #0C120C", +"X( c #0D0F0C", +"Y( c #070D0E", +"Z( c #121A16", +"`( c #0A130B", +" _ c #0B120E", +"._ c #0C1513", +"+_ c #0A1311", +"@_ c #10110E", +"#_ c #111A16", +"$_ c #060E08", +"%_ c #000002", +"&_ c #D2DCDC", +"*_ c #C5C9C2", +"=_ c #C4CAC5", +"-_ c #C9C7C6", +";_ c #C5CAC7", +">_ c #C6C5C5", +",_ c #D5DCD9", +"'_ c #E5E8E8", +")_ c #D2D6D0", +"!_ c #E6E6E9", +"~_ c #E0E1DD", +"{_ c #DFE5E0", +"]_ c #DDDFD7", +"^_ c #C0C7C3", +"/_ c #DBDFDC", +"(_ c #B2B6AE", +"__ c #ABAFA6", +":_ c #E0E5E9", +"<_ c #959286", +"[_ c #4B4842", +"}_ c #3C3F3B", +"|_ c #898E89", +"1_ c #82817F", +"2_ c #858B84", +"3_ c #3B3932", +"4_ c #84888B", +"5_ c #767A79", +"6_ c #CBCFCD", +"7_ c #C3C5C4", +"8_ c #C5C4BE", +"9_ c #C3CAC3", +"0_ c #C8C6C3", +"a_ c #C4C9C1", +"b_ c #C7C7C2", +"c_ c #C5C9C3", +"d_ c #C3C6C5", +"e_ c #C4C3C0", +"f_ c #C5C6C6", +"g_ c #C6C9C6", +"h_ c #55563B", +"i_ c #020302", +"j_ c #0D110F", +"k_ c #0C120B", +"l_ c #09100C", +"m_ c #151615", +"n_ c #0D0E10", +"o_ c #0C1311", +"p_ c #0D100F", +"q_ c #061610", +"r_ c #081110", +"s_ c #0B1111", +"t_ c #08120F", +"u_ c #0B110F", +"v_ c #04070B", +"w_ c #0E1016", +"x_ c #171919", +"y_ c #0C1212", +"z_ c #091210", +"A_ c #0B1410", +"B_ c #0B120F", +"C_ c #09130C", +"D_ c #111D17", +"E_ c #000703", +"F_ c #394050", +"G_ c #C6CDC6", +"H_ c #C3CBC6", +"I_ c #C4C9C6", +"J_ c #C7CBC9", +"K_ c #CACAC6", +"L_ c #D8DED8", +"M_ c #BCBFB5", +"N_ c #8C8C8C", +"O_ c #D0D1CF", +"P_ c #DCE0DE", +"Q_ c #91918D", +"R_ c #373931", +"S_ c #8E8D8D", +"T_ c #EAECE6", +"U_ c #53514B", +"V_ c #C7CFC7", +"W_ c #F6F9F6", +"X_ c #4F4E4D", +"Y_ c #242C28", +"Z_ c #ECEBE6", +"`_ c #484136", +" : c #676667", +".: c #898986", +"+: c #666B6C", +"@: c #6C6C65", +"#: c #AFB9BB", +"$: c #71706D", +"%: c #53564E", +"&: c #A7A7A6", +"*: c #D9D9DD", +"=: c #C4C8C0", +"-: c #C2C6C7", +";: c #C3C7C0", +">: c #C2C9C3", +",: c #C6C6C5", +"': c #C6C5C4", +"): c #C6C7C7", +"!: c #C6C6C2", +"~: c #F3F1F0", +"{: c #524E37", +"]: c #030404", +"^: c #171B16", +"/: c #0E1111", +"(: c #0C100C", +"_: c #101211", +":: c #161815", +"<: c #0B100D", +"[: c #0C0F0D", +"}: c #0C1111", +"|: c #0A1210", +"1: c #0F1011", +"2: c #08150D", +"3: c #0B1313", +"4: c #000803", +"5: c #171215", +"6: c #171917", +"7: c #0F1710", +"8: c #0B110E", +"9: c #06150F", +"0: c #041410", +"a: c #101314", +"b: c #0C1010", +"c: c #0A1914", +"d: c #0E1713", +"e: c #9A9FA5", +"f: c #F0F0E6", +"g: c #C3CAC5", +"h: c #C7CCCA", +"i: c #C5C9C6", +"j: c #C0C7BE", +"k: c #AFACA7", +"l: c #42433B", +"m: c #737272", +"n: c #3D3C3D", +"o: c #B3B3B0", +"p: c #282823", +"q: c #A0A1A3", +"r: c #313936", +"s: c #A6AEA2", +"t: c #3E4A45", +"u: c #E2E6E6", +"v: c #9DA098", +"w: c #7C7F73", +"x: c #343535", +"y: c #DBDDDE", +"z: c #757069", +"A: c #272927", +"B: c #3D3F3A", +"C: c #494C43", +"D: c #858B8A", +"E: c #C0C2B9", +"F: c #999D95", +"G: c #111011", +"H: c #DDE3E4", +"I: c #D0D3CF", +"J: c #C6C8C1", +"K: c #C2C6C3", +"L: c #C5C7BF", +"M: c #C8C9C8", +"N: c #BEC1C1", +"O: c #574E3D", +"P: c #030506", +"Q: c #191C19", +"R: c #0B0F0F", +"S: c #100F0D", +"T: c #0E1414", +"U: c #101813", +"V: c #111817", +"W: c #09120F", +"X: c #0D100E", +"Y: c #0E1112", +"Z: c #07120D", +"`: c #0B1512", +" < c #071611", +".< c #08110E", +"+< c #080F0E", +"@< c #08100F", +"#< c #0D1212", +"$< c #0D1613", +"%< c #0C1612", +"&< c #2C2D2B", +"*< c #323530", +"=< c #0B0B06", +"-< c #08120C", +";< c #0E110C", +">< c #0A110D", +",< c #0F1914", +"'< c #060C07", +")< c #0C0F10", +"!< c #CFD4D4", +"~< c #DBE2D5", +"{< c #C9CCCA", +"]< c #C6CAC6", +"^< c #C9C8C3", +"/< c #C4C9C4", +"(< c #CBCAC3", +"_< c #C1C8C2", +":< c #E8EBEB", +"<< c #919083", +"[< c #4D514E", +"}< c #8E9390", +"|< c #5D6061", +"1< c #6F6F64", +"2< c #A5ACAA", +"3< c #52544B", +"4< c #767978", +"5< c #6A7372", +"6< c #F1EFEF", +"7< c #2E2C29", +"8< c #535552", +"9< c #32332A", +"0< c #7B7F7D", +"a< c #5C5C59", +"b< c #C9CFD7", +"c< c #545651", +"d< c #8E9592", +"e< c #787975", +"f< c #4C4E49", +"g< c #636C6C", +"h< c #C8C6C8", +"i< c #D3D6D3", +"j< c #C7C7C6", +"k< c #C3C4C3", +"l< c #C5C8C5", +"m< c #C6CBC1", +"n< c #C9CAC3", +"o< c #BAC0BE", +"p< c #695F50", +"q< c #131B14", +"r< c #0E120D", +"s< c #0C110B", +"t< c #0F1111", +"u< c #161916", +"v< c #0F1611", +"w< c #091511", +"x< c #081511", +"y< c #0D1913", +"z< c #0E1912", +"A< c #08110C", +"B< c #2F2C2B", +"C< c #51444B", +"D< c #0B150E", +"E< c #0E0F0B", +"F< c #0A160F", +"G< c #5E686D", +"H< c #F8F6F6", +"I< c #C7CDBC", +"J< c #C4C9C3", +"K< c #C4C9C7", +"L< c #C7C8CA", +"M< c #C7C7CB", +"N< c #C0C4C1", +"O< c #97978E", +"P< c #232525", +"Q< c #6E7776", +"R< c #414136", +"S< c #71736F", +"T< c #969592", +"U< c #515557", +"V< c #C1B8B5", +"W< c #31302F", +"X< c #7A8177", +"Y< c #5E5F59", +"Z< c #7C817B", +"`< c #DBDBDC", +" [ c #BAB7B6", +".[ c #909491", +"+[ c #B3B4AE", +"@[ c #D7DDD7", +"#[ c #D8D6D1", +"$[ c #7A7E75", +"%[ c #C6CECE", +"&[ c #ABA6A1", +"*[ c #8E928D", +"=[ c #CFD3D1", +"-[ c #C2C8C4", +";[ c #C7C6C5", +">[ c #C8C7C4", +",[ c #C4CAC2", +"'[ c #BDC0BF", +")[ c #F3F3EF", +"![ c #898377", +"~[ c #0E100E", +"{[ c #0E1110", +"][ c #07130F", +"^[ c #0D1515", +"/[ c #1A1C1A", +"([ c #141916", +"_[ c #050A06", +":[ c #050A09", +"<[ c #07100F", +"[[ c #081614", +"}[ c #0C1915", +"|[ c #06130E", +"1[ c #010302", +"2[ c #020705", +"3[ c #000705", +"4[ c #262723", +"5[ c #3D3D38", +"6[ c #0E0B0E", +"7[ c #13100F", +"8[ c #121415", +"9[ c #09100D", +"0[ c #0A1410", +"a[ c #0E1212", +"b[ c #050908", +"c[ c #141719", +"d[ c #C2CACB", +"e[ c #F0EDE8", +"f[ c #A0A496", +"g[ c #C7C8C6", +"h[ c #C4C8C5", +"i[ c #C8C9CB", +"j[ c #62625D", +"k[ c #959697", +"l[ c #464941", +"m[ c #526257", +"n[ c #E5EBE9", +"o[ c #D6D8D3", +"p[ c #74736D", +"q[ c #88978E", +"r[ c #BFC6C0", +"s[ c #9EA197", +"t[ c #868984", +"u[ c #B8C0B7", +"v[ c #868581", +"w[ c #888785", +"x[ c #8C8981", +"y[ c #686B63", +"z[ c #888984", +"A[ c #737874", +"B[ c #9A9A96", +"C[ c #878D8B", +"D[ c #6F6E67", +"E[ c #576261", +"F[ c #E6EAEA", +"G[ c #C6C9C3", +"H[ c #C7C5C4", +"I[ c #C5CAC3", +"J[ c #C1C7C0", +"K[ c #C6C6C7", +"L[ c #E7EDE8", +"M[ c #B1A6A1", +"N[ c #131711", +"O[ c #111311", +"P[ c #0E100D", +"Q[ c #0C0E0C", +"R[ c #071210", +"S[ c #121716", +"T[ c #1B1C1B", +"U[ c #212421", +"V[ c #0B0B0B", +"W[ c #0E0F0F", +"X[ c #131111", +"Y[ c #161515", +"Z[ c #1C1F1F", +"`[ c #222627", +" } c #262526", +".} c #070D06", +"+} c #0F0F0F", +"@} c #0D1110", +"#} c #0C0F0E", +"$} c #0D1412", +"%} c #0A150E", +"&} c #0D1A15", +"*} c #6C7173", +"=} c #BBC0B3", +"-} c #5F5F5D", +";} c #C7C6C4", +">} c #C7C8BE", +",} c #CFD5D5", +"'} c #BEC0BD", +")} c #9FA19C", +"!} c #B8C1BA", +"~} c #B4B5A7", +"{} c #91958E", +"]} c #929496", +"^} c #B8BAB4", +"/} c #6E746B", +"(} c #ACB2AB", +"_} c #AFB0A9", +":} c #727672", +"<} c #B5C2BE", +"[} c #C0C5C0", +"}} c #DFE3DE", +"|} c #6D6F68", +"1} c #9DA6A5", +"2} c #AFB1B1", +"3} c #6F7B78", +"4} c #B5B2AF", +"5} c #45403A", +"6} c #A1ACA5", +"7} c #6F6F68", +"8} c #878F8F", +"9} c #E3E6E5", +"0} c #C4C3C2", +"a} c #C8C8C2", +"b} c #C2C7C5", +"c} c #C4C6C7", +"d} c #C7C5C1", +"e} c #C7CAC8", +"f} c #C8C8BF", +"g} c #C3C6C4", +"h} c #DBE0DE", +"i} c #D5D0CE", +"j} c #0B0D0A", +"k} c #151815", +"l} c #0E140D", +"m} c #0B1511", +"n} c #091110", +"o} c #111615", +"p} c #141411", +"q} c #232723", +"r} c #424541", +"s} c #62615D", +"t} c #7A736F", +"u} c #837976", +"v} c #625D59", +"w} c #252823", +"x} c #090F0C", +"y} c #0F110C", +"z} c #100F10", +"A} c #0F0D10", +"B} c #091510", +"C} c #091612", +"D} c #0C170E", +"E} c #091412", +"F} c #071411", +"G} c #0A1412", +"H} c #080F0B", +"I} c #0D1C18", +"J} c #000603", +"K} c #1C2325", +"L} c #E0E7EA", +"M} c #E7E6E0", +"N} c #6E6F69", +"O} c #4F504C", +"P} c #C8CBC7", +"Q} c #C1C8C0", +"R} c #C7CCC5", +"S} c #DFE0D8", +"T} c #86857E", +"U} c #5A5959", +"V} c #747D77", +"W} c #B6B5AD", +"X} c #2C2827", +"Y} c #99A09D", +"Z} c #878381", +"`} c #2C2D29", +" | c #5D5F58", +".| c #AAAEA7", +"+| c #8C8E89", +"@| c #4F5050", +"#| c #B2B1AE", +"$| c #A3A79D", +"%| c #8E9087", +"&| c #B9BCBB", +"*| c #C0BEB9", +"=| c #9FA69E", +"-| c #D7D9D7", +";| c #CFD0D0", +">| c #9DA09C", +",| c #9DA29D", +"'| c #B5B7B6", +")| c #D5D8D7", +"!| c #C8C4C6", +"~| c #C9C9C3", +"{| c #C9C8C9", +"]| c #C8CECD", +"^| c #282017", +"/| c #070704", +"(| c #171B13", +"_| c #0F100B", +":| c #0F100C", +"<| c #0F0F0B", +"[| c #0B1711", +"}| c #081411", +"|| c #141512", +"1| c #191F1A", +"2| c #1C201A", +"3| c #100F0C", +"4| c #0B0F0D", +"5| c #081611", +"6| c #081410", +"7| c #0B1210", +"8| c #09160F", +"9| c #0D1B16", +"0| c #9BA3A5", +"a| c #FFFFFB", +"b| c #9A9C8F", +"c| c #474547", +"d| c #717073", +"e| c #C5C9C5", +"f| c #DADCDA", +"g| c #81857F", +"h| c #737370", +"i| c #6C7266", +"j| c #6A6C72", +"k| c #C9D1CD", +"l| c #CFD7CF", +"m| c #A3A1A3", +"n| c #6B716D", +"o| c #717E71", +"p| c #B5B9B6", +"q| c #808981", +"r| c #A7AAA9", +"s| c #C7C9C9", +"t| c #D6D3D1", +"u| c #C8C9CA", +"v| c #D7D6D0", +"w| c #E2E5E1", +"x| c #DEDCDA", +"y| c #DADBD8", +"z| c #C5C4C3", +"A| c #7E7870", +"B| c #010000", +"C| c #10140D", +"D| c #10120C", +"E| c #110F0D", +"F| c #08140C", +"G| c #0F110F", +"H| c #131413", +"I| c #070A05", +"J| c #060606", +"K| c #090D09", +"L| c #0E160C", +"M| c #0A0E0C", +"N| c #0A140C", +"O| c #0B130C", +"P| c #0E1610", +"Q| c #09170F", +"R| c #09130D", +"S| c #09150F", +"T| c #07120A", +"U| c #06120B", +"V| c #0C1913", +"W| c #0C1A13", +"X| c #858D93", +"Y| c #B0B2A8", +"Z| c #434340", +"`| c #585759", +" 1 c #939393", +".1 c #C2C8C0", +"+1 c #CED0CF", +"@1 c #A8ACA6", +"#1 c #868D84", +"$1 c #9A9F9C", +"%1 c #C2C7C8", +"&1 c #C7D3CE", +"*1 c #DCD9D5", +"=1 c #D3CECA", +"-1 c #DFE3DF", +";1 c #DDE2DE", +">1 c #DADEDF", +",1 c #D1D4D1", +"'1 c #DBDBD3", +")1 c #D8D9D6", +"!1 c #BDC2BD", +"~1 c #C3BFBE", +"{1 c #BEC2BE", +"]1 c #C4CBC6", +"^1 c #C8C8C6", +"/1 c #C9CBC4", +"(1 c #C4C8BD", +"_1 c #E6E6E8", +":1 c #BDB9B7", +"<1 c #161711", +"[1 c #11110C", +"}1 c #0F120B", +"|1 c #101010", +"11 c #10100D", +"21 c #0A130D", +"31 c #07150D", +"41 c #0C150E", +"51 c #0A120E", +"61 c #09100B", +"71 c #0B100B", +"81 c #0D1513", +"91 c #06120D", +"01 c #091010", +"a1 c #0A1811", +"b1 c #0C1512", +"c1 c #0D1A14", +"d1 c #555F60", +"e1 c #575857", +"f1 c #434345", +"g1 c #878686", +"h1 c #B0AFAD", +"i1 c #C2C8C3", +"j1 c #CCCCCB", +"k1 c #D8DBD7", +"l1 c #E0E2DD", +"m1 c #D6D6D1", +"n1 c #CED3CB", +"o1 c #BEC2BC", +"p1 c #CACAC5", +"q1 c #C3C9C5", +"r1 c #C4C8C7", +"s1 c #C3C9C1", +"t1 c #C9C8C4", +"u1 c #C3C9C4", +"v1 c #C7C6C2", +"w1 c #C8C8C8", +"x1 c #CAC9CA", +"y1 c #CACAC8", +"z1 c #CAC9C8", +"A1 c #D0CFCD", +"B1 c #E8E8E3", +"C1 c #333430", +"D1 c #040604", +"E1 c #161610", +"F1 c #0D160F", +"G1 c #10100F", +"H1 c #0D100D", +"I1 c #0D0F0D", +"J1 c #06110E", +"K1 c #121111", +"L1 c #11120B", +"M1 c #0B1110", +"N1 c #101214", +"O1 c #0B120D", +"P1 c #091313", +"Q1 c #081211", +"R1 c #081510", +"S1 c #06130F", +"T1 c #121513", +"U1 c #121812", +"V1 c #4C505B", +"W1 c #E9EDEF", +"X1 c #D6D7CF", +"Y1 c #7F7E78", +"Z1 c #3F4140", +"`1 c #78777A", +" 2 c #A4A4A2", +".2 c #CAC9CB", +"+2 c #C2C6BE", +"@2 c #C3C6BF", +"#2 c #C0C8C3", +"$2 c #C0C8BF", +"%2 c #C5C7C8", +"&2 c #C2C8C5", +"*2 c #C0CAC0", +"=2 c #C3C8C3", +"-2 c #C3C8C5", +";2 c #C1C8C4", +">2 c #C9C9C4", +",2 c #CCCAC9", +"'2 c #F6FAF7", +")2 c #979697", +"!2 c #131511", +"~2 c #13150F", +"{2 c #0F120C", +"]2 c #09120E", +"^2 c #0D150F", +"/2 c #091112", +"(2 c #0F1213", +"_2 c #081210", +":2 c #0F1013", +"<2 c #0C1113", +"[2 c #151711", +"}2 c #4D4E56", +"|2 c #E6E9EC", +"12 c #E0E2D8", +"22 c #898989", +"32 c #3D3C42", +"42 c #6C6A6B", +"52 c #979797", +"62 c #E1E2E2", +"72 c #C6C5C6", +"82 c #C1C5C3", +"92 c #C3C9C2", +"02 c #C7C9C1", +"a2 c #CACBC5", +"b2 c #C9CCC6", +"c2 c #CBC9CA", +"d2 c #CBCCCA", +"e2 c #3A3938", +"f2 c #020200", +"g2 c #1A1C15", +"h2 c #11120C", +"i2 c #121311", +"j2 c #0C1412", +"k2 c #06140F", +"l2 c #090F0D", +"m2 c #13110E", +"n2 c #08130C", +"o2 c #0F0E0B", +"p2 c #0C110F", +"q2 c #0F1112", +"r2 c #111913", +"s2 c #081009", +"t2 c #5E6569", +"u2 c #E8ECEE", +"v2 c #DEE0D7", +"w2 c #8D8D88", +"x2 c #393838", +"y2 c #62635F", +"z2 c #8F8E8D", +"A2 c #B9B7B7", +"B2 c #DEDCDC", +"C2 c #C2C5C4", +"D2 c #C0C6C1", +"E2 c #C4C2BF", +"F2 c #BCBFBB", +"G2 c #BCBEB7", +"H2 c #BDC2BC", +"I2 c #BBBDB8", +"J2 c #BCBEBA", +"K2 c #BBBCBA", +"L2 c #BFC0BF", +"M2 c #BFC3BF", +"N2 c #C4C4C4", +"O2 c #BDBEBD", +"P2 c #EBEEEC", +"Q2 c #B4B2B1", +"R2 c #080708", +"S2 c #10150D", +"T2 c #121612", +"U2 c #0D130A", +"V2 c #131616", +"W2 c #121A15", +"X2 c #121810", +"Y2 c #121811", +"Z2 c #131B15", +"`2 c #131A17", +" 3 c #101913", +".3 c #111A13", +"+3 c #141813", +"@3 c #000102", +"#3 c #858889", +"$3 c #D7D7CE", +"%3 c #82827C", +"&3 c #363637", +"*3 c #5C5C5C", +"=3 c #858888", +"-3 c #ADAEAF", +";3 c #D6D4D6", +">3 c #F1EDEE", +",3 c #FCFBFB", +"'3 c #C6CCC5", +")3 c #C8CDC9", +"!3 c #CACEC8", +"~3 c #CBCFCB", +"{3 c #CDCDC9", +"]3 c #CACEC9", +"^3 c #CCCCC7", +"/3 c #CCCDC9", +"(3 c #CCCCCC", +"_3 c #CCCDCA", +":3 c #878786", +"<3 c #1B1E18", +"[3 c #131710", +"}3 c #111414", +"|3 c #11100F", +"13 c #0F1713", +"23 c #141912", +"33 c #121B17", +"43 c #10100B", +"53 c #0C0F0B", +"63 c #0A0B0D", +"73 c #090D0C", +"83 c #080807", +"93 c #050503", +"03 c #37393D", +"a3 c #AEB3B3", +"b3 c #71706C", +"c3 c #343434", +"d3 c #575858", +"e3 c #858585", +"f3 c #A9A8A8", +"g3 c #CFCFCF", +"h3 c #BFC1BC", +"i3 c #BDBFBA", +"j3 c #BDC3BC", +"k3 c #CED1CD", +"l3 c #D6D7D4", +"m3 c #F6F9F5", +"n3 c #F6F8F7", +"o3 c #D5D7D5", +"p3 c #D6D9D7", +"q3 c #D4D4D1", +"r3 c #555552", +"s3 c #030502", +"t3 c #1A1F16", +"u3 c #191914", +"v3 c #1A1917", +"w3 c #151A16", +"x3 c #141A12", +"y3 c #0D0E09", +"z3 c #070605", +"A3 c #030503", +"B3 c #020405", +"C3 c #010301", +"D3 c #000107", +"E3 c #0D1B22", +"F3 c #2A3D44", +"G3 c #545F67", +"H3 c #787F83", +"I3 c #8C969D", +"J3 c #9DAAAF", +"K3 c #B1B1B7", +"L3 c #B7BABC", +"M3 c #B9BDBD", +"N3 c #E7E9E9", +"O3 c #F9FBF1", +"P3 c #BBBEB9", +"Q3 c #515052", +"R3 c #373739", +"S3 c #5A5B59", +"T3 c #848483", +"U3 c #A7A7A7", +"V3 c #CBCBCB", +"W3 c #CCCCCA", +"X3 c #D6D6D4", +"Y3 c #F5F6F6", +"Z3 c #FBFAFB", +"`3 c #DDDFDC", +" 4 c #CED3CF", +".4 c #D3D4D0", +"+4 c #CFD1CF", +"@4 c #C9CEC6", +"#4 c #C0C5BD", +"$4 c #474745", +"%4 c #020102", +"&4 c #15160D", +"*4 c #11130A", +"=4 c #0B1006", +"-4 c #060701", +";4 c #040504", +">4 c #040605", +",4 c #060909", +"'4 c #111619", +")4 c #262B31", +"!4 c #39434C", +"~4 c #5B6471", +"{4 c #788E94", +"]4 c #A8BDC4", +"^4 c #D7DADD", +"/4 c #DDDDDB", +"(4 c #DCE0E0", +"_4 c #E1E6E7", +":4 c #E9EEEF", +"<4 c #FFFFFA", +"[4 c #FDFFF4", +"}4 c #EEF2E7", +"|4 c #E6E8DE", +"14 c #E7E6E1", +"24 c #CBCAC4", +"34 c #868A80", +"44 c #3E3D43", +"54 c #393A3A", +"64 c #61615D", +"74 c #868585", +"84 c #DCDDDD", +"94 c #E2E4E0", +"04 c #464A42", +"a4 c #0C0F0F", +"b4 c #111215", +"c4 c #18191A", +"d4 c #1B1E1D", +"e4 c #1E2021", +"f4 c #272D36", +"g4 c #45525D", +"h4 c #6B767F", +"i4 c #909BA2", +"j4 c #A9B5B9", +"k4 c #B8C7C8", +"l4 c #D7E6EA", +"m4 c #F3FAFA", +"n4 c #F9F9F8", +"o4 c #F8FAF4", +"p4 c #F5F6EB", +"q4 c #DCDED6", +"r4 c #CDCEC4", +"s4 c #C2C5B9", +"t4 c #B4B6B1", +"u4 c #AAAAA3", +"v4 c #A6A99E", +"w4 c #A2A49E", +"x4 c #8C8D88", +"y4 c #767770", +"z4 c #676962", +"A4 c #666465", +"B4 c #474846", +"C4 c #343435", +"D4 c #494A4B", +"E4 c #666766", +"F4 c #868686", +"G4 c #A8A9AA", +"H4 c #F9FBFA", +"I4 c #FAFCFA", +"J4 c #D5DADB", +"K4 c #E6EAE9", +"L4 c #F2F5F6", +"M4 c #AFB8B9", +"N4 c #BDC5CA", +"O4 c #DEE4E8", +"P4 c #EEF6F5", +"Q4 c #F6FAF5", +"R4 c #F7F7F4", +"S4 c #EEECE8", +"T4 c #E6E4DF", +"U4 c #DBDBD6", +"V4 c #D9D7D5", +"W4 c #DDDCDA", +"X4 c #E0DFD7", +"Y4 c #D8D8CD", +"Z4 c #CCCEC3", +"`4 c #B6B6AD", +" 5 c #A29F98", +".5 c #898A86", +"+5 c #797B75", +"@5 c #767872", +"#5 c #757671", +"$5 c #666964", +"%5 c #595858", +"&5 c #50514F", +"*5 c #444342", +"=5 c #3E3F3D", +"-5 c #414142", +";5 c #3B3A3A", +">5 c #353436", +",5 c #2E2E2E", +"'5 c #313132", +")5 c #333336", +"!5 c #373838", +"~5 c #474847", +"{5 c #5C5A5B", +"]5 c #6E6E6E", +"^5 c #8C8A8B", +"/5 c #ADAEAC", +"(5 c #CDCECE", +"_5 c #F9FDFF", +":5 c #F9FDFD", +"<5 c #F5F2EF", +"[5 c #C3C2BB", +"}5 c #A9ACA4", +"|5 c #959791", +"15 c #7D7C7A", +"25 c #5B5B59", +"35 c #353633", +"45 c #292C27", +"55 c #313430", +"65 c #2F302E", +"75 c #2F2E2F", +"85 c #2B2B2C", +"95 c #272727", +"05 c #2D2E2D", +"a5 c #323331", +"b5 c #343333", +"c5 c #3A383E", +"d5 c #3E3B3E", +"e5 c #424143", +"f5 c #454347", +"g5 c #4A494A", +"h5 c #4E4F50", +"i5 c #575657", +"j5 c #5B5C5B", +"k5 c #5E5E5C", +"l5 c #616160", +"m5 c #6D6D6D", +"n5 c #7F7F7F", +"o5 c #9A9A9B", +"p5 c #B6B6B4", +"q5 c #D3D4D5", +"r5 c #FBFFFF", +"s5 c #FAFDFF", +"t5 c #FCFFFF", +"u5 c #FAFFFF", +"v5 c #F5FAFC", +"w5 c #E7E6EA", +"x5 c #C7C6C8", +"y5 c #9DA0A0", +"z5 c #8D9193", +"A5 c #86858A", +"B5 c #5F6163", +"C5 c #4A4A4B", +"D5 c #4C4B48", +"E5 c #4B4B49", +"F5 c #454344", +"G5 c #464846", +"H5 c #5A5A58", +"I5 c #636162", +"J5 c #686869", +"K5 c #6D6C6C", +"L5 c #6E6E6C", +"M5 c #727272", +"N5 c #757676", +"O5 c #7D7D7C", +"P5 c #818281", +"Q5 c #858685", +"R5 c #8D8D8E", +"S5 c #9A9A9A", +"T5 c #AEAEAF", +"U5 c #DEDFDD", +"V5 c #EDECEE", +"W5 c #FAF9FA", +"X5 c #FFFDFC", +"Y5 c #D7D9D9", +"Z5 c #B6B9BD", +"`5 c #A7A8AB", +" 6 c #A7A6A8", +".6 c #A3A1A2", +"+6 c #939292", +"@6 c #8B8C8B", +"#6 c #909391", +"$6 c #979997", +"%6 c #9F9F9F", +"&6 c #ADAEAE", +"*6 c #B4B4B4", +"=6 c #BABBBA", +"-6 c #C2C2C2", +";6 c #D9D9D9", +">6 c #FAFFFD", +",6 c #EFF1F3", +"'6 c #DFE0DD", +")6 c #D7D6D4", +"!6 c #DCDBDA", +"~6 c #DEDDDC", +"{6 c #E3E1E2", +"]6 c #FBFCFD", +"^6 c #FAFAFB", +"/6 c #FBFDFD", +"(6 c #FBFFFD", +"_6 c #FFFCFD", +":6 c #FDFFFC", +"<6 c #FAFDFC", +"[6 c #F9FCFD", +"}6 c #FFFCFA", +"|6 c #EFF2F3", +"16 c #ECEEF0", +"26 c #EAEDEE", +"36 c #E3E8E8", +"46 c #E2E6E8", +"56 c #DFE5E7", +"66 c #DCE2E4", +"76 c #D9DFE1", +"86 c #DBE1E3", +"96 c #DAE0E2", +"06 c #C9CFD1", +"a6 c #CCD0D2", +"b6 c #CED3D6", +"c6 c #CFD3D5", +"d6 c #CCD1D3", +"e6 c #CDD4D6", +"f6 c #CDD2D5", +"g6 c #CAD3D5", +"h6 c #D1D5D7", +"i6 c #D0D4D7", +"j6 c #D1D6D8", +"k6 c #D2D6D9", +"l6 c #D3D7DB", +"m6 c #D2D7D9", +"n6 c #D9DDDF", +"o6 c #D7DFDD", +"p6 c #D9E0DF", +"q6 c #DCE1E1", +"r6 c #DDE3E5", +"s6 c #E1E6E9", +"t6 c #E4E8EA", +"u6 c #F5FAF9", +"v6 c #F6F9F9", +"w6 c #F7F8F9", +"x6 c #F9FAFB", +"y6 c #F3F7FB", +"z6 c #F6FAFF", +"A6 c #FCFCFF", +"B6 c #C6CBCA", +"C6 c #C4CDCB", +"D6 c #C4CBCB", +"E6 c #C3CDCB", +"F6 c #C1CCCA", +"G6 c #C7CECC", +"H6 c #C6CFCE", +"I6 c #C5CECD", +"J6 c #C9D1D1", +"K6 c #C8CFCF", +"L6 c #C7D0CF", +"M6 c #D0D9D7", +"N6 c #A6ADAC", +"O6 c #A4AAA9", +"P6 c #AFB5B4", +"Q6 c #ABB2B1", +"R6 c #ADB4B2", +"S6 c #AFB4B4", +"T6 c #B3B9B9", +"U6 c #B1B6B8", +"V6 c #B3B9B6", +"W6 c #B3B9BB", +"X6 c #B4BBBA", +"Y6 c #B7BDBA", +"Z6 c #B6BDBC", +"`6 c #B7BEBE", +" 7 c #B7BDBD", +".7 c #B8BCBC", +"+7 c #B6BEBE", +"@7 c #BBBFC1", +"#7 c #B7C1C3", +"$7 c #B7BFC0", +"%7 c #BCC0C5", +"&7 c #BDC0C3", +"*7 c #BCC1C0", +"=7 c #BEC3C5", +"-7 c #BFC6C6", +";7 c #C1C9C7", +">7 c #BFC8C7", +",7 c #C3CCCC", +"'7 c #C6CED0", +")7 c #D0D8D7", +"!7 c #D4DBD9", +"~7 c #DBDEDE", +"{7 c #DBE1DF", +"]7 c #E2E5E4", +"^7 c #E7EAEA", +"/7 c #F4FAF9", +"(7 c #F0F3F6", +"_7 c #F2F5F8", +":7 c #F0F0F4", +"<7 c #EEF1F3", +"[7 c #F3F7F8", +"}7 c #FAFCFD", +"|7 c #FAFAFD", +"17 c #F6F9FC", +"27 c #F5FCFD", +"37 c #F6FBFF", +"47 c #F5F8FB", +"57 c #F8FAFB", +"67 c #FFFCFC", +"77 c #3C3D3E", +"87 c #393A3B", +"97 c #383A3C", +"07 c #373B3C", +"a7 c #363A3A", +"b7 c #3A3D3C", +"c7 c #3C3E3E", +"d7 c #3A3B3C", +"e7 c #353637", +"f7 c #8D908D", +"g7 c #BBC0BF", +"h7 c #AFB7B4", +"i7 c #BDC5C2", +"j7 c #BBC2BF", +"k7 c #BBC4C0", +"l7 c #BFC3C2", +"m7 c #BFC4C2", +"n7 c #BFC5C4", +"o7 c #BFC5C3", +"p7 c #C1C7C6", +"q7 c #C0C6C7", +"r7 c #C0C7C5", +"s7 c #C2C7C9", +"t7 c #C3CAC9", +"u7 c #C5CAC8", +"v7 c #C4C9C8", +"w7 c #C5CBCA", +"x7 c #C6C9CA", +"y7 c #C5C9C8", +"z7 c #C6CACE", +"A7 c #C6CDCB", +"B7 c #C3C8CB", +"C7 c #C3C9CA", +"D7 c #C2C9CA", +"E7 c #C4CCCC", +"F7 c #C4CCCB", +"G7 c #C0C8C5", +"H7 c #C2C9C8", +"I7 c #C0C7C6", +"J7 c #BEC5C6", +"K7 c #BEC5C5", +"L7 c #BBC6C4", +"M7 c #BBC5C3", +"N7 c #BCC9C7", +"O7 c #C1CACA", +"P7 c #C5CCCC", +"Q7 c #C9D1D0", +"R7 c #C8D0D0", +"S7 c #C9D0D0", +"T7 c #D1D4D5", +"U7 c #D8DCDC", +"V7 c #E0E3E5", +"W7 c #E3E6E8", +"X7 c #EAECEF", +"Y7 c #EEF1F2", +"Z7 c #F6FAF9", +"`7 c #F4F8F7", +" 8 c #F7FAFC", +".8 c #F9FBFC", +"+8 c #F2F1F5", +"@8 c #F0EFF4", +"#8 c #EDF0F2", +"$8 c #F6FCFC", +"%8 c #F4F9FB", +"&8 c #F4FAFB", +"*8 c #F4F8FC", +"=8 c #757575", +"-8 c #C0C5C4", +";8 c #AFB3B2", +">8 c #B5BBBB", +",8 c #BCC1C1", +"'8 c #BAC1C1", +")8 c #BBC1BF", +"!8 c #BBC1C1", +"~8 c #BBC0C1", +"{8 c #BCC1BF", +"]8 c #BEC5C3", +"^8 c #BFC1C3", +"/8 c #BEC3C3", +"(8 c #BFC6C5", +"_8 c #C0C5C5", +":8 c #C2CACA", +"<8 c #C4CAC7", +"[8 c #C2C8C9", +"}8 c #C1C9C9", +"|8 c #C6CDCC", +"18 c #C8CDD0", +"28 c #C5CDCB", +"38 c #C7CECE", +"48 c #C9D0D1", +"58 c #C7CFCF", +"68 c #C8D0CF", +"78 c #CDD2D3", +"88 c #CCD2D2", +"98 c #CAD1D0", +"08 c #CAD0D1", +"a8 c #C9CFD0", +"b8 c #C7CECD", +"c8 c #C4CAC9", +"d8 c #C7CDCD", +"e8 c #C8CCCE", +"f8 c #C3CDCC", +"g8 c #C2CCCB", +"h8 c #C0C8C8", +"i8 c #BEC4C7", +"j8 c #BEC6C7", +"k8 c #BBC6C5", +"l8 c #BDC6C6", +"m8 c #C3CCCD", +"n8 c #C5CBCD", +"o8 c #CBCFD0", +"p8 c #CED3D1", +"q8 c #D5D8D8", +"r8 c #EBEAEE", +"s8 c #FFFCFF", +"t8 c #EBECF0", +"u8 c #EFF2F4", +"v8 c #F9FAF8", +"w8 c #FBFDFF", +"x8 c #020A06", +"y8 c #050804", +"z8 c #080B07", +"A8 c #080C08", +"B8 c #090D0B", +"C8 c #060A09", +"D8 c #090C08", +"E8 c #080D05", +"F8 c #050F08", +"G8 c #090D0A", +"H8 c #090E0B", +"I8 c #666665", +"J8 c #BFC8C5", +"K8 c #B0B7B8", +"L8 c #BAC1BE", +"M8 c #B7BBBD", +"N8 c #B8C0BE", +"O8 c #B9C0BE", +"P8 c #B8C0BD", +"Q8 c #B6C1BF", +"R8 c #BBC3C0", +"S8 c #B9C1C0", +"T8 c #BDC2C3", +"U8 c #B9C0C0", +"V8 c #BCBEC0", +"W8 c #C0C4C5", +"X8 c #BDC2C2", +"Y8 c #BEC1C4", +"Z8 c #BFC3C6", +"`8 c #C0C4C8", +" 9 c #C2C7C7", +".9 c #C2C8C6", +"+9 c #C2C8C7", +"@9 c #C0C6C6", +"#9 c #C3C8C9", +"$9 c #C1CBC6", +"%9 c #BFC9CA", +"&9 c #C6CBCB", +"*9 c #C5CCCB", +"=9 c #C1C9CD", +"-9 c #C4CBCC", +";9 c #C8CDCB", +">9 c #C6CCCC", +",9 c #C7CCCC", +"'9 c #C8CECF", +")9 c #CBD0D0", +"!9 c #CDD1D2", +"~9 c #C8CFCE", +"{9 c #CAD0D0", +"]9 c #CAD1D1", +"^9 c #CACFD0", +"/9 c #CCD2D1", +"(9 c #CCD5D4", +"_9 c #C9D4D2", +":9 c #CAD2D2", +"<9 c #CBD0D1", +"[9 c #CDD4D2", +"}9 c #C7D0CD", +"|9 c #C9D0CF", +"19 c #C3CCCB", +"29 c #C5CDCC", +"39 c #C3C9C9", +"49 c #C0C7C7", +"59 c #BDC6C5", +"69 c #C0C3C4", +"79 c #BDC0C2", +"89 c #BCC4C6", +"99 c #C2C6C9", +"09 c #C7CBCD", +"a9 c #CDD3D6", +"b9 c #D8DEE1", +"c9 c #DFE1E3", +"d9 c #E4E4E6", +"e9 c #EAEFEE", +"f9 c #F4F7F8", +"g9 c #EEEFF1", +"h9 c #020905", +"i9 c #000D08", +"j9 c #020A0A", +"k9 c #020806", +"l9 c #040A05", +"m9 c #030C07", +"n9 c #040807", +"o9 c #020903", +"p9 c #040B06", +"q9 c #03080A", +"r9 c #070D0C", +"s9 c #080E08", +"t9 c #6E6D6B", +"u9 c #B2BEBE", +"v9 c #B4BAB8", +"w9 c #B7BCBA", +"x9 c #B9BABC", +"y9 c #BBBFBF", +"z9 c #BBC0BE", +"A9 c #B6C0BF", +"B9 c #B9C2C1", +"C9 c #BAC2C0", +"D9 c #BEC2C3", +"E9 c #BAC3C3", +"F9 c #BCC1C2", +"G9 c #BDC3C2", +"H9 c #BDC1C2", +"I9 c #C1C4C5", +"J9 c #C0C4C4", +"K9 c #BEC4C4", +"L9 c #BFC5C6", +"M9 c #C1C6C8", +"N9 c #C3C7C7", +"O9 c #C4C9CB", +"P9 c #C8CDCE", +"Q9 c #C7C8CB", +"R9 c #C6CDCD", +"S9 c #C9CECF", +"T9 c #C7CCCD", +"U9 c #C8CDCD", +"V9 c #C8CECE", +"W9 c #CBD1D1", +"X9 c #C9CFCF", +"Y9 c #C7D0D0", +"Z9 c #C9D2D2", +"`9 c #C9CBCD", +" 0 c #C6C9CB", +".0 c #C9CDCF", +"+0 c #CBCFD1", +"@0 c #CDD4D4", +"#0 c #C6CFCB", +"$0 c #C9CDCD", +"%0 c #C5CBC9", +"&0 c #C0C4C6", +"*0 c #BCC6C3", +"=0 c #BBBFBE", +"-0 c #B8BFBC", +";0 c #B9BEBE", +">0 c #BBC0C2", +",0 c #C0C4C3", +"'0 c #C4C8C8", +")0 c #C6CFCF", +"!0 c #D8DCDE", +"~0 c #F7F7F8", +"{0 c #EEEEF1", +"]0 c #E3E6E9", +"^0 c #EAECF0", +"/0 c #07100C", +"(0 c #050906", +"_0 c #020B08", +":0 c #020807", +"<0 c #000B05", +"[0 c #030A06", +"}0 c #040907", +"|0 c #010B08", +"10 c #020808", +"20 c #0B0E0B", +"30 c #070F0A", +"40 c #7B7D7F", +"50 c #ADB6B8", +"60 c #B5BDBA", +"70 c #BBBBBB", +"80 c #B3BABA", +"90 c #B7BEBF", +"00 c #B9BFBE", +"a0 c #BAC0C0", +"b0 c #B8BEBF", +"c0 c #B7BFBE", +"d0 c #BCC4C4", +"e0 c #B9C3BF", +"f0 c #BDC2C0", +"g0 c #BDC5C4", +"h0 c #BCC3C3", +"i0 c #BEC6C5", +"j0 c #BEC7C6", +"k0 c #C0C7CA", +"l0 c #BDC3C6", +"m0 c #BFC6C4", +"n0 c #C1C7C4", +"o0 c #C2C8C8", +"p0 c #C6C9CC", +"q0 c #C2CDC8", +"r0 c #BFCAC9", +"s0 c #C3CBCE", +"t0 c #C2CAC8", +"u0 c #C7C9CB", +"v0 c #CACECF", +"w0 c #CACCCD", +"x0 c #C6D0CE", +"y0 c #C8CBCE", +"z0 c #CACDD0", +"A0 c #C6CBCC", +"B0 c #C9CED0", +"C0 c #C9CDD0", +"D0 c #C9CCCC", +"E0 c #C5C8C9", +"F0 c #C7CCCB", +"G0 c #CACBCE", +"H0 c #CBD0D3", +"I0 c #CBCECF", +"J0 c #CBCDCF", +"K0 c #CACDCE", +"L0 c #C7CACB", +"M0 c #C1C7C9", +"N0 c #BBBEBF", +"O0 c #B6BDBE", +"P0 c #B3BDBD", +"Q0 c #B0B9B8", +"R0 c #B5BABA", +"S0 c #C9CDCE", +"T0 c #CED2D2", +"U0 c #D7DBDC", +"V0 c #E0E4E4", +"W0 c #080E06", +"X0 c #020902", +"Y0 c #040903", +"Z0 c #010804", +"`0 c #000906", +" a c #040802", +".a c #010902", +"+a c #010807", +"@a c #030908", +"#a c #040906", +"$a c #010904", +"%a c #020B0B", +"&a c #020E0C", +"*a c #070D0A", +"=a c #AAACA8", +"-a c #D9DBE2", +";a c #A9AEAE", +">a c #B7C1BA", +",a c #B3BCBB", +"'a c #B4BABE", +")a c #B6BCBA", +"!a c #B4C1BB", +"~a c #BABDBE", +"{a c #BABFBD", +"]a c #BCC2C0", +"^a c #BDC2C4", +"/a c #BBC3C2", +"(a c #B8C2C0", +"_a c #BEC8C6", +":a c #C0C8C6", +"b c #C4CACC", +",b c #C1C8C8", +"'b c #C2CBC9", +")b c #C0C8C7", +"!b c #C0C5C6", +"~b c #C3C5C7", +"{b c #C1C3C6", +"]b c #C1C6C7", +"^b c #BBC2C2", +"/b c #B9BEC1", +"(b c #B4BCBC", +"_b c #B1B9B7", +":b c #ABB4B2", +"c c #010708", +",c c #0A060B", +"'c c #030909", +")c c #080D0D", +"!c c #000001", +"~c c #141311", +"{c c #D0DBDE", +"]c c #A8B1B0", +"^c c #B7BDBC", +"/c c #B6BBBD", +"(c c #B8BBBB", +"_c c #B9BDBF", +":c c #B7C0BE", +"d c #BBC1C4", +",d c #BBC2C1", +"'d c #BAC6C3", +")d c #BDC5C8", +"!d c #C0C7C8", +"~d c #C3C7CA", +"{d c #C2C8CA", +"]d c #C0CACA", +"^d c #C4C7C8", +"/d c #C1C8CA", +"(d c #C2CCC8", +"_d c #C1CAC8", +":d c #C2C5C8", +"e c #ABB4B5", +",e c #AFB4B6", +"'e c #B0B5B7", +")e c #AAB4B1", +"!e c #ABB2B2", +"~e c #ADB0B1", +"{e c #ACB0B1", +"]e c #AAB2B0", +"^e c #ABAFB3", +"/e c #A9AEB0", +"(e c #A6AAAC", +"_e c #A4A8AB", +":e c #9CA3A4", +"f c #A9ADB1", +",f c #A9AFAF", +"'f c #AAAEAD", +")f c #A7AAAD", +"!f c #A5ACAC", +"~f c #AAAAAD", +"{f c #B5BEC1", +"]f c #C0C5C7", +"^f c #B4B8B9", +"/f c #BCC0C1", +"(f c #C7CBCB", +"_f c #D7D9DA", +":f c #DDDDDE", +"g c #04080B", +",g c #01090B", +"'g c #040E0B", +")g c #444644", +"!g c #D6DEDA", +"~g c #B2B7BA", +"{g c #B5BAB6", +"]g c #B2BABA", +"^g c #B4BBB9", +"/g c #B3BAB6", +"(g c #B5BFBA", +"_g c #B6BBBF", +":g c #B9BCBE", +"h c #C0C3C6", +",h c #BBC3C4", +"'h c #BCC6C7", +")h c #BDC3C5", +"!h c #BCC6C4", +"~h c #BDC7C6", +"{h c #C1C6C5", +"]h c #BEC6C3", +"^h c #C4C8CA", +"/h c #BAC2C2", +"(h c #BCC1C5", +"_h c #BBC2C3", +":h c #BBC4C3", +"i c #B1B9B9", +",i c #B1B4B8", +"'i c #B0B6B6", +")i c #AEB7B6", +"!i c #ADB5B4", +"~i c #B0B5B3", +"{i c #B3B4B5", +"]i c #AEB0B4", +"^i c #ACB0B2", +"/i c #ACB1B0", +"(i c #AAB1B0", +"_i c #A9ADAF", +":i c #A9ABAE", +"j c #9BA19F", +",j c #DCE0E2", +"'j c #898D8C", +")j c #070807", +"!j c #090F0E", +"~j c #080909", +"{j c #050B09", +"]j c #040B0A", +"^j c #020809", +"/j c #080A0B", +"(j c #090709", +"_j c #0E0E13", +":j c #081113", +"k c #060808", +",k c #04070A", +"'k c #050808", +")k c #050909", +"!k c #050D0A", +"~k c #050C09", +"{k c #0D0E0F", +"]k c #08110F", +"^k c #020805", +"/k c #020804", +"(k c #020A03", +"_k c #010907", +":k c #000B04", +"l c #020709", +",l c #000809", +"'l c #000807", +")l c #010703", +"!l c #000503", +"~l c #090A0C", +"{l c #0B1012", +"]l c #040F0F", +"^l c #060B08", +"/l c #020404", +"(l c #000209", +"_l c #000106", +":l c #000203", +"m c #070C0C", +",m c #030A09", +"'m c #070B0A", +")m c #020505", +"!m c #000104", +"~m c #000005", +"{m c #010001", +"]m c #3A3936", +"^m c #D5DBDA", +"/m c #B7BDBE", +"(m c #B3BDB7", +"_m c #B3BDBE", +":m c #ACB4B7", +"n c #B5C2BF", +",n c #B2BABB", +"'n c #B3BDBC", +")n c #BCBCBE", +"!n c #B2B7B9", +"~n c #B3BBB8", +"{n c #ACB8B8", +"]n c #DFDBD4", +"^n c #C7C9C8", +"/n c #A4B1AF", +"(n c #D3DBD4", +"_n c #CDCCC6", +":n c #6D7F91", +"o c #959B9A", +",o c #7F8484", +"'o c #BBC6C1", +")o c #798180", +"!o c #555957", +"~o c #B2BBB7", +"{o c #9FA8A4", +"]o c #A0A9A3", +"^o c #A1ABA5", +"/o c #8F9694", +"(o c #BEC2C1", +"_o c #96A09C", +":o c #A0ABA6", +"p c #B2BBB8", +",p c #9DA1A1", +"'p c #A3A9A8", +")p c #98A29E", +"!p c #A5A8A8", +"~p c #A8ACAC", +"{p c #CED3D2", +"]p c #D1DADB", +"^p c #808A8C", +"/p c #AFB5B2", +"(p c #A1A9AD", +"_p c #B2B7B5", +":p c #B0B3B0", +"
QmitkToolTrackingStatusWidget.h
+ 1 + + + QmitkTrackingDeviceConfigurationWidget + QWidget +
QmitkTrackingDeviceConfigurationWidget.h
+ 1 +
+ + + + diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkNavigationDataCSVSequentialPlayer.cpp b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkNavigationDataCSVSequentialPlayer.cpp new file mode 100644 index 0000000000..a7fca9f3ca --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkNavigationDataCSVSequentialPlayer.cpp @@ -0,0 +1,210 @@ +/*=================================================================== + +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. + +===================================================================*/ +#define _USE_MATH_DEFINES +#include "mitkNavigationDataCSVSequentialPlayer.h" +#include +#include +#include +#include +#include + +mitk::NavigationDataCSVSequentialPlayer::NavigationDataCSVSequentialPlayer() + : mitk::NavigationDataPlayerBase() +{ + m_NavigationDatas = std::vector(); + m_CurrentPos = 0; + m_Filetype = mitk::NavigationDataCSVSequentialPlayer::NavigationDataCSV; +} + +mitk::NavigationDataCSVSequentialPlayer::~NavigationDataCSVSequentialPlayer() +{ +} + +bool mitk::NavigationDataCSVSequentialPlayer::IsAtEnd() +{ + if (m_CurrentPos >= m_NavigationDatas.size()) return true; + else return false; +} + +void mitk::NavigationDataCSVSequentialPlayer:: +SetFileName(const std::string& fileName) +{ + this->SetNumberOfOutputs(1); + FillOutputEmpty(0); + + MITK_INFO << "Reading file: " << fileName; + m_NavigationDatas = GetNavigationDatasFromFile(fileName); + + this->Modified(); +} + +void mitk::NavigationDataCSVSequentialPlayer::FillOutputEmpty(int number) +{ + this->SetNthOutput(number, GetEmptyNavigationData()); +} + +mitk::NavigationData::Pointer mitk::NavigationDataCSVSequentialPlayer::GetEmptyNavigationData() +{ + mitk::NavigationData::Pointer emptyNd = mitk::NavigationData::New(); + mitk::NavigationData::PositionType position; + mitk::NavigationData::OrientationType orientation(0.0, 0.0, 0.0, 0.0); + position.Fill(0.0); + + emptyNd->SetPosition(position); + emptyNd->SetOrientation(orientation); + emptyNd->SetDataValid(false); + return emptyNd; +} + +void mitk::NavigationDataCSVSequentialPlayer::GenerateData() +{ + for (unsigned int index = 0; index < this->GetNumberOfOutputs(); index++) + { + mitk::NavigationData* output = this->GetOutput(index); + + if (m_CurrentPos > m_NavigationDatas.size()) + { + FillOutputEmpty(index); + return; + } + + output->Graft(this->m_NavigationDatas.at(m_CurrentPos)); + m_CurrentPos++; + } +} + +void mitk::NavigationDataCSVSequentialPlayer::UpdateOutputInformation() +{ + this->Modified(); // make sure that we need to be updated + Superclass::UpdateOutputInformation(); +} + +std::vector mitk::NavigationDataCSVSequentialPlayer::GetNavigationDatasFromFile(std::string filename) +{ + std::vector returnValue = std::vector(); + std::vector fileContentLineByLine = GetFileContentLineByLine(filename); + for (int i = 1; (i < fileContentLineByLine.size()); i = i + 24) //skip header so start at 1 + { + returnValue.push_back(GetNavigationDataOutOfOneLine(fileContentLineByLine.at(i))); + } + + return returnValue; +} + +std::vector mitk::NavigationDataCSVSequentialPlayer::GetFileContentLineByLine(std::string filename) +{ + std::vector readData = std::vector(); + + //save old locale + char * oldLocale; + oldLocale = setlocale(LC_ALL, 0); + + //define own locale + std::locale C("C"); + setlocale(LC_ALL, "C"); + + //read file + std::ifstream file; + file.open(filename.c_str(), std::ios::in); + if (file.good()) + { + //read out file + file.seekg(0L, std::ios::beg); // move to begin of file + while (!file.eof()) + { + std::string buffer; + std::getline(file, buffer); // read out file line by line + if (buffer.size() > 0) readData.push_back(buffer); + } + } + + file.close(); + + //switch back to old locale + setlocale(LC_ALL, oldLocale); + + return readData; +} + +mitk::NavigationData::Pointer mitk::NavigationDataCSVSequentialPlayer::GetNavigationDataOutOfOneLine(std::string line) +{ + mitk::NavigationData::Pointer returnValue = mitk::NavigationData::New(); + + QString myLine = QString(line.c_str()); + + QStringList myLineList = myLine.split(';'); + + mitk::Point3D position; + mitk::Quaternion orientation; + bool valid = false; + double time; + + if (m_Filetype = mitk::NavigationDataCSVSequentialPlayer::NavigationDataCSV) + { + if (myLineList.size() < 10) + { + MITK_ERROR << "Error: cannot read line: only found " << myLineList.size() << " fields. Last field: " << myLineList.at(myLineList.size() - 1).toStdString(); + returnValue = GetEmptyNavigationData(); + return returnValue; + } + + time = myLineList.at(2).toDouble(); + + if (myLineList.at(3).toStdString() == "1") valid = true; + + position[0] = myLineList.at(4).toDouble(); + position[1] = myLineList.at(5).toDouble(); + position[2] = myLineList.at(6).toDouble(); + + double euler1 = (myLineList.at(11).toDouble() / 180 * M_PI); + double euler2 = (myLineList.at(12).toDouble() / 180 * M_PI); + double euler3 = (myLineList.at(13).toDouble() / 180 * M_PI); + mitk::Quaternion eulerQuat(euler3, euler2, euler1); + orientation = eulerQuat; + } + else + { + if (myLineList.size() < 10) + { + MITK_ERROR << "Error: cannot read line: only found " << myLineList.size() << " fields. Last field: " << myLineList.at(myLineList.size() - 1).toStdString(); + returnValue = GetEmptyNavigationData(); + return returnValue; + } + + //time = myLineList.at(2).toDouble(); + + //if (myLineList.at(2).toStdString() == "true") + //valid-flag wurde hier nicht gespeichert + valid = true; + + position[0] = myLineList.at(4).toDouble(); + position[1] = myLineList.at(5).toDouble(); + position[2] = myLineList.at(6).toDouble(); + + double euler1 = (myLineList.at(11).toDouble() / 180 * M_PI); + double euler2 = (myLineList.at(12).toDouble() / 180 * M_PI); + double euler3 = (myLineList.at(13).toDouble() / 180 * M_PI); + mitk::Quaternion eulerQuat(euler3, euler2, euler1); + orientation = eulerQuat; + } + + //returnValue->SetTimeStamp(time); //DOES NOT WORK ANY MORE... CANNOT SET TIME TO itk::timestamp CLASS + returnValue->SetDataValid(valid); + returnValue->SetPosition(position); + returnValue->SetOrientation(orientation); + + return returnValue; +} diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkNavigationDataCSVSequentialPlayer.h b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkNavigationDataCSVSequentialPlayer.h new file mode 100644 index 0000000000..457ae7771c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkNavigationDataCSVSequentialPlayer.h @@ -0,0 +1,97 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + + +#ifndef MITKNavigationDataCSVSequentialPlayer_H_HEADER_INCLUDED_ +#define MITKNavigationDataCSVSequentialPlayer_H_HEADER_INCLUDED_ + +#include +#include "tinyxml.h" + + +namespace mitk +{ + + /**Documentation + * \brief This class is a NavigationDataPlayer which can play CSV formatted + * files in sequential order, which means it doesn't + * care about timestamps and just + * outputs the navigationdatas in their sequential order + * + * \ingroup IGT + */ + class NavigationDataCSVSequentialPlayer + : public NavigationDataPlayerBase + { + public: + + enum Filetype + { + NavigationDataCSV, + ManualLoggingCSV + }; + + mitkClassMacro(NavigationDataCSVSequentialPlayer, NavigationDataPlayerBase); + itkNewMacro(Self); + + /** + * \brief sets the file name and path (if XMLString is set, this is neglected) + */ + void SetFileName(const std::string& _FileName); + + /** + * \brief returns the file name and path + */ + itkGetStringMacro(FileName); + + itkSetMacro(Filetype,Filetype); + + bool IsAtEnd(); + + /** + * \brief Used for pipeline update just to tell the pipeline + * that we always have to update + */ + virtual void UpdateOutputInformation(); + + protected: + NavigationDataCSVSequentialPlayer(); + virtual ~NavigationDataCSVSequentialPlayer(); + + /// + /// do the work here + /// + virtual void GenerateData(); + + std::string m_FileName; + + int m_CurrentPos; + Filetype m_Filetype; + + //member for the navigation datas which were read (only one output is supported at the moment) + std::vector m_NavigationDatas; + + std::vector GetNavigationDatasFromFile(std::string filename); + std::vector GetFileContentLineByLine(std::string filename); + mitk::NavigationData::Pointer GetNavigationDataOutOfOneLine(std::string line); + + void FillOutputEmpty(int number); + mitk::NavigationData::Pointer GetEmptyNavigationData(); + + }; +} // namespace mitk + +#endif /* MITKNavigationDataCSVSequentialPlayer_H_HEADER_INCLUDED_ */ diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkPluginActivator.cpp b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkPluginActivator.cpp new file mode 100644 index 0000000000..daf9692487 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkPluginActivator.cpp @@ -0,0 +1,39 @@ +/*========================================================================= + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +=========================================================================*/ + +#include "mitkPluginActivator.h" + +#include + +#include "QmitkIGTTrackingSemiAutomaticMeasurementView.h" +#include "QmitkIGTTrackingDataEvaluationView.h" + +namespace mitk { + void PluginActivator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(QmitkIGTTrackingSemiAutomaticMeasurementView, context) + BERRY_REGISTER_EXTENSION_CLASS(QmitkIGTTrackingDataEvaluationView, context) + } + + void PluginActivator::stop(ctkPluginContext* context) + { + Q_UNUSED(context) + } +} + +#if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) +Q_EXPORT_PLUGIN2(org_mitk_gui_qt_igttrackingsemiautomaticmeasurement, mitk::PluginActivator) +#endif diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkPluginActivator.h b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkPluginActivator.h new file mode 100644 index 0000000000..08f307e628 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkPluginActivator.h @@ -0,0 +1,43 @@ +/*=================================================================== + +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 MITKPLUGINACTIVATOR_H +#define MITKPLUGINACTIVATOR_H + +#include + +namespace mitk { + +class PluginActivator : + public QObject, public ctkPluginActivator +{ + Q_OBJECT + #if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0) + Q_PLUGIN_METADATA(IID "org_mitk_gui_qt_igtapphummelprotocolmeasurements") + #endif + Q_INTERFACES(ctkPluginActivator) + +public: + + void start(ctkPluginContext* context); + void stop(ctkPluginContext* context); + +}; // PluginActivator + +} + +#endif // MITKPLUGINACTIVATOR_H

q c #A4AEAB", +",q c #969C9A", +"'q c #454B49", +")q c #8B9691", +"!q c #7F8B8B", +"~q c #9FA4A7", +"{q c #AFB2B1", +"]q c #ABB0AF", +"^q c #C8CED0", +"/q c #939999", +"(q c #44484B", +"_q c #C2C5C6", +":q c #59595B", +"r c #525656", +",r c #485052", +"'r c #858587", +")r c #9EA39D", +"!r c #313536", +"~r c #515257", +"{r c #6C7271", +"]r c #70767A", +"^r c #1B1A1C", +"/r c #A2A5A6", +"(r c #666A6C", +"_r c #919696", +":r c #485051", +"s c #B2B9B8", +",s c #56595C", +"'s c #57585D", +")s c #D8D8D9", +"!s c #4F4F54", +"~s c #999FA0", +"{s c #9FA5A1", +"]s c #737475", +"^s c #727575", +"/s c #8E9394", +"(s c #8B888B", +"_s c #292E2F", +":s c #A7B2B2", +"t c #8B9591", +",t c #9EA3A7", +"'t c #46464A", +")t c #858D91", +"!t c #C7CBCF", +"~t c #ABB1AE", +"{t c #ADB3B2", +"]t c #ACB1B1", +"^t c #A5A9AB", +"/t c #D7DFDC", +"(t c #757776", +"_t c #000003", +":t c #030304", +"u c #0A0808", +",u c #303231", +"'u c #D8DEDF", +")u c #A5ABB1", +"!u c #B6BCB7", +"~u c #B3C0BE", +"{u c #B4BDBD", +"]u c #B0BABA", +"^u c #B4BABD", +"/u c #ACB5B7", +"(u c #ABB2AF", +"_u c #AAAEAF", +":u c #AEAEB1", +"v c #A5AFAD", +",v c #A2ABAB", +"'v c #A2AEAB", +")v c #A5ADA8", +"!v c #A2A9AB", +"~v c #A0A9AA", +"{v c #A4ABA9", +"]v c #A6AAA8", +"^v c #A0ACAB", +"/v c #A3A9AB", +"(v c #A4A8A9", +"_v c #A0A6A4", +":v c #A2ACA6", +"w c #AEB2B3", +",w c #A9B1B2", +"'w c #ADAFB0", +")w c #CDD3D3", +"!w c #010401", +"~w c #0C0C0A", +"{w c #464B48", +"]w c #414544", +"^w c #4D4F50", +"/w c #818789", +"(w c #A1A4A4", +"_w c #E3E7E6", +":w c #E8EDE9", +"x c #ACAFAF", +",x c #AAB2AD", +"'x c #ADB3B1", +")x c #ABB1AF", +"!x c #DEE3E2", +"~x c #313432", +"{x c #010300", +"]x c #020401", +"^x c #191B19", +"/x c #696A6A", +"(x c #656260", +"_x c #5D5D5C", +":x c #545355", +"y c #BBC3BF", +",y c #BAC0C2", +"'y c #B1B9BA", +")y c #A7AEAD", +"!y c #A1ACAC", +"~y c #A5A7A9", +"{y c #A3A7A8", +"]y c #A2AAA7", +"^y c #A3A7A5", +"/y c #A1A5A3", +"(y c #A1A7A4", +"_y c #A2A7A5", +":y c #A4A9AB", +"z c #ABAFAE", +",z c #ABB3AF", +"'z c #AAB2AF", +")z c #E6EAE8", +"!z c #52514E", +"~z c #000900", +"{z c #0F110A", +"]z c #090C04", +"^z c #D7D7D7", +"/z c #B3B3B3", +"(z c #AAAAAA", +"_z c #A3A3A3", +":z c #7C7C7C", +"A c #9CA2A0", +",A c #9BA2A0", +"'A c #9FA4A3", +")A c #9FA4A2", +"!A c #9BA0A0", +"~A c #9AA3A2", +"{A c #9CA6A4", +"]A c #9AA4A2", +"^A c #9EA7A4", +"/A c #9EA8A2", +"(A c #A2AAA5", +"_A c #A2A7A9", +":A c #A0A9A6", +"B c #030204", +",B c #070601", +"'B c #050600", +")B c #050602", +"!B c #030700", +"~B c #DADDDB", +"{B c #D5D5D5", +"]B c #BEBDBE", +"^B c #B8B8B8", +"/B c #A9A9A9", +"(B c #919191", +"_B c #818182", +":B c #7A7B7B", +"C c #3B393B", +",C c #3B3C3A", +"'C c #464644", +")C c #565757", +"!C c #656566", +"~C c #666866", +"{C c #6A6C6A", +"]C c #737577", +"^C c #808483", +"/C c #959694", +"(C c #97A09D", +"_C c #9C9E9C", +":C c #9EA6A2", +"D c #090F08", +",D c #B5B5B5", +"'D c #AEAEAE", +")D c #A8A9A8", +"!D c #A0A0A0", +"~D c #8E8E8E", +"{D c #848584", +"]D c #7D7D7D", +"^D c #6C6C6D", +"/D c #585959", +"(D c #535253", +"_D c #4B4D4C", +":D c #484848", +"E c #AEB5B2", +",E c #7D7D7B", +"'E c #555659", +")E c #3D3F40", +"!E c #313232", +"~E c #2A2B2C", +"{E c #2A2A2B", +"]E c #BCBDBD", +"^E c #B7B6B6", +"/E c #B2B1B2", +"(E c #ACACAC", +"_E c #A4A4A4", +":E c #8F8E8E", +"F c #757675", +",F c #6E6D6E", +"'F c #646565", +")F c #606061", +"!F c #5C5B5B", +"~F c #595A59", +"{F c #545555", +"]F c #4F4F4F", +"^F c #454544", +"/F c #414140", +"(F c #3E4040", +"_F c #3B3939", +":F c #3C3838", +" , ' ) ! ~ { ~ ~ ] ^ / ( _ ) ) ) ) : < ^ [ } ~ { | 1 | ( ) = * 2 * { @ @ . . . . . . . . . . . . . @ . @ . . . . . . @ * . . . . . . . . . . . . . . . . . . . ", +". @ @ @ . @ . @ + . . . . . . . . . . . . . . . . . . . % + = * = ~ 3 4 4 5 6 7 8 9 9 9 0 a b c d c e f g h i j j j k l m n f o p q r s t u v w x y l z f k A B n C D E F G H I 9 J ) { { { * = @ . . . . . . . . . @ @ . @ @ . . . . . . . . . . . . . . . . . . . ", +". . . K L + @ @ + @ @ + & M N O P Q P R S T U V W X w v A Y Z ` . ...+. . .+.+.@.m m m m v #.l h n $.l $.W %.j &.@.n #.h *.=.m -.-.;.>.W y v ,.'.-.).!.~.{.k ].z l z z ^.k &.&./.(._.(.:.(./.<.[.}.|.1.2.3.4.5.= @ + @ @ @ . . . @ . @ . . . . . . . . . . . . . . ", +"6.7.8.9.0.d $.a.'.m .+.p h b.c.d.e.f. .h .v g.h.i.j.k.*.l.w n m.$.n.x -.o.0.'.p.q.r.l.s.b ^.F }.c F t.u.v.w.F x.y.X z.d w d A.|.B.|.}.C.D.V E.X F.B.G.F.H.I.v.J.w K.E ^.A.}.}.p.n.y.v.L.|.B.v.M.N.v.v./.&.O.P.[.N./.}.Q.R.S.T.+ . . . . . . . . . @ . . . . . . . ", +"` U...V.W.h X.Y.Z.W y $.v #.`.F c +.+e ++@+#+$+%+B.v.V #+d &+X p.p.*+d =+C.-+;+>+a ,+K.X '+V )+K.C !+|.~+K.!+{+V )+|.{+]+^+d /+K.(+;+|.V _+:+)+V %+<+^+F.|.[+}+a |+)+1+2+[+-+3+4+E.$+&+5+K.[+6+(+;+G.(+{+1+#+7+}.G.8+v.9+[.0+9+Q.a+9 b+* . . . . @ @ . . @ . . . . ", +"c+d d+@+V &+d e+f+0.'+X /+g+c+h+,+i+^+A.j+$+%+k+l+m+,+{+{+[+n+o+o+p+9.q+r+s+t+p+u+v+w+$+Q.l+x+y+z+A+B+/+^+/+{+C+D+E+F+G+P H+I+J+K+L+M+N+O+P+Q+R+S+T+U+I+V+P W+X+L+L+Y+Z+`+Z+ @.@R +@@@#@$@%@I+&@ @Z+*@=@-@1.q+9.@@3+;@1.3+9.5+%+>@N.,@M.'@)@!@: . . ~@. + @ . . @ . ", +";+V g+V {@]@K.^+/+^@^+^@R /@(@_@$@^+:@<@[@}@H+5+E+_@|@R ^@1@(@-@A+v+2@K+3@H+4@v+5@M+6@7@8@I+9@6@0@a@b@c@d@e@b@b@f@g@8@0@0@h@0@i@j@k@8.l@=@H+i+m@T n@o@(+p@q@'@r@s@t@5+S ^@E+8.u@A+v@r@w@X+;@X+x@y@z@A@R h@B@C@8@D@E@P C@q@8.F@@@2.k@1.t+Q.Q.}.v.|.G@. $ @ . . . . . ", +"R H@S+/+p+/+I@J@(@(@(@(@S #@Z+E+K@y+W+L@M@N@O@P@Q@R@J@S@4.T@T@U@U@V@W@X@Y@Z@`@ #=@y@.#+#@#2.B@B@T+##$+$+1+Q.t+$#%#%+&#+*#-+}.=#X+-#9.E.B+r@.#t@;#1.E+A@7@;#8@P@>#O@,#'#)#!#~#{#7@O P ]#~#J@a+(@k@^#/#(#a+_#(#`@g@]#:#<#[#}#7@|#5+O+E+1#Q@<#3.B.:.-+2#. @ . . . . ", +"x+3#4#^@u@5#'#6#7#8#7.R@8#9#j@{#0#C+}#j@(#a#b#-@R@g@P 1.R /+E.$###>+c#d#^+##e#f#Q.g#$+K.)+h#i#j#'@j#C@<#o+k#k@C+]#'#l#R C+{#0#^#m#k@n#o#S@a+p#A@|#q#r#s#0@]#t#]#E+8#U+u#v#t#m#w#a+v#x#y#z#A#R@R@P B#C#D#Q 7.S@E#h@!#O+3.F#^#8@G ;#k@^#[#G#8.(#|#H#@@I#I#J . . . . . ", +"G J#K#{#L#M#R@C@3.z@9.-@l+l+e+@+*#E.d#}+##k+N#&+j+g+i#{+{+/+(@ #|#0@0@d@M@K#O#P#Q#R#S#9 T#U#V#6#Q G {#W#X#Y#8#P#K#Q K#T@J@Z#`# $.$O@+$@$'##$Z#$$C@%$&$R@8#O S@G d@*$4.a+Z#7.g@e@9 =$-$;$|#>$S@,$Y@4.0@'${#)$s#S@J#4.S@>#x#R.R.R.R.!$~$M#)#7.s#Q G {$}./.]$C@. . . . ", +"Z+o+l+^$/$p.p.&+&+m.($_$($3+l+:$<#0@v#Y#<$H#z#y#[$}$|$S#1$2$3$4$5$.$d@c@I >$Y#6$>#7.x#P 7.x#7$@$S# $)#P#d@S#b@U@e@K#8$R#[$x#>#-$%$Z#9$@$u#0$%$K#X@a$`#8$4$R.b$)$c$s#9#4.9 P#*$d$d@e$%$a$f$!@g$@$e@b@8$Y@@$)$a@b@0 c@h$c@7.S#S#i$S#j$k$P#7.[$S#l$I 8$X@5+/.m$3.K @ . ", +"C n$@@=@O+r#s#z#a$k$N o$p$q$r$s$j$4.t$k$>$5$j$8#9#0@d@9@-$C#c$d@<$d@O#e@e@u$>$%$%$e@@$Y@>$z#e@z#[$c@v$y#w$*$t$)@x$7.Y@y$[$z$L#y#z#0 J#k$*$A$B$N )$0 4$b@C$D$U@%$E$F$G$b$e$a@g$a@8$j$0$d@t$b$H$4$8$c$I$J$b$y#Y@I K$L$I 0 5.9#9 %$9 %$M$N$f@o$O$J$J$S#P$O+t+4+]$Q$. . ", +"R$S$g$0 %$S#4$S#P#[$[$P#N S#a$K#8$T$r#U$M#I$8$[$9$9$a@y#~$d@e$V$B#S#[$>$*$5$b$8$k$y#8$4$[$7$P#;$t$f@8$k$y#W$Y@X$0 e$)$)$Y@9$I O$e@Y$Y$J$J$t$g$b$L#!@v$[$0 a@Z$5.%$0 J$)@5.`$O$N u$!@0 0 %.%4$+%@%#%P$o$N 0 $%%%&%*%=%0 -%J$;%>%;%,%'%o$)%O$O$!%*%e$1$o#'+~%{%]%R . ", +"k$M#X@^%M#S#[$[$[$S#8#k$S#N 8$*$8 5$I !@X$P#8$8$!@0 @$z#/%(%0 M#_%g$:%9 I 9$5.g$B$<%N [%0 e$0 P$I I : y#N g$g$N$W$!@e$+%X$X$N J$J$p$p$q$!@}%2$|%9$)@t$l$)@R$I .%l$S#g$4$N$I 8$S#N B$O#%$*$a@G d@%$f@H$M#1%H$1%J#{$b@b@c@2%e$g$*$8#k$*$3%d@X$1%4%c@y#B$5%n+[+6%7%8%e$", +"5.O$O$S#[$[$5.9%4./%0%b$J$J$8$9#a%)@X$b%c%q$o$1%N 9%P$0 >$}$0 d%e%f%1%)$g%5.O$h%i%O$6.: y#v$j%o$8 H k%d%)%l%0 m%n%5$2%l$i%o%S$l$p%i$O$Y$H$[%e@~$4$@$b$X$q%}$L$8$3$m%r%s%t%u%v%w%x%y%& z%+ A%B%C%D%A%A%A%& + + + + E%> F%& + + ~@+ ~@A%D%G%H%I%I%J%B%. D$2+K%#+L%M%N%", +"5.N N N N [$%$5.I I O$O$P$!@O%g$D#O$K$P%Q%O$N N R%S%S%T%S%U%V%h%4$h%h%i%W%|$X%d%y$0%O$F$N o%[$g%N o$p%8$O$N y$Y%u$.%H q$[$s$Z%T%} 6.`% &.&+&@&. . . . K K 2##&= $&%&0%O$!@V$d@e$C@/#1.g+&&/$c#B.*&=&-&;&>&,&'&)&)&!&~&{&]&^&/&(&(&'&>&,&>@I.8+G.}.(&@+] 7 '@##_&:&<&", +"u$6.6.y$o$J$)%[&6.)%6.i%[$[&[&d%H }&h%o$.%Z%|&.%1&6.o$2&2&)%3&4&7 F$5&X%6&7 6&}$T%T%7&8&9&] &0&M } a&b&c&d&e&f&. . . . . . g&T./%!@Z@h&i&3+##;&:&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&A&I&J&K&L&M&N&O&P&Q&R&S&T&T&Y.P&U&V&W&X&V&Y&n&Z&_#`&#+ *d+.*", +"N y$6.6.T%o$o$f%6.7&`%+*@*#*i$}&4&6.$*y$X%f%8 %*[%N )%o$Z%&***=*-*;*>*,*'*)** . # . . . . . K K !*~*{*)$r#=@]*^*/*(*_*:*<*m&[*}*|*1*2*3*4*5*6*7*8*9*0*a*b*c*d*e*f*g*h*i*j*k*l*m*U%n*o*p*q*r*s*t*u*v*w*x*y*z*A*B*C*C*C*D*E*F*z*G*H*I*J*K*L*M*N*O*P*Q*R*($S*J.T*U*V*W*", +"6.p$6.} 6.R%6.X*Y*2&g$L$5$5$Z*`*A$ =.=} +=^ '** #&* @ @ . . . . . . K @=#=$=(#'@V*7%%=&=N%*===-=;=>=,='=)=!=~={=~=]=^=/=(=_=:=<=[=}=|=1=2=}=q&3=4=5=>=6=7=8=9=0=a=b=c=d=e=f=g=. h=i=j=i=i=k=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=i=l=m=n=o=@@=%p=q=", +"`%+*Z%r=s=4$q$y$#=R%} t=u=v=w=+ ~@@ x=K . g&y=z=A=a@=@($M%B=C=D=E=m&F=G=H=I=J=2=/=K=L=M=N=O=P=>=Q=R=S=T=U=V=W=X=Y=Z=`= -.-+-S=@-#-;=3=3=;=$-%-&->=*-=---;-'=>-,-'-)-!-~-{-]-^-/-i=(-_-:-<-[-}-|-1-2-3-4-5-6-7-8-9-0-a-b-5-c-d-e-f-g-h-i-j-k-l-m-n-o-p-q-r-s-t-u-v-*.", +"5 = + $ . . @ A%w-x-^ = T.: 1.=&^&(*y-z-A-B-C-D-E-F-G-H-I-%-J-H-K-K-L-M-N-O-P-Q-R--=S-T-U-V-W-W-X-Y-Z-S-P-`- ;}*.;+;@;J-#;$;%;&;*;=;-;;;>;,;';);!;|=!;!;~;=-{;];^;/;(;_;:;<;[;i=};|;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;q;i;j;r;j;s;t;u;v;w;x;y; #^*", +"k%H I d@O c#z;A;B;C;D;E;F;G;H;I;J;K;L;E;M;N;O;R-P;Q;R;S;T;S;U;V;W;X;Y;Z;Q-O-N;`; >O;.>+>@>g=#>g=$>M-%>&>*>K;=>->`-;>>>,>'>)>&->>}=!>~>{>%-|=]>^>d=/>*-(>_>:><><=[>}>|>1>2>3>i=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>a;x>y>z>8>A>B>C>D>E>F>G>F+", +"H>@>I>@;H-&;U=J>K>L>M>N>O>P>Q>R>S>T>U>V>W>X>Y>Z>`> ,H>.,+,@,L>J>R--=#,R-$,J>J>S-%,&,*,=,-,K>#-%,I>L-K-;,@;>,,,->@;',=;),R=!,~,{,Q=}=],^,;;>=/,>-(,}>M=~>~>_,:,<,[,},|,x=1,i=2,3,4,5,6,7,9>8,9,0,a,b,c,9;k>d,i>e,f,g,h,i,z>j,k,8>h;l,p>r;m,n,o,r;p,q,r,s,t,u,v,w,x,^&", +"O>R;y,z,A,B,Y>C,A,C,X>Z;D,Y>E,F,y,S;m&G,H,I,J,K,L,M,U;N,O,P,Q,R,M>-=S,R,T,U,V,S-W,K;X,Y,Z,N-`,,>W= ' -.'`-`-';+'*;@'H=#'~,;;$'~,>>%'+'&'Q=*'6=|=a=='-'N=;'%'>',''')'!'~'i={']'^'/'('_':'0;<'r;r>o,0;k,['}'o>|'1'2'm>r,3'4'5'6'7'8'p,k>9'8>0'a'b'c'p,d'e'f'g'i=h'6%i'", +"j'k'l'A,C,y,X>Y>X>X>m'n'o'T>p'*=q'`>r's'Y-t'u'v'N,w'L,R,P-O,D;P;R,J>R--,x'y'z'A'F-@>P-W,W=%>B'C'`-F-D'$;;;}*E'F'4=G';;H'->G-I'J'K'3=[=K'L'M'N'<=}>0=O'P'Q'R'S'!>T'U'V'W'X'Y'Z'`' ).)+)@)#)$)s;%)q,&)2'*)=)@)-)8';)b->),)')))!)~){)9;h;])}'^)0'n,d'f,/)&)()_):)<)[)})", +"|)1)2)3)4)5)6)7)8)9) ,L,M,P;L>v'u'S-T-0)Q;a)b)M,c)d)e)f)g)#,h)W-$>X-i)j)J;K>&,k),>l)+>`-`,S-m)L-n);=*>o)=;+'p)q)'>F;r)s)n)%'$-*-s),;&'*;6=|*2=M'I'6=K=>;t)u)!;v)w)x)y)z)A)%)%)B)$)C)^'n>D)E)E)F)r>G)j,H)I)J)e;K)L)M)N)O)P)Q)R)S)T)i>f,U)7'V)V)W)j,X)z>0;Y)w><-i=Z)`)", +"p' !.!+!@!#!F=M>$!%!&!*!L>=!L>-!;!>!@,#,,!'!)!!!~!{!i)P-R,X-Z-]!W-g=+>^!/!(!%,_!:!L-&>`;.>&;,>>1!I>H-),*;H-{>*>L'>=>=2!,;O'3!%'%'4!{>N'|*<,5!/>6!7!p%8!i=9!0!a!f;b!7>>):':'j,J)c!}'g>d!a'g;e!e!f!g!h!i!j!k!l!m!n!7'o!p!q!7'r!s!t!u!v!w!^)v!x!y!z!A!B!C!", +"D!W;E!D;&!F!A-G!H!I!J!D;T;K!P;L!M!g)X;'!N!;!O!P!Q!R!S!T!=,U!K;R,W=V!K>J>J>&>}*U=W=W!+>J-',;=X!H;Y!N-Z!`!>,*;); ~.~+~@~[=}=H-#~$'$~2==;a=%~&~*~(,=~2=-~;~$->~,~'~)~!~~~{~b,]~5;Y)^~^)^'/~o,(~0'_~r,:~:'<~[~}~|~1~2~3~4~()5~6~7~8~9~T)0~Z'a~k>w>n;=)b~c~d~9;e~f~g~i=h~", +"i~j~k~l~0)m~n~+,P;V-4)o~@,p~I,q~r~N,s~o~t~u~-!v~w~x~y~z'S-U,$>#,V!N-E-`-=> -E;z~W!K-&>@;o)I>A~H-)>B~;>I-=;;>o));$'C~5=>=1=%-G-L'!>D~E~!=F~G~H~I~e=:,J~q&K~L~M~N~O~k=P~Q~J)s;0'R~S~S~T~1'U~%)V~9;r;U~W~X~Y~Z~`~ {.{i=+{+{@{#{${%{&{9-*{h,={g,-{y>;{>{,{:''{#)m,){i=!{", +"~{>!{{]{U;K,^{/{=!({{{p~U-P;_{$,]!N!:{R,]!V,<{[{P,P-W-B'}{-,g=W,U! -+>F-|{B'#,1{V!`;2{`-',Z&3{*;2{4{5{3=.;6{7{)>o)@;,;'>@;L'8{q&D~;;,;9{r)0{#~a{{>b{c{d{e{f{g{h{i{X).)V~j{k{l{/)g>a>m{n{o{p{q{i>&)r{s{t{u{v{w{x{y{g>z{e>A{P~o,B{C{0'D{k>E{Y)F{G{H{I{J{p{K{8>L{g'M{N{", +"O{Q;P{Q{-=R{P;/{Y-S{T{$,V-P;R-U!U{J>%,O;V{W{X{Y{V-Z{`{`,A' ].]W=+-+]_!U,Z, -X!G=',I>@]E- -=;#]:!H=I>$]%]&]*] ~H-=][=G-H'5{{>,;3=3=I',;b{Q=-]r);]),Q=>],],;']Z#)]i=!]~]{]r>]]#)&)^]_~a'V)a' )0~9;0;/](]_]:]<]J)])g>c,[]}]q;}]Y)2'L{|]1]2]r;3]s;4]5]E{E{9;6]&)c,7]u,8]", +"9]p~g)H>0]a]D;b]c]w'p~@,v~-,R-R-d]e]N!f]j)W{P,`{5=g]h]i]#,X=P-N-+-',j]X=N-%],>]!o)I>J-[!4=#;m)k].>l]m]s)8=n]*'I-],o]@;p]),),>;3=>=H=*;L'5=a{);q]c{r]]>=;s]t]u]v]w]X'+)x](~b~]]y]9,V)s>z]A]b;U)['5;B]C]D]E]F]G]H]9;E)I]J]K]i>}'L]s;M]N]O]a!P]E{c'g,h,b;$)q{&)g,Q]R]S]", +"Q;u'S{T]u'U]V-#,V]J!_{W]X]Y]=,R--=Z]S!`]N,S- ^.^+^`;@^y'%,W=K-U,X!,>.]Y=.]W=-;I>#^$^%^L-n];;.]G'.;}=&^8=3=}=*^n]=^-^~,;^>^,^}={>>;'^m)3=!;)^>;$'4{+~H=!^~^{^]^i=(~^^:'o,a>/^(^j,():'b,_^:^<^1'y]]~6'[^}^y]|^m;a;s>1^b;9;b,p,K{c!m,2^3^4^5^6^=)B{=)7^8^9^0^a^3]b^c^d^", +"e^f^a]g^h^i^j^_{S{W-:!V,b)k^l^V]m^@-@>V-n^,>U!I>N-o^.]p^',N--, -q^P-M-r^q^s^t^u^v^+-F;.;w^I;n]';x^3{k)>>;;>>&;-^q&B~5=;;H-y^),Y!->!,(,!;+~E~ ~~>%',;%'+'z^O A^i=B^t{h;/~p{C^D)f;^)r,j,*)^'D^g,p{E^F^G^H^I^l,J^])K^a~}]4]L^j,M^S)S~c!N^O^P^Q^R^S^j,R~8^T^U^['V^W^X^Y^", +"Z]Z^Q-`^!!Y-R,s'R-J>J>P-W=w~ /S,./+/@/P-q^.]#>T]y'1>T,G=k)#/$/%/&/*/=/-/;/R=*>,>',M-H;5=D'#^%;(,*,H;>/';-/J-';}=}=2{H-&;n)V=,/],->'/)/!/-/{>%-->E'&;%-%'~/{&{/]/^///6,n{g,(/L^6,m,_/j,6,:'5'o,:/E)r,1/0'h,2/3/4/5;B{:'E{5/6/7/8/d'9/G)q!>{0/q>a/K^U)b/c^c/", +"H>R!d/J>e/f/J>#,R-s'K;#,b)g/l)K>h/^!i/J>-,w^j/:!k^#;Z,q^W=T=k/l/+-1=p'm/),L-n/@]%]y^>>K>;>),'/B'G;o/J-p/q/o)M-@'-^v^%]F;S=V=m)#^J-;=6{r/J;1{3=3=;=I-@;N=s/t/i=u/v/S)g;$)w/6,x/6^<^H)9;y/z/~)@)A/y>B/C/D/f,c,z/J)[]c,E/V)0'F/K{G/H/9;I/J/K/L/C)Z'A/H/h,_~M/u!%)('N)N/", +"U!J!g)T-V-V-Q,i)#,R,N-W=K>J>W-W,S-O/A'`,P/&,Q/R/A'S/<{+>+>T/#]'/$~U{],U/t~9{=^;;V/1>s^[!A'I>D'W/X/@'$^ ~Y/[!Z/%]`/p/H'w^2{>>#;>>],&/Z!4= -],&; (I-;=#^.(+(@(i=#($(M/u;L]:^m>g;%(*)g>E{5'h>&(S)q!w>^^&(*(h>G)J]=(>{-({]5;]~p,/)A>;(>)>(,(9>w>'(9;V^H/E{i>)(c'Z'!(k=~(", +"V-{(Q,:{g=j/](W-K;N-]!J>]!N;$>-,E;P-^(k/:!Z,W=K-@-K-K>!,%-#;/(((_(:(<([(}(:&B 9{%-;/[! ~U=*;),,^|(1(2{5{@'H-&];=&/3=`-H'.;->D'%>%;2(D'>>n))>S=.;k)L'5=s]3(4(i=5(6(R~5;7(s;h;6^q{L^^)5;8(p!8'E{_~9(0(a(b(c(J)d'G/r!d(_/s;c!e(f(|/g(h(i(i>j(k(z]l(O^m(N]c>Z'n(e;o,i=o(", +"p(o&$,q(K;p~N-S/T-b)b),>V]W=Z,+'4{r(#]s(t(u(#~v(S!,>u)w(x(y(z(A(V,X+2=B(C(D(E(F(`;#;&;*;->G(=]o)R=4=H(U=~,Z!%,2=';`;G=F;;=J-F;G(+'*,p/*;J- -H;J-',',G=,-I(J(K(L(M(o>c(@)N(p,5'm>1'g,c!%)O(8'(/P(|/c'o;z/Q(1]R(1]S(K{T(U(V(I]W(V)=)X(Y(Z(*{`( _K{t!._+_K]U^@_#_$_%_&_", +"O;V,*_N-U-e]<{=_Q!<{-_f];_>_`,,_'_)_+~!_~_{_j)]_^_a=/_(___:_<_[_}_|_1_2_3_4_5_6_ ,H=@;[!7_G-`-W!8_H(J-X!9_H-0_a_Z&*;Y!b_c_d_e_f_',p/*;q^I;#~@'V!@;g_q/M'M#h_i_<-k>(/h,])j_k_k(c'()|/B{^)u>v!$)l_|^m_u;n_o_={p_t!p_t!q_r_s_V)t_u_o,v_w_x_i>B{6]y_T(z_u_A_B_C_D_E_F_u@", +"'!G_H_P-.-I_C'J_P-i)K_j/I_3=L_M_N_O_P_Q_R_S_T_U_O>V_W_X_Y_Z_`_ :.:+:@:#:$:%:&:*:,>>>L-`->>#'O/U==:Z!-:L-;:2(@'X!>:x^&;b_ ~,:X!@'G-':%] ~#-):5{K>!:!:',(>~:{:]:^:/:8;(:p,m,j,T)R^K{w/a;J{a;G/V)m;_:::V)<:[:}:r!}:t_1]|:1:s!2:K{3:4:5:6:7:8:q!g~ _u_9:0:a:b:c:d:i=e:f:", +"P-g:h:i)K-`;j)Z-v^i:K>9_j:;.k:l:m:n:o:p:q:r:s:t:u:P$v:w:x:y:z:A:B:. C:D:E:F:G:H:I:!,y^F-`-%];;y^J:n]G=G=H;W!{,W!',#> -p/ 'K:%]+>.;!:4=w^X!k)L:`-F- ~M:N:,$O:P:Q:R:1^]~0;d'J{()~)M(D^S:o!&(M(z_T:o_U:V:W:X:Y:Z:`: <.<+<@<#<$<%/M-j<5{`-J-,>k<):=^!:v^J;`,l<@;Y/%>k)&/.>H;F;!:H(k)&/-,;>k/N-,>q^muD1]7^]~X(EZ/L=[5=jW=I>1{]<>,-[K:;[r^ -.>I>+>'/>[:!&>I>I>*,,[K-Y/#,i)H;r^=>'[)[![i=B^&(a:~[R^-)5'_/sL-h[i[f j[k[_ ]%p=l[m[n[o[p[q[r[s[t[u[v[w[x[y[z[A[B[C[D[E[F[1{I> ;G[R=K-V=D'K>H[L;N-I>#;Y/H;&>w^j<+-I[V=.>]<#,J[S/%>':K-I>I>K[g[R,b{L[M[i=N[n>v!L{$)a;p{O[R^7,5/C)P[6^3'Q[|^R[}:S[(/T[U[R~V[W[X[Y[Z[`[ }8~.}'(g,+}a(H/@}1]#}Q( <$}%}&}i=*}. =}-}", +"-,+-1{~/,>;}W!l)#>#;N-l<>}^{,}'})}!}~}{}]}^}/}(}_}:}<}[}}}|}1}2}3}. 4}5}6}7}8}9}0}=:`;*;a}V!;,b}c}4=d}U=.]+>_!@'d/i:l)m]=>U!e}&>f},>g}-,K;M:]!:!`;u~b)5=h}i}i=j}k}C)S~^)e~c>6,&(l}O[R^E{B_c~a(m}B{n}o}s,p{p}q}r}s}t}u}v}w}(/x}y}z}A}B}C}D}k,u_E}F}G}H}I}J}K}L}M}N}O}", +"P}w^K-g_`-Y/`;F-q^.]*;Q}R}S}T}U}V}W}X}Y}Z}`} |.|+|@|#|$|;.%|&|*|=|-|;|>|,|'|)|!|'/I>;;5=K> -U=K;F;Z,U,K> -H;.>&>V!U,;=`,~/|{N-[!P-S,]!#,T,b_~|N,S-r^g={|]|>&^|/|(|R^*)g,m,6>(/c~_|5':|<|T)f!G)[|v>}|_~-)||o>j,g>1|2|3|K(4|Q~J{:|V^5|6|u!L]7|8|p_a~G}9|}]i=0|a|b|c|d|", +"1>X!.>.>@]-,e|K-1{y',>,>R,f|g|h| |i|j|k|l|m|n|o|p|3{q|r|s|t|u|L,v|Q=.>w|x|y|%^V/+-c_e|K-;=G[:!I>;=W,z|`-U=J:+>.>W,=,g=U,+-X=+>P-J>+-Q-]! ]:!P-`;P- ]r^O,|!Y*A|B|j-%)-)x>i>C|D|}'j;0'E|@)x/V(F|A_e,f!U)V^G|L^H|~[I|J|K|L|B_M|N|u!O|P|0^Q|R|S|A_T|U|V|W|i=X|. Y|Z|`| 1", +"W!G=Z{.1`--^1>1> -*;Z-S!/(+1@1#1$1%1&1*1=1-1;1>1,1'1~_)1W/V-]<;;H(q^u^!1~1{1Z&]1,:;/f]H;g=D';=]!J>U,^1,>N-N,S-/1V!,>',x'A'V!B'P-+-W-N-Y-g=#,W-N;]-R,]!q^(1_1:1i=f!<1[1W(a(}'}1D|O(=)g>|11121314151G/61v>y!')y{715'1:t_81>{91<:r!01W[(/51-{a1P|EO-+>V,*!y1/1 ]g[z1M;i)A1B1C1D1E1N(F1^)9;K{a(()G16,H1I16,J1M/K1a'j,5;L1U^M1N1n}O1q!P1>{N]Q13/R1S1H/B{S^0'8:T1U1i=V1W1X1Y1Z1`1 2.2", +"-,n];=g[g};=+2F;v1%>I>@2#;H;d/b_>^#24{;,@'$2,>@'%2&2*2=2K>`-J:V=Y/G[-2I>#,M-h[;2q^.>`-/1,>x~I[h/`;.>.>S-`;W-y~>2R,@>d/,2K>]!W-P-N,P-S- ]N,-= ]S- ] ]-,W{~/!:'2)2j=H|!2%)~2c!c'T)11L{||{211g,S)~[_:e(7[5'L{v>:'z/]2z_tW!j<@>F-W-B~J<92n/U,`;g=.>o)j^+-t(S-O/S-c_T/]<=,S-_!Y,g/K-02@-+-Z/`;`;+>a2P-~/-=h) ]-,g=]-$,g=U!W=Y{E-R- >P!R,@,b2 > ]:!J>v~c2!:d2=%e2f2g2:/&(6,h2<^L^i2p{p,[]:/N(Z'{]51K^0^j2k2O(l2n(m2n2o2p2R(R^q2p_k,b>}[O]r2s2i=t2u2v2w2x2y2z2A2B2W#", +"X=*>y^@^5{'>|!X!V=C2D2b{E2Q=a=F2)=G24!u)S'H2H2I2J2K2_,Q'&''}=-!;L2=-&;M2N2F'>>#;e_s)L-,>`;W-&,%>P-g=I>`;J>@-g=Q,J>X-W{<{W,0]N,b2$>U! ]v'T,v~J!J>L,v'b)~/R*J!O2P2Q2R2S2H^_~5'L^@_8'g, _3]T2h>W[F/U2k((/9;=)0^J{S~r>V2W2X2Y2Z2`2 3.3+3p{E/g,K(@3#3. $3%3&3*3=3-3;3>3,3", +"W,;=F-%];,1>o)%]N-w^'3j) ~Y{b2 >Q,J!J!P})3r~!3+,R-P;Z;~3w'L,Q-Q-@,{3!3N,N,N,V-J>]3@-T-0]W-&,M,M,J>J>J>b2R-F=z'J!F=-=P-$,Y-^3W-N,/3&,M, ][*W-(3_3/3V-Y-H>M,h)V-'}. :3i=<3[3*)}3]~()J{K{&)11|3}'|/13P~23P^g'330(X2435363738393k=i=i=i=i=i=i=03a3. B-b3c3d3e3f3g3R = . ", +"h3<=<=i3h3h3D~j3!/*_k3l3m$@.%.1+S O J@7.f%m3y$Y*7&7&n3y$@$P R@(@h#1+#.y n y f|o3p3q3E,V-G=W,`-H=V=`-@;p/J-=;I-@;L'*;H-'/;>I-P-P-G[P-W-P-O--=Y-A-/1Q!M>_3 ]q'D;J-@;2$r3s3t30!0's>b;v/u3v3w3x38/b~y3z3A3u,B3C3i=i=i=i=i=D3E3F3G3H3I3J3K3L3M3N3O3P3Q3R3S3T3U3V3>+~ . . ", +">!W3X3}.V$H : i%Y3k%~ - * ,*Z3+ @ . @ . . . . $ . . . . . @ . I%@ + + v=+ * = { { { ~ J ) J A=d%}&) ) W%5$u@E.n `3r j' 42).4+4m' ,_3#,,>1>;;F-),I>1{@>;=#,W-G[@4#4b28+$4%4&4*4=4-4i=i=%_i_;4>4c^c^,4'4)4!4~4{4]4^4/4c.(4_4:4S$f&<4[4}4|414243444546474f3P/L%H @ @ . ", +"@ @ @ . . . . . . . . . # . . . . @ @ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . K K $ . . w=I%& A%@ + @ { }&[$R@<+#.+@E.%.84t ]%m&R;+1Z;O'y,9404a4b4c4d4e4f4g4h4i4j4k4l4m4n4_ W%9%Y3o4p4q4r4s4t4u4v4w4x4y4z4G*A4B4C4D4E4F4G4V3L%5.@ . . . ", +"@ @ . @ . @ . K . . . @ B%@ . . . . . . . . . a|K K . @ . . . . . . . . @ . . @ . . . . . . . . K . @ . . . K . . . x=. K . . . @ . . . . . . . . . . . . F%H4I4|&X#J4K4L4M4N4O4P4Q4R4S4T4U4V4W4X4Y4Z4`4 5.5+5@5#5$5%5&5*5=5-5;5>5,5'5)5!5~5{5]5^5/5(5L%H @ @ . . . ", +"@ . @ . @ . . K K . . g&g&% . . . . . . . . . 2#. . @ . @ . @ @ @ . . . @ @ g&. L . . . . . . . K . K L @ . K . # . K . . . @ . . . . @ . . @ K @ . . % . K . % . . . _5:5. . . f&<5C=[5}5|515253545556575859505a5b5&3c5d5e5f5g5h5i5j5k5l5m5n5o5p5q5.@J @ @ . @ . . ", +"# . # # . # . . . . . . . . . . . . . . . . @ . . K . K K # % . # . # . . . @ . g&K . . . . @ L . . . $ . . . . # . . . . . . . . . . . . . . . . . . . . K . $ @ . # . . :5r5s5_5t5r5u5v5&*w5x5y5z5A5B5C5D5E5F5G5X_H5I5J5K5L5M5N5O5P5Q5R5S5T5K[U5V5W5. . . . . . . ", +"$ . % B%2#x=. . K x=x=x=x=K . # @ . # . # @ . $ x=. K g&. x=. @ . X5K . . @ . @ # K . @ @ . . K . % L % . . . @ . . @ . . . . . . . . . @ . . @ . @ . . . . . @ + @ . @ @ . B%g&2#L . . . . . . . . . 7 F 0+Y5Z5`5 6.6+6@6#6$6%6U3&6*6=6-6)!;6t.d@+&. . . . . . . . ", +"% . @ . . . . . . . . . . . . . . . . . . . . . K . K . . . L g&x=K # % % . # . % . . K w=K . . . . # . f&# # . . . . . . @ . . . . @ @ . . . + . . @ @ . . . . @ . . @ @ . @ . . +&F%F%F%F%f&L t=>6. . . . . . $ ~@.&1$,6`+'6X3)6!6~6{6L%T I { & . % . . . @ . @ # ", +". . # 2#K ]6,*~@,*^62 >*. . ~@$ ~@$ y%/6$ I%& # $ 2#(6# # # . . . . . . . . . . . . . . . . . . % _6% % % . g&@ + . . . . . . @ + . @ @ . . . . . @ . . . . . . . . . . . . . . . # # . L f&F%B%:6<6. # # . @ . . . . . # t5. s5r5[64&4 Y3n4,*@ . K }6K g&. @ @ . . ", +"3&|61626263646566676869606a6b6c6d6e6f6g6h6i6j6k6l6m6l6n6o6p6q6r6O4s6t6N+M@L+O T@{#S#a$.%4&-*v=. . . . . . . . . . . . . . + @ @ @ @ . @ . @ + . . . @ . . . . @ . . . . . . . . @ . . . . . . . _6H%g&. @ I%H4a&u6v6w6x6H%B%g&I%t5r5u5_5y6z6z6r%4 '*A6,32#$ . . . . ", +"B6C6D6E6F6G6H6I6H6J6K6L6M6N6O6P6Q6R6P6R6S6P6T6U6V6W6X6Y6Z6`6 7.7+7@7#7$7%7&7*7=7-7;7>7,7'7J6)7!7~7~7{7]7N3^79@5$R%$%M 2 . . . . . . . . @ . . . @ . @ @ @ . . . . . . . . . . . . . . . . . . . $ # # @ L # % x%/7n%(7_7:7<7[7}7' H #&. . u5[6|717273747471757+&B%67", +"77879707a7b754b7b7c7d7e7f7C%g7h7i7j7k7l7m7n7o7p7q7p7r7p7s7t7u7v7t7w7x7y7z7'7A7B7C7D7E7F7G7H7I7J7J7K7L7M7M7N7O7P7P7Q7R7S7T7U7(4V7W7X7Y7Z7. . . . . . . . . . . @ . @ . . . . . . @ . . . . . . K K . . _6. . . . . . . $ }&`7 8.8+8@8[%#8#8 8. . . # /6t5}7$8%8v5&8*8", +"J|i=i=i=i=i=i=i=i=i=i=i=i==8+=-8;8o<>8,8'8)8!8~8{8]8'8^8/8(8_8D7:8D7-2<8[8}8|8]|B618283848586878%[88a698S708a8b8c8d8e8f8g8h8i8j8k8l8d[m8n8o8p8q866r8~ 2 % . . . . g&. . . . % . :6. K :6g&s8. :6. @ # % . @ . @ + $ . . . . x=x=@ $ '*4&9&w6u#t8u8u%@ v8. . # t5w8_5", +"$}x8y8z8A8B8C8D8E8F8G873H8i=I8~ J8K8L8M8N8O8P8Q8R8S8T8U8V8W8X8Y8Z8`8 9.9+9@9#9t7$9%9&9*9=9-9;9e8>9,9'9)9!9~9{9]988^9/9(9_9:9<9]|[9}9|91929:83949596979899909a9b9c9d9e9f9* * ~@y%. . . . . . @ @ + . . . . . K x=K . + . a|2#+ . . . . . . K '*^6-*g9`%C$Y7W#6$W5+ I%", +"#}h9i9j9k9l9C>m9n9o9p9q9r9s9i=t9_5u9v9w9x9y9z9z9A9B9C9D9E9F9G9H9W8I9J9K949L9M9N9N9O9;7P9Q909R9d8S9T9U9T9T9V9V9V9{9S9W9K6X9Y9Z9`9 0S7.0+0K6V9@0|9#0$0.0d8%0&0*0'8=0-0;0>0,0'0)0!0]@7.X$~02 I%. . . . . . . . & @ @ . . @ . # ~@@ . . . . . . . K . . . . * 6&r%{0]0^0", +"/0(0_0n9:0<0]/[0}0|010l9_[2030i=40f@506070809000a0b0c0B9d0e0f0g0h0K9i0j0k0l0m0n0o0N9p0%1q0r0s0t0d8U9u0&9>9v0d8b829w0K6x0X9.0y0z0A0B0C0.0e8D0E0&9F0u0Q9'958G0H0I0J0K0L0M0_8N0O0P0Q0X6R0W8S0T0U0V0$@.$s$. . . . . K 2#K g&g&. . . . . . . . . . x=. . . . . . . . $ ^6", +"W0X0Y0X0Z0`0Z0 a.a+a@a#a$a%a&a*ai==a-a;a>a,a'a)a!aa0~a+7{a]a)8^a/a(aK9W8=7K7_a]8p7:a9ca|ada}8eafaga1aha}8,7iaA0B7jaka/a60lamanaoapaM8T8qarasata. . . . . K . @ . . . . . K . @ $ . . . % . K @ @ . . ", +"uavawaxah9yazaAaBa4:k9CaDaEaFaGaHaIaJaKaLaMaNaOaPaQaRaSaP8Ta00'8UaF9VaWaH9Xa/aYaZaL9p7`a b;7%139D6.b+bR9@b#bP7$bP9%b38K61aR9'7&b*b&9A0=b-bia;b>b,b-:2a&9%b'b39@/,bp7o0}8)b!b~b{b1!&0jaK9]b&0X8^b/b(b_b:b7}8o0#bg8AbBb#b@bCbo0T9f89aDb6aEbzbu7FbGbGbO7HbEb<8IbE7=bJbKb9aLb#b9aMbh849Nb]bJbObWaObPbQbH9,8X8PbRbSbTbz9UbVbc0WbXbYbZb`b c.c+c@cC!~@. . . . . . . . . . x=:62#@ @ . g&", +"M]#c$cr9%c&c*c=c-c;c>ccb,c'c:[C{)c!c~cx~{c]cO0^c/c(c_c:c7Kb1bkcNbN9jalcmcncObh0ocPb^bU8pc,8X8qcrcM3^csctcucvcwcxcyczcAcBcCc`bDcEcFcGcD 0&E%Hc. . . g&_6. @ @ . . ", +"IcJcKcLcMcNcOcPcQcRcScTcUcVc:0WcXcYci=Zcf9`c d.d+d@dsc#d$dZ6%d&d*d=d:c-dS8;d,8>d,d'dG9X8n7]b]bAb)dH7H7!d~d0c{d]dt7^d|a:at7/dAbAbf8!b@b|a39(d_d#9.9:d8Wb3d 74d d5d6d7dP68d9d0d}badadbd`bcdddedfdgdV9hdY#s$. . . . . + . ", +"r9idjdkdldAamdndodi=pdqdrdsdtdudvdwd!cxd1)S7ydzdAdgdBdCd8ucR05d5d>e,e'ena)e!e~e{e]e!e^e/e(e_e:ef,f'f)f!f~fY}{f]f^f/fFe7c(f_f:f", +"/2g,g'gi=)g!gO8~g{gvc]gDdxc(b^gNa.7 f;0/g(g_g:gL8h,h'h)h 9!hj0~hEe{hmcK<]h^_sf^h bXa(8G9/hl7(h^a_h:hi,i'i)i!i~i{i]i^i/i(iAc_i:i0!8M8qcobXiYi}hR0@dZi`iYg jhi.jmg+jog@j#j$j%j&j*j=j-j;j>j,j'ji=)j!j~j{jTc]j^jvh/j(j_j", +":j+a:0k,k'k)k!k~k{k", +"]kQg^k/koh(k_kid:kdiHapd8df80*iMkuchiigNkOkPkQkRkSkTkUk9d*fVkWkXkYkZk`k l.l+l@li=#l$l2jg!.{%l^k)k&l*l=le~", +"-l;lh9>l,l4:Lc'l)l!l~l{l]l^l/l(l_l:l8WbFhre|l1lP;2l3l4l5l6l7l8l9l0lalblcldlelflglhliljlGfklDdllmlnlolplqlrlsltlulvlwlxle}ylzl57(@AlBlClDlElQ7Fl%iGl90>8O8Hl+hIlHlXiJlKlLl*iMlqeNlkgOlPlQlRlSlTlUloaVlWlXlYlZl&f`l m.m+m@m#mi_$m%m*l:0m7i,m{j'mk9)mHaAa!mi=~m{mi=]m^m_aLl*i/mvcGf(m_m:miSjEmFmGmP6HmHlImJmZjKmLmMmNmOmQ6PmQmRmSmWkTmUmVmWmXmi=:[8iEa|j;kYm|kZmkdudm9`m n", +"z_.n+n@n#n$nEaWc}03[%n&nAai=B|Ha*n=n-ni=r*;n>n,n'nFh`ese)n!n~n{nl7]n^n/n(nM2_nM,)-:no,o@k'o)o!o~o{o]o^o/obc(o_o:op,p'p)p!p~p{p]p^p/p(pM8Y6_p:pq,q'q)qd Gd!qOk~q{qfmv9]q^q/q(q_q:qr`b,r'r)r!r~r{r]r^r/r(r_r:rjKrLrMrNrOrPrQrRrSrTrUrVrWrXrYrZr`r s.sSn+s@s#s$s%s&sv9^n*s=s@$-s;sh:>s,s'sil)s!s~s{s]s^s/s(s_s:st,t't)t!t~t{txr/i(i]t^t/t(ti=k=6sfq:l%__tP)k=:tq;i=HaB]&gXc", +"R:7TtUtVtWtXtYtZt`tCq~t u6h.u&j+up6@ui=Qcypk=gq#uu*li=,uj&'u)uzf!u~uzew9{u+o]uZg2hMoT6^uKmZjVmWl/ujooaa35h(u_u:uwnv,v'v)v!p!v~v{v]vBt^v/v(v_v:vw,w'w(e)w!pi=K(!wO)vo@3%_k=i=;4~wk=%_8bK(~j", +"{w]w^w/w(w;;^+4.'#g@9 _w:wykxLa9hVl[bbh,x'x>w)xws@v0qa3#kdv!x~xi=JuK({x]xJu_t#ui=M{^xtpi=fqdb", +"/x(x_x:xycg,yZ6Fh'yLh=y@wvx2z*jLa,z)x)xP6]e'z u1sAOq,A'A)A!Atm'A~Avz{A]AYy)AqxFt1}^Aen/A(A@z_A6u:Agzzsw-y*B=B-B;B>Bds,BM{xa'BcyGz)B8spp!B*l", +". . . . . . . . . . . + * = { 5.9 S {+L%A ~B{B@!(3>_]B^BMz/B8ply(B22_B:B=8+OB&.d.;6PBV3QBRBiySBTB_zUB 1VBWBXBYBZB`B C.C+C@C#C$C%CC,C'C)C!C~C{C]C^C/C(C_C:C+L%pCd.^zqC(3L;KzrCsCtCuCvCwCxC(ByCXBzCACM5m5[z}zq*BCi5CCDCECwAFCGCHCICJCKC54LCMC3zNCSrOCPCQCRCSCTCpu`u}wVlzz;j>A{AUCVCWCOAXCXyYCZC`CXy DYvnmFrwg5yYkDx.DN6rvkt+Dit>z@D#D$D%D&Di=*DKB=D-D;DIz&nqp>D", +". . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . @ * = ~ H 9 Q P {+F k j d.^zqCkAV3N2rC,D'D)D!DS5qA~DyC{D]DRzFAEIl;E_p>iRa/r!^S+,E'E2q)E!5!E~E{E", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . @ . . . . . . . . . . . . . . . . . . @ + * { ~ ) H a+a+R F ^.&.e.iA^z@!kAP/N2]E^E/E(E/B_EOzPz:EF+A.^._.3F;6^zjA4FP/QB5F70,D6FTB_E%67F 1N_nyXBn5;F}E+gF 1hFiFjF^.J . . @ @ @ @ . . . . . . . . . . . . . . . . . . . . . . . @ = = = J 5.9 9 Q R >+^.&.e.e.oDjA@!ZEP/N2RBLz*6'DjyTBeF_E%6S5pD", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ~ lykF<'lFmFnFoFpFqFQB@ @ . @ . . . . . . . . . . . . . . . @ . . . @ . @ . @ . . . . . . . . @ @ + { { ~ J H I a+a+>+1+F j 3Fd.oD^zrFjAg3kAP/", +". . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . J ,DsFtFuFvFwFxF +#include + +// Qmitk +#include "QmitkIGTTrackingDataEvaluationView.h" +#include "QmitkStdMultiWidget.h" + +// Qt +#include +#include +#include + +// MITK +#include "mitkNavigationDataCSVSequentialPlayer.h" +#include +#include +#include + +//ITK +#include + +//VNL +#include + +//vtk headers +#include +#include +#include + +const std::string QmitkIGTTrackingDataEvaluationView::VIEW_ID = "org.mitk.views.igttrackingdataevaluation"; + +QmitkIGTTrackingDataEvaluationView::QmitkIGTTrackingDataEvaluationView() + : QmitkFunctionality() + , m_Controls(0) + , m_MultiWidget(NULL) + , m_scalingfactor(1) +{ + m_CSVtoXMLInputFilenameVector = std::vector(); + m_CSVtoXMLOutputFilenameVector = std::vector(); +} + +QmitkIGTTrackingDataEvaluationView::~QmitkIGTTrackingDataEvaluationView() +{ +} + +void QmitkIGTTrackingDataEvaluationView::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::QmitkIGTTrackingDataEvaluationViewControls; + m_Controls->setupUi(parent); + + connect(m_Controls->m_LoadInputFileList, SIGNAL(clicked()), this, SLOT(OnLoadFileList())); + connect(m_Controls->m_StartEvaluation, SIGNAL(clicked()), this, SLOT(OnEvaluateData())); + connect(m_Controls->m_AddToCurrentList, SIGNAL(clicked()), this, SLOT(OnAddToCurrentList())); + connect(m_Controls->m_GeneratePointSetOfMeanPositions, SIGNAL(clicked()), this, SLOT(OnGeneratePointSet())); + connect(m_Controls->m_GenerateRotationLines, SIGNAL(clicked()), this, SLOT(OnGenerateRotationLines())); + connect(m_Controls->m_GeneratePointSet, SIGNAL(clicked()), this, SLOT(OnGenerateGroundTruthPointSet())); + connect(m_Controls->m_Convert, SIGNAL(clicked()), this, SLOT(OnConvertCSVtoXMLFile())); + connect(m_Controls->m_loadCSVtoXMLInputList, SIGNAL(clicked()), this, SLOT(OnCSVtoXMLLoadInputList())); + connect(m_Controls->m_loadCSVtoXMLOutputList, SIGNAL(clicked()), this, SLOT(OnCSVtoXMLLoadOutputList())); + connect(m_Controls->m_OrientationCalculationGenerateReference, SIGNAL(clicked()), this, SLOT(OnOrientationCalculation_CalcRef())); + connect(m_Controls->m_OrientationCalculationWriteOrientationsToFile, SIGNAL(clicked()), this, SLOT(OnOrientationCalculation_CalcOrientandWriteToFile())); + connect(m_Controls->m_GeneratePointSetsOfSinglePositions, SIGNAL(clicked()), this, SLOT(OnGeneratePointSetsOfSinglePositions())); + } +} + +void QmitkIGTTrackingDataEvaluationView::OnOrientationCalculation_CalcRef() +{ + if (m_FilenameVector.size() != 3) + { + MessageBox("Need exactly three points as reference, aborting!"); + return; + } + + //start loop and iterate through all files of list + for (int i = 0; i < m_FilenameVector.size(); i++) + { + //create navigation data player + mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = mitk::NavigationDataCSVSequentialPlayer::New(); + myPlayer->SetFiletype(mitk::NavigationDataCSVSequentialPlayer::ManualLoggingCSV); + myPlayer->SetFileName(m_FilenameVector.at(i)); + + //check if the stream is valid and skip file if not + /* + if (!myPlayer->GetStreamValid()) + { + MITK_ERROR << "Error in file " << m_FilenameVector.at(i) << ": " << myPlayer->GetErrorMessage() << " ; Skipping file!"; + continue; + } + */ + + //create evaluation filter + mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New(); + + //connect pipeline + for (int j = 0; j < myPlayer->GetNumberOfOutputs(); j++) { myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j)); } + + //update pipline until number of samlples is reached + for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); j++) + { + myEvaluationFilter->Update(); + } + + //store mean position as reference + switch (i) + { + case 0: + m_RefPoint1 = myEvaluationFilter->GetPositionMean(0); + break; + case 1: + m_RefPoint2 = myEvaluationFilter->GetPositionMean(0); + break; + case 2: + m_RefPoint3 = myEvaluationFilter->GetPositionMean(0); + break; + } + } + MessageBox("Created Reference!"); +} + +void QmitkIGTTrackingDataEvaluationView::OnOrientationCalculation_CalcOrientandWriteToFile() +{ + //start loop and iterate through all files of list + for (int i = 0; i < m_FilenameVector.size(); i++) + { + //create navigation data player + mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = mitk::NavigationDataCSVSequentialPlayer::New(); + myPlayer->SetFiletype(mitk::NavigationDataCSVSequentialPlayer::ManualLoggingCSV); + myPlayer->SetFileName(m_FilenameVector.at(i)); + + //check if the stream is valid and skip file if not + /* + if (!myPlayer->GetStreamValid()) + { + MITK_ERROR << "Error in file " << m_FilenameVector.at(i) << ": " << myPlayer->GetErrorMessage() << " ; Skipping file!"; + continue; + } + */ + + //open file header + QString outputname = QString(m_FilenameVector.at(i).c_str()) + "_orientationFile.csv"; + m_CurrentWriteFile.open(outputname.toStdString().c_str(), std::ios::out); + if (m_CurrentWriteFile.bad()) + { + MessageBox("Error: Can't open output file!"); + return; + } + + //write header to file + m_CurrentWriteFile << "Nr;Calypso_Time;Valid_Reference;MeasureTool_Measurement-Tool[x];MeasureTool_Measurement-Tool[y];MeasureTool_Measurement-Tool[z];MeasureTool_Measurement-Tool[qx];MeasureTool_Measurement-Tool[qy];MeasureTool_Measurement-Tool[qz];MeasureTool_Measurement-Tool[qr]\n"; + + //update pipeline until number of samples is reached + int step = 0; + mitk::Point3D point1, point2, point3; + mitk::Quaternion current_orientation; + + for (int j = 0; !myPlayer->IsAtEnd(); j++) + { + myPlayer->Update(); + mitk::NavigationData::Pointer currentNavData = myPlayer->GetOutput(0); + switch (step) + { + case 0: + step++; + point1 = currentNavData->GetPosition(); + break; + case 1: + step++; + point2 = currentNavData->GetPosition(); + break; + case 2: + step = 0; + point3 = currentNavData->GetPosition(); + + //compute transform from reference to current points + if (point1[0] == 0 && + point1[1] == 0 && + point1[2] == 0 && + point2[0] == 0 && + point2[1] == 0 && + point2[2] == 0 && + point3[0] == 0 && + point3[1] == 0 && + point3[2] == 0 + ) current_orientation.fill(0); + else + { + /* Drehen um eine Achse um das "Umschlagen" zu vermeiden + itk::Matrix rot180degreeAroundY; + rot180degreeAroundY.Fill(0); + rot180degreeAroundY[0][0] = -1; + rot180degreeAroundY[1][1] = 1; + rot180degreeAroundY[2][2] = -1; + point1 = rot180degreeAroundY * point1; + point2 = rot180degreeAroundY * point2; + point3 = rot180degreeAroundY * point3; + */ + + vtkSmartPointer transform = vtkSmartPointer::New(); + vtkSmartPointer sourcePoints = vtkSmartPointer::New(); + double sourcepoint1[3] = { point1[0], point1[1], point1[2] }; + double sourcepoint2[3] = { point2[0], point2[1], point2[2] }; + double sourcepoint3[3] = { point3[0], point3[1], point3[2] }; + sourcePoints->InsertNextPoint(sourcepoint1); + sourcePoints->InsertNextPoint(sourcepoint2); + sourcePoints->InsertNextPoint(sourcepoint3); + vtkSmartPointer targetPoints = vtkSmartPointer::New(); + double targetpoint1[3] = { m_RefPoint1[0], m_RefPoint1[1], m_RefPoint1[2] }; + double targetpoint2[3] = { m_RefPoint2[0], m_RefPoint2[1], m_RefPoint2[2] }; + double targetpoint3[3] = { m_RefPoint3[0], m_RefPoint3[1], m_RefPoint3[2] }; + targetPoints->InsertNextPoint(targetpoint1); + targetPoints->InsertNextPoint(targetpoint2); + targetPoints->InsertNextPoint(targetpoint3); + + transform->SetSourceLandmarks(sourcePoints); + transform->SetTargetLandmarks(targetPoints); + transform->Modified(); + transform->Update(); + + mitk::Transform::Pointer newTransform = mitk::Transform::New(); + newTransform->SetMatrix(transform->GetMatrix()); + current_orientation = newTransform->GetOrientation(); + + //add pointset with the three positions + if ((j > 15) && (j < 18)) + { + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + mitk::PointSet::Pointer newPointSet = mitk::PointSet::New(); + newPointSet->InsertPoint(0, point1); + newPointSet->InsertPoint(1, point2); + newPointSet->InsertPoint(2, point3); + QString name = QString(m_FilenameVector.at(i).c_str()); + newNode->SetName(name.toStdString().c_str()); + newNode->SetData(newPointSet); + newNode->SetFloatProperty("pointsize", 0.1); + this->GetDataStorage()->Add(newNode); + } + } + + break; + } + m_CurrentWriteFile << i << ";"; + m_CurrentWriteFile << currentNavData->GetTimeStamp() << ";"; //IMPORTANT: change to GetIGTTimeStamp in new version! + m_CurrentWriteFile << "true;"; + m_CurrentWriteFile << currentNavData->GetPosition()[0] << ";"; + m_CurrentWriteFile << currentNavData->GetPosition()[1] << ";"; + m_CurrentWriteFile << currentNavData->GetPosition()[2] << ";"; + m_CurrentWriteFile << current_orientation.x() << ";"; + m_CurrentWriteFile << current_orientation.y() << ";"; + m_CurrentWriteFile << current_orientation.z() << ";"; + m_CurrentWriteFile << current_orientation.r() << ";"; + m_CurrentWriteFile << "\n"; + } + //close output file + m_CurrentWriteFile.close(); + } + MessageBox("Finished!"); +} + +void QmitkIGTTrackingDataEvaluationView::StdMultiWidgetAvailable(QmitkStdMultiWidget &stdMultiWidget) +{ + m_MultiWidget = &stdMultiWidget; +} + +void QmitkIGTTrackingDataEvaluationView::StdMultiWidgetNotAvailable() +{ + m_MultiWidget = NULL; +} + +void QmitkIGTTrackingDataEvaluationView::OnAddToCurrentList() +{ + //read in files + QStringList files = QFileDialog::getOpenFileNames(NULL, "Select one or more files to open", "/", "CSV (*.csv)"); + if (files.isEmpty()) return; + + for (int i = 0; i < files.size(); i++){ + std::string tmp = files.at(i).toStdString().c_str(); + m_FilenameVector.push_back(tmp); + } + /* + //save old locale + char * oldLocale; + oldLocale = setlocale( LC_ALL, 0 ); + + //define own locale + std::locale C("C"); + setlocale( LC_ALL, "C" ); + */ //TODO: check if this is needed here, and load old locale if yes + + /* + //read file + std::ifstream file; + file.open(filename.toStdString().c_str(), std::ios::in); + if (file.good()) + { + //read out file + file.seekg(0L, std::ios::beg); // move to begin of file + while (!file.eof()) + { + std::string buffer; + std::getline(file, buffer); // read out file line by line + if (buffer.size() > 0) + { + std::string thisFilename = ""; + if (m_Controls->m_AddPath->isChecked()) thisFilename = m_Controls->m_ListPath->text().toStdString(); + thisFilename.append(buffer); + m_FilenameVector.push_back(thisFilename); + } + } + } + */ + //fill list at GUI + m_Controls->m_FileList->clear(); + for (unsigned int i = 0; i < m_FilenameVector.size(); i++) { new QListWidgetItem(tr(m_FilenameVector.at(i).c_str()), m_Controls->m_FileList); } +} + +void QmitkIGTTrackingDataEvaluationView::OnLoadFileList() +{ + m_FilenameVector = std::vector(); + m_FilenameVector.clear(); + OnAddToCurrentList(); +} + +void QmitkIGTTrackingDataEvaluationView::OnEvaluateData() +{ + //open output file + m_CurrentWriteFile.open(std::string(m_Controls->m_OutputFilename->text().toUtf8()).c_str(), std::ios::out); + if (m_CurrentWriteFile.bad()) + { + MessageBox("Error: Can't open output file!"); + return; + } + + //write output file header + WriteHeader(); + + //start loop and iterate through all files of list + for (int i = 0; i < m_FilenameVector.size(); i++) + { + //create navigation data player + mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = mitk::NavigationDataCSVSequentialPlayer::New(); + myPlayer->SetFiletype(mitk::NavigationDataCSVSequentialPlayer::ManualLoggingCSV); + myPlayer->SetFileName(m_FilenameVector.at(i)); + + //check if the stream is valid and skip file if not + /* + if (!myPlayer->GetStreamValid()) + { + MITK_ERROR << "Error in file " << m_FilenameVector.at(i) << ": " << myPlayer->GetErrorMessage() << " ; Skipping file!"; + + continue; + } + */ + + //create evaluation filter + mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New(); + + //connect pipeline + for (int j = 0; j < myPlayer->GetNumberOfOutputs(); j++) { myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j)); } + + //update pipline until number of samlples is reached + for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); j++) + { + myEvaluationFilter->Update(); + //Debug output: + //std::cout.precision(5); + //std::cout << "Euler " << j << ";" << myPlayer->GetOutput()->GetOrientation().rotation_euler_angles()[0] << ";" << myPlayer->GetOutput()->GetOrientation().rotation_euler_angles()[1] << ";" << myPlayer->GetOutput()->GetOrientation().rotation_euler_angles()[2] << "\n"; + } + + //write result to output file + WriteDataSet(myEvaluationFilter, m_FilenameVector.at(i)); + } + + //close output file + m_CurrentWriteFile.close(); + + //calculate angles if option is on + if (m_Controls->m_settingDifferenceAngles->isChecked() || m_Controls->m_DifferencesSLERP->isChecked()) CalculateDifferenceAngles(); + + MessageBox("Finished!"); +} + +void QmitkIGTTrackingDataEvaluationView::OnGeneratePointSetsOfSinglePositions() +{ + m_scalingfactor = m_Controls->m_ScalingFactor->value(); + + //start loop and iterate through all files of list + for (int i = 0; i < m_FilenameVector.size(); i++) + { + //create point set for this file + mitk::PointSet::Pointer thisPointSet = mitk::PointSet::New(); + + //create navigation data player + mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = mitk::NavigationDataCSVSequentialPlayer::New(); + myPlayer->SetFiletype(mitk::NavigationDataCSVSequentialPlayer::ManualLoggingCSV); + myPlayer->SetFileName(m_FilenameVector.at(i)); + + //check if the stream is valid and skip file if not + /* + if (!myPlayer->GetStreamValid()) + { + MITK_ERROR << "Error in file " << m_FilenameVector.at(i) << ": " << myPlayer->GetErrorMessage() << " ; Skipping file!"; + + continue; + } + */ + + //update pipline until number of samlples is reached and store every single point + for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); j++) + { + myPlayer->Update(); + mitk::Point3D thisPoint = myPlayer->GetOutput()->GetPosition(); + thisPoint[0] *= m_scalingfactor; + thisPoint[1] *= m_scalingfactor; + thisPoint[2] *= m_scalingfactor; + thisPointSet->InsertPoint(j, thisPoint); + } + + //add point set to data storage + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + QString name = this->m_Controls->m_prefix->text() + QString("PointSet_of_All_Positions_") + QString::number(i); + newNode->SetName(name.toStdString()); + newNode->SetData(thisPointSet); + this->GetDataStorage()->Add(newNode); + } +} + +void QmitkIGTTrackingDataEvaluationView::OnGeneratePointSet() +{ + m_scalingfactor = m_Controls->m_ScalingFactor->value(); + + mitk::PointSet::Pointer generatedPointSet = mitk::PointSet::New(); + + //start loop and iterate through all files of list + for (int i = 0; i < m_FilenameVector.size(); i++) + { + //create navigation data player + mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = mitk::NavigationDataCSVSequentialPlayer::New(); + myPlayer->SetFiletype(mitk::NavigationDataCSVSequentialPlayer::ManualLoggingCSV); + myPlayer->SetFileName(m_FilenameVector.at(i)); + + //check if the stream is valid and skip file if not + /* + if (!myPlayer->GetStreamValid()) + { + MITK_ERROR << "Error in file " << m_FilenameVector.at(i) << ": " << myPlayer->GetErrorMessage() << " ; Skipping file!"; + + continue; + } + */ + + //create evaluation filter + mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New(); + + //connect pipeline + for (int j = 0; j < myPlayer->GetNumberOfOutputs(); j++) { myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j)); } + + //update pipline until number of samlples is reached + for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); j++) { myEvaluationFilter->Update(); } + + //add mean position to point set + mitk::Point3D meanPos = myEvaluationFilter->GetPositionMean(0); + if (m_scalingfactor != 1) + { + meanPos[0] *= m_scalingfactor; + meanPos[1] *= m_scalingfactor; + meanPos[2] *= m_scalingfactor; + } + generatedPointSet->InsertPoint(i, meanPos); + } + + //add point set to data storage + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + QString name = this->m_Controls->m_prefix->text() + "PointSet_of_Mean_Positions"; + newNode->SetName(name.toStdString()); + newNode->SetData(generatedPointSet); + this->GetDataStorage()->Add(newNode); +} + +void QmitkIGTTrackingDataEvaluationView::OnGenerateRotationLines() +{ + m_scalingfactor = m_Controls->m_ScalingFactor->value(); + + //start loop and iterate through all files of list + for (int i = 0; i < m_FilenameVector.size(); i++) + { + //create navigation data player + mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = mitk::NavigationDataCSVSequentialPlayer::New(); + myPlayer->SetFiletype(mitk::NavigationDataCSVSequentialPlayer::ManualLoggingCSV); + myPlayer->SetFileName(m_FilenameVector.at(i)); + + //check if the stream is valid and skip file if not + /* + if (!myPlayer->GetStreamValid()) + { + MITK_ERROR << "Error in file " << m_FilenameVector.at(i) << ": " << myPlayer->GetErrorMessage() << " ; Skipping file!"; + } + else + */ + { + //create evaluation filter + mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New(); + + //connect pipeline + for (int j = 0; j < myPlayer->GetNumberOfOutputs(); j++) { myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j)); } + + //update pipline until number of samlples is reached + for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); j++) + { + myEvaluationFilter->Update(); + /* + if (!myPlayer->GetStreamValid()) + { + MITK_ERROR << "Error in file " << m_FilenameVector.at(i) << ": " << myPlayer->GetErrorMessage() << " ; Skipping file!"; + continue; + } + */ + } + //if (!myPlayer->IsAtEnd()) continue; + + //create line from mean pos to a second point which lies along the sensor (1,0,0 in tool coordinates for aurora) + mitk::Point3D meanPos = myEvaluationFilter->GetPositionMean(0); + if (m_scalingfactor != 1) + { + meanPos[0] *= m_scalingfactor; + meanPos[1] *= m_scalingfactor; + meanPos[2] *= m_scalingfactor; + } + mitk::Point3D secondPoint; + mitk::Point3D thirdPoint; + mitk::Point3D fourthPoint; + + mitk::FillVector3D(secondPoint, 2, 0, 0); //X + vnl_vector secondPointTransformed = myEvaluationFilter->GetQuaternionMean(0).rotation_matrix_transpose().transpose() * secondPoint.Get_vnl_vector() + meanPos.Get_vnl_vector(); + mitk::Point3D secondPointTransformedMITK; + mitk::FillVector3D(secondPointTransformedMITK, secondPointTransformed[0], secondPointTransformed[1], secondPointTransformed[2]); + + mitk::FillVector3D(thirdPoint, 0, 4, 0); //Y + vnl_vector thirdPointTransformed = myEvaluationFilter->GetQuaternionMean(0).rotation_matrix_transpose().transpose() * thirdPoint.Get_vnl_vector() + meanPos.Get_vnl_vector(); + mitk::Point3D thirdPointTransformedMITK; + mitk::FillVector3D(thirdPointTransformedMITK, thirdPointTransformed[0], thirdPointTransformed[1], thirdPointTransformed[2]); + + mitk::FillVector3D(fourthPoint, 0, 0, 6); //Z + vnl_vector fourthPointTransformed = myEvaluationFilter->GetQuaternionMean(0).rotation_matrix_transpose().transpose() * fourthPoint.Get_vnl_vector() + meanPos.Get_vnl_vector(); + mitk::Point3D fourthPointTransformedMITK; + mitk::FillVector3D(fourthPointTransformedMITK, fourthPointTransformed[0], fourthPointTransformed[1], fourthPointTransformed[2]); + + mitk::PointSet::Pointer rotationLine = mitk::PointSet::New(); + rotationLine->InsertPoint(0, secondPointTransformedMITK); + rotationLine->InsertPoint(1, meanPos); + rotationLine->InsertPoint(2, thirdPointTransformedMITK); + rotationLine->InsertPoint(3, meanPos); + rotationLine->InsertPoint(4, fourthPointTransformedMITK); + + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + QString nodeName = this->m_Controls->m_prefix->text() + "RotationLineNumber" + QString::number(i); + newNode->SetName(nodeName.toStdString()); + newNode->SetData(rotationLine); + newNode->SetBoolProperty("show contour", true); + newNode->SetFloatProperty("pointsize", 0.5); + this->GetDataStorage()->Add(newNode); + } + } +} + +void QmitkIGTTrackingDataEvaluationView::OnGenerateGroundTruthPointSet() +{ + mitk::PointSet::Pointer generatedPointSet = mitk::PointSet::New(); + int currentPointID = 0; + mitk::Point3D currentPoint; + mitk::FillVector3D(currentPoint, 0, 0, 0); + for (int i = 0; i < m_Controls->m_PointNumber1->value(); i++) + { + for (int j = 0; j < m_Controls->m_PointNumber2->value(); j++) + { + generatedPointSet->InsertPoint(currentPointID, currentPoint); + currentPointID++; + currentPoint[1] += m_Controls->m_PointDistance->value(); + } + currentPoint[1] = 0; + currentPoint[2] += m_Controls->m_PointDistance->value(); + } + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + QString nodeName = "GroundTruthPointSet_" + QString::number(m_Controls->m_PointNumber1->value()) + "x" + QString::number(m_Controls->m_PointNumber2->value()) + "_(" + QString::number(m_Controls->m_PointDistance->value()) + "mm)"; + newNode->SetName(nodeName.toStdString()); + newNode->SetData(generatedPointSet); + this->GetDataStorage()->Add(newNode); +} + +void QmitkIGTTrackingDataEvaluationView::OnConvertCSVtoXMLFile() +{ + if (m_Controls->m_ConvertSingleFile->isChecked()) + { //convert one file + int lines = ConvertOneFile(this->m_Controls->m_InputCSV->text().toStdString(), this->m_Controls->m_OutputXML->text().toStdString()); + + QString result = "Converted one file with" + QString::number(lines) + " data sets"; + MessageBox(result.toStdString()); + } + else //converte file list + { + if (m_CSVtoXMLInputFilenameVector.empty() || m_CSVtoXMLOutputFilenameVector.empty()) + { + MessageBox("Error: one list is not loaded!"); + return; + } + else if (m_CSVtoXMLInputFilenameVector.size() != m_CSVtoXMLOutputFilenameVector.size()) + { + MessageBox("Error: lists do not have the same number of files!"); + return; + } + for (int i = 0; i < m_CSVtoXMLInputFilenameVector.size(); i++) + { + int lines = ConvertOneFile(m_CSVtoXMLInputFilenameVector.at(i), m_CSVtoXMLOutputFilenameVector.at(i)); + } + QString result = "Converted " + QString::number(m_CSVtoXMLInputFilenameVector.size()) + " files from file list!"; + MessageBox(result.toStdString()); + } +} + +int QmitkIGTTrackingDataEvaluationView::ConvertOneFile(std::string inputFilename, std::string outputFilename) +{ + std::vector myNavigationDatas = GetNavigationDatasFromFile(inputFilename); + mitk::NavigationDataRecorderDeprecated::Pointer myRecorder = mitk::NavigationDataRecorderDeprecated::New(); + myRecorder->SetFileName(outputFilename.c_str()); + mitk::NavigationData::Pointer input = mitk::NavigationData::New(); + if (m_Controls->m_ConvertCSV->isChecked()) myRecorder->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::csv); + myRecorder->AddNavigationData(input); + myRecorder->StartRecording(); + for (int i = 0; i < myNavigationDatas.size(); i++) + { + input->Graft(myNavigationDatas.at(i)); + myRecorder->Update(); + } + myRecorder->StopRecording(); + return myNavigationDatas.size(); +} + +void QmitkIGTTrackingDataEvaluationView::OnCSVtoXMLLoadInputList() +{ + //read in filename + QString filename = QFileDialog::getOpenFileName(NULL, tr("Open Measurement Filename List"), "/", tr("All Files (*.*)")); + if (filename.isNull()) return; + + m_CSVtoXMLInputFilenameVector = this->GetFileContentLineByLine(filename.toStdString()); + + m_Controls->m_labelCSVtoXMLInputList->setText("READY"); +} + +void QmitkIGTTrackingDataEvaluationView::OnCSVtoXMLLoadOutputList() +{ + //read in filename + QString filename = QFileDialog::getOpenFileName(NULL, tr("Open Measurement Filename List"), "/", tr("All Files (*.*)")); + if (filename.isNull()) return; + + m_CSVtoXMLOutputFilenameVector = this->GetFileContentLineByLine(filename.toStdString()); + + m_Controls->m_labelCSVtoXMLOutputList->setText("READY"); +} + +void QmitkIGTTrackingDataEvaluationView::MessageBox(std::string s) +{ + QMessageBox msgBox; + msgBox.setText(s.c_str()); + msgBox.exec(); +} + +void QmitkIGTTrackingDataEvaluationView::WriteHeader() +{ + m_CurrentWriteFile << "Filename;"; + m_CurrentWriteFile << "N;"; + m_CurrentWriteFile << "N_invalid;"; + m_CurrentWriteFile << "Percentage_invalid;"; + + if (m_Controls->m_settingPosMean->isChecked()) + { + m_CurrentWriteFile << "Position_Mean[x];"; + m_CurrentWriteFile << "Position_Mean[y];"; + m_CurrentWriteFile << "Position_Mean[z];"; + } + + if (m_Controls->m_settingPosStabw->isChecked()) + { + m_CurrentWriteFile << "Position_StandDev[x];"; + m_CurrentWriteFile << "Position_StandDev[y];"; + m_CurrentWriteFile << "Position_StandDev[z];"; + } + + if (m_Controls->m_settingPosSampleStabw->isChecked()) + { + m_CurrentWriteFile << "Position_SampleStandDev[x];"; + m_CurrentWriteFile << "Position_SampleStandDev[y];"; + m_CurrentWriteFile << "Position_SampleStandDev[z];"; + } + + if (m_Controls->m_settingQuaternionMean->isChecked()) + { + m_CurrentWriteFile << "Quaternion_Mean[qx];"; + m_CurrentWriteFile << "Quaternion_Mean[qy];"; + m_CurrentWriteFile << "Quaternion_Mean[qz];"; + m_CurrentWriteFile << "Quaternion_Mean[qr];"; + } + + if (m_Controls->m_settionQuaternionStabw->isChecked()) + { + m_CurrentWriteFile << "Quaternion_StandDev[qx];"; + m_CurrentWriteFile << "Quaternion_StandDev[qy];"; + m_CurrentWriteFile << "Quaternion_StandDev[qz];"; + m_CurrentWriteFile << "Quaternion_StandDev[qr];"; + } + + if (m_Controls->m_settingPosErrorMean->isChecked()) m_CurrentWriteFile << "PositionError_Mean;"; + + if (m_Controls->m_settingPosErrorStabw->isChecked()) m_CurrentWriteFile << "PositionError_StandDev;"; + + if (m_Controls->m_settingPosErrorSampleStabw->isChecked()) m_CurrentWriteFile << "PositionError_SampleStandDev;"; + + if (m_Controls->m_settingPosErrorRMS->isChecked()) m_CurrentWriteFile << "PositionError_RMS;"; + + if (m_Controls->m_settingPosErrorMedian->isChecked()) m_CurrentWriteFile << "PositionError_Median;"; + + if (m_Controls->m_settingPosErrorMinMax->isChecked()) + { + m_CurrentWriteFile << "PositionError_Max;"; + m_CurrentWriteFile << "PositionError_Min;"; + } + + if (m_Controls->m_settingEulerMean->isChecked()) + { + m_CurrentWriteFile << "Euler_tx;"; + m_CurrentWriteFile << "Euler_ty;"; + m_CurrentWriteFile << "Euler_tz;"; + } + + if (m_Controls->m_settingEulerRMS->isChecked()) + { + m_CurrentWriteFile << "EulerErrorRMS (rad);"; + m_CurrentWriteFile << "EulerErrorRMS (grad);"; + } + + m_CurrentWriteFile << "\n"; +} + +void QmitkIGTTrackingDataEvaluationView::WriteDataSet(mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter, std::string dataSetName) +{ + if (myEvaluationFilter->GetNumberOfOutputs() == 0) m_CurrentWriteFile << "Error: no input \n"; + else + { + m_CurrentWriteFile << dataSetName << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetNumberOfAnalysedNavigationData(0) << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetNumberOfInvalidSamples(0) << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetPercentageOfInvalidSamples(0) << ";"; + + if (m_Controls->m_settingPosMean->isChecked()) + { + m_CurrentWriteFile << myEvaluationFilter->GetPositionMean(0)[0] << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetPositionMean(0)[1] << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetPositionMean(0)[2] << ";"; + } + + if (m_Controls->m_settingPosStabw->isChecked()) + { + m_CurrentWriteFile << myEvaluationFilter->GetPositionStandardDeviation(0)[0] << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetPositionStandardDeviation(0)[1] << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetPositionStandardDeviation(0)[2] << ";"; + } + + if (m_Controls->m_settingPosSampleStabw->isChecked()) + { + m_CurrentWriteFile << myEvaluationFilter->GetPositionSampleStandardDeviation(0)[0] << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetPositionSampleStandardDeviation(0)[1] << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetPositionSampleStandardDeviation(0)[2] << ";"; + } + + if (m_Controls->m_settingQuaternionMean->isChecked()) + { + m_CurrentWriteFile << myEvaluationFilter->GetQuaternionMean(0).x() << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetQuaternionMean(0).y() << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetQuaternionMean(0).z() << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetQuaternionMean(0).r() << ";"; + } + + if (m_Controls->m_settionQuaternionStabw->isChecked()) + { + m_CurrentWriteFile << myEvaluationFilter->GetQuaternionStandardDeviation(0).x() << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetQuaternionStandardDeviation(0).y() << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetQuaternionStandardDeviation(0).z() << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetQuaternionStandardDeviation(0).r() << ";"; + } + + if (m_Controls->m_settingPosErrorMean->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorMean(0) << ";"; + if (m_Controls->m_settingPosErrorStabw->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorStandardDeviation(0) << ";"; + if (m_Controls->m_settingPosErrorSampleStabw->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorSampleStandardDeviation(0) << ";"; + if (m_Controls->m_settingPosErrorRMS->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorRMS(0) << ";"; + if (m_Controls->m_settingPosErrorMedian->isChecked()) m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorMedian(0) << ";"; + if (m_Controls->m_settingPosErrorMinMax->isChecked()) + { + m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorMax(0) << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetPositionErrorMin(0) << ";"; + } + + if (m_Controls->m_settingEulerMean->isChecked()) + { + m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesMean(0)[0] << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesMean(0)[1] << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesMean(0)[2] << ";"; + } + + if (m_Controls->m_settingEulerRMS->isChecked()) + { + m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesRMS(0) << ";"; + m_CurrentWriteFile << myEvaluationFilter->GetEulerAnglesRMSDegree(0) << ";"; + } + + m_CurrentWriteFile << "\n"; + } +} + +void QmitkIGTTrackingDataEvaluationView::CalculateDifferenceAngles() +{ + std::vector EvaluationDataCollection; + + //start loop and iterate through all files of list: store the evaluation data + for (int i = 0; i < m_FilenameVector.size(); i++) + { + //create navigation data player + mitk::NavigationDataCSVSequentialPlayer::Pointer myPlayer = mitk::NavigationDataCSVSequentialPlayer::New(); + myPlayer->SetFiletype(mitk::NavigationDataCSVSequentialPlayer::ManualLoggingCSV); + myPlayer->SetFileName(m_FilenameVector.at(i)); + + //create evaluation filter + mitk::NavigationDataEvaluationFilter::Pointer myEvaluationFilter = mitk::NavigationDataEvaluationFilter::New(); + + //check if the stream is valid and skip file if not + /* + if (!myPlayer->GetStreamValid()) + { + MITK_ERROR << "Error in file " << m_FilenameVector.at(i) << ": " << myPlayer->GetErrorMessage() << " ; Skipping file!"; + } + else + */ + { + //connect pipeline + for (int j = 0; j < myPlayer->GetNumberOfOutputs(); j++) { myEvaluationFilter->SetInput(j, myPlayer->GetOutput(j)); } + //update pipline until number of samlples is reached + for (int j = 0; j < m_Controls->m_NumberOfSamples->value(); j++) { myEvaluationFilter->Update(); } + } + + myEvaluationFilter->SetInput(NULL); + myPlayer = NULL; + EvaluationDataCollection.push_back(myEvaluationFilter); + } + + //calculation and writing of output data + //open output file + m_CurrentAngleDifferencesWriteFile.open(std::string((m_Controls->m_OutputFilename->text() + ".angledifferences.csv").toUtf8()).c_str(), std::ios::out); + if (m_CurrentAngleDifferencesWriteFile.bad()) + { + MessageBox("Error: Can't open output file for angle differences calculation!"); + return; + } + //write header + WriteDifferenceAnglesHeader(); + //compute angle differences + QString pos1 = "invalid"; + QString pos2 = "invalid"; + //now iterate through all evaluation data and calculate the angles + for (int i = 0; i < m_FilenameVector.size(); i++) + { + pos1 = QString::fromStdString(itksys::SystemTools::GetFilenameWithoutLastExtension(m_FilenameVector.at(i))); + for (int j = 0; j < m_FilenameVector.size(); j++) + { + pos2 = QString::fromStdString(itksys::SystemTools::GetFilenameWithoutLastExtension(m_FilenameVector.at(j))); + + mitk::Quaternion q1; + mitk::Quaternion q2; + + if (m_Controls->m_DifferencesSLERP->isChecked()) + { + //compute slerp average + q1 = GetSLERPAverage(EvaluationDataCollection.at(i)); + q2 = GetSLERPAverage(EvaluationDataCollection.at(j)); + } + else + { + //compute arithmetic average + q1 = EvaluationDataCollection.at(i)->GetQuaternionMean(0); + q2 = EvaluationDataCollection.at(j)->GetQuaternionMean(0); + } + + double AngleBetweenTwoQuaternions = GetAngleBetweenTwoQuaterions(q1, q2); + + //write data set + WriteDifferenceAnglesDataSet(pos1.toStdString(), pos2.toStdString(), i, j, AngleBetweenTwoQuaternions); + } + } + + //close output file + m_CurrentAngleDifferencesWriteFile.close(); +} + +void QmitkIGTTrackingDataEvaluationView::WriteDifferenceAnglesHeader() +{ + m_CurrentAngleDifferencesWriteFile << "Name;Idx1;Idx2;Angle [-PI..+PI]; Angle [Degree]\n"; +} + +void QmitkIGTTrackingDataEvaluationView::WriteDifferenceAnglesDataSet(std::string pos1, std::string pos2, int idx1, int idx2, double angle) +{ + double PI = 3.1415926535897932384626433832795; + double angle_degree = angle * 180 / PI; + m_CurrentAngleDifferencesWriteFile << "Angle between " << pos1 << " and " << pos2 << ";" << idx1 << ";" << idx2 << ";" << angle << ";" << angle_degree << "\n"; + MITK_INFO << "Angle: " << angle_degree; +} + +double QmitkIGTTrackingDataEvaluationView::GetAngleBetweenTwoQuaterions(mitk::Quaternion a, mitk::Quaternion b) +{ + double returnValue; + + //variant to work with the data received from the polhemus tracker + returnValue = ((a[0] * b[0] + a[1] * b[1] + a[2] * b[2] + a[3] * b[3]) / (sqrt(a[0] * a[0] + a[1] * a[1] + a[2] * a[2] + a[3] * a[3])*sqrt(b[0] * b[0] + b[1] * b[1] + b[2] * b[2] + b[3] * b[3]))); + returnValue = 2 * acos(returnValue); + + /* + //another variant + mitk::Quaternion combinedRotation = b * a; + + itk::Vector pt1; //caution 5D-Tools: Vector must lie in the YZ-plane for a correct result. + pt1[0] = 0.0; + pt1[1] = 0.0; + pt1[2] = 100000.0; + + itk::Matrix rotMatrixA; + for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) rotMatrixA[i][j] = combinedRotation.rotation_matrix_transpose().transpose()[i][j]; + itk::Vector pt2 = rotMatrixA*pt1; + + //compute angle between the two vectors + returnValue = (pt1[0] * pt2[0] + pt1[1] * pt2[1] + pt1[2] * pt2[2]) / (sqrt(pow(pt1[0], 2) + pow(pt1[1], 2) + pow(pt1[2], 2)) * sqrt(pow(pt2[0], 2) + pow(pt2[1], 2) + pow(pt2[2], 2))); + returnValue = acos(returnValue); + */ + /* + //variant with double precision + + itk::Vector point; //caution 5D-Tools: Vector must lie in the YZ-plane for a correct result. + //TODO: welchen Vektor hier nehmen? + point[0] = 0; + point[1] = 100000.0; + point[2] = 100000.0; + + //OB DAS HILFT? + a.normalize(); + b.normalize(); + + itk::Matrix rotMatrixA; + for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) rotMatrixA[i][j] = a.rotation_matrix_transpose().transpose()[i][j]; + + itk::Matrix rotMatrixB; + for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) rotMatrixB[i][j] = b.rotation_matrix_transpose().transpose()[i][j]; + + itk::Vector pt1 = rotMatrixA * point; + itk::Vector pt2 = rotMatrixB * point; + + returnValue = (pt1[0] * pt2[0] + pt1[1] * pt2[1] + pt1[2] * pt2[2]) / (sqrt(pow(pt1[0], 2.0) + pow(pt1[1], 2.0) + pow(pt1[2], 2.0)) * sqrt(pow(pt2[0], 2.0) + pow(pt2[1], 2.0) + pow(pt2[2], 2.0))); + returnValue = acos(returnValue); + */ + /* + // same code with float precision: + mitk::Point3D point; + mitk::FillVector3D(point, 0, 0, 100); //caution 5D-Tools: Vector must lie in the YZ-plane for a correct result. + vnl_vector pt1 = a.rotate(point.Get_vnl_vector()); + vnl_vector pt2 = b.rotate(point.Get_vnl_vector()); + + //compute angle between the two vectors + returnValue = (pt1[0] * pt2[0] + pt1[1] * pt2[1] + pt1[2] * pt2[2]) / (sqrt(pow(pt1[0], 2) + pow(pt1[1], 2) + pow(pt1[2], 2)) * sqrt(pow(pt2[0], 2) + pow(pt2[1], 2) + pow(pt2[2], 2))); + returnValue = acos(returnValue); + //angle(pt1,pt2); + */ + return returnValue; +} + +std::vector QmitkIGTTrackingDataEvaluationView::GetNavigationDatasFromFile(std::string filename) +{ + std::vector returnValue = std::vector(); + std::vector fileContentLineByLine = GetFileContentLineByLine(filename); + for (int i = 1; i < fileContentLineByLine.size(); i++) //skip header so start at 1 + { + returnValue.push_back(GetNavigationDataOutOfOneLine(fileContentLineByLine.at(i))); + } + + return returnValue; +} + +std::vector QmitkIGTTrackingDataEvaluationView::GetFileContentLineByLine(std::string filename) +{ + std::vector readData = std::vector(); + + //save old locale + char * oldLocale; + oldLocale = setlocale(LC_ALL, 0); + + //define own locale + std::locale C("C"); + setlocale(LC_ALL, "C"); + + //read file + std::ifstream file; + file.open(filename.c_str(), std::ios::in); + if (file.good()) + { + //read out file + file.seekg(0L, std::ios::beg); // move to begin of file + while (!file.eof()) + { + std::string buffer; + std::getline(file, buffer); // read out file line by line + if (buffer.size() > 0) readData.push_back(buffer); + } + } + + file.close(); + + //switch back to old locale + setlocale(LC_ALL, oldLocale); + + return readData; +} + +mitk::NavigationData::Pointer QmitkIGTTrackingDataEvaluationView::GetNavigationDataOutOfOneLine(std::string line) +{ + mitk::NavigationData::Pointer returnValue = mitk::NavigationData::New(); + + QString myLine = QString(line.c_str()); + + QStringList myLineList = myLine.split(';'); + + mitk::Point3D position; + mitk::Quaternion orientation; + + double time = myLineList.at(1).toDouble(); + + bool valid = false; + if (myLineList.at(2).toStdString() == "1") valid = true; + + position[0] = myLineList.at(3).toDouble(); + position[1] = myLineList.at(4).toDouble(); + position[2] = myLineList.at(5).toDouble(); + + orientation[0] = myLineList.at(6).toDouble(); + orientation[1] = myLineList.at(7).toDouble(); + orientation[2] = myLineList.at(8).toDouble(); + orientation[3] = myLineList.at(9).toDouble(); + + //returnValue->SetTimeStamp(time); + returnValue->SetDataValid(valid); + returnValue->SetPosition(position); + returnValue->SetOrientation(orientation); + + return returnValue; +} + +mitk::Quaternion QmitkIGTTrackingDataEvaluationView::GetSLERPAverage(mitk::NavigationDataEvaluationFilter::Pointer evaluationFilter) +{ + mitk::Quaternion average; + + //build a vector of quaternions from the evaulation filter (caution always takes the first (0) input of the filter + std::vector quaternions = std::vector(); + for (int i = 0; i < evaluationFilter->GetNumberOfAnalysedNavigationData(0); i++) + { + mitk::Quaternion currentq = evaluationFilter->GetLoggedOrientation(i, 0); + + quaternions.push_back(currentq); + } + + //compute the slerp average using the quaternion averaging class + mitk::QuaternionAveraging::Pointer myAverager = mitk::QuaternionAveraging::New(); + average = myAverager->CalcAverage(quaternions); + + return average; +} diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingDataEvaluationView.h b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingDataEvaluationView.h new file mode 100644 index 0000000000..8a5a688a51 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingDataEvaluationView.h @@ -0,0 +1,123 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkIGTTrackingDataEvaluationView_h +#define QmitkIGTTrackingDataEvaluationView_h + +#include + +#include + +#include "ui_QmitkIGTTrackingDataEvaluationViewControls.h" + +#include + + + +/*! + \brief QmitkIGTTrackingDataEvaluationView + + \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. + + \sa QmitkFunctionality + \ingroup Functionalities +*/ +class QmitkIGTTrackingDataEvaluationView : 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; + + QmitkIGTTrackingDataEvaluationView(); + virtual ~QmitkIGTTrackingDataEvaluationView(); + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void StdMultiWidgetAvailable (QmitkStdMultiWidget &stdMultiWidget); + virtual void StdMultiWidgetNotAvailable(); + + protected slots: + + void OnLoadFileList(); + void OnAddToCurrentList(); + void OnEvaluateData(); + void OnGeneratePointSet(); + void OnGeneratePointSetsOfSinglePositions(); + void OnGenerateRotationLines(); + void OnGenerateGroundTruthPointSet(); + void OnConvertCSVtoXMLFile(); + void OnCSVtoXMLLoadInputList(); + void OnCSVtoXMLLoadOutputList(); + + /** Reads in exactly three position files als reference. */ + void OnOrientationCalculation_CalcRef(); + /** Uses always three positions (1,2,3: first orientation; 4,5,6: second orientation; and so on) in every file to calcualte a orientation. */ + void OnOrientationCalculation_CalcOrientandWriteToFile(); + + + protected: + + Ui::QmitkIGTTrackingDataEvaluationViewControls* m_Controls; + + QmitkStdMultiWidget* m_MultiWidget; + + std::vector m_FilenameVector; + + void MessageBox(std::string s); + + std::fstream m_CurrentWriteFile; + void WriteHeader(); + void WriteDataSet(mitk::NavigationDataEvaluationFilter::Pointer evaluationFilter, std::string dataSetName); + + //members for orientation calculation + mitk::Point3D m_RefPoint1; + mitk::Point3D m_RefPoint2; + mitk::Point3D m_RefPoint3; + + double m_scalingfactor; //scaling factor for visualization, 1 by default + + //angle diffrences: seperated file + std::fstream m_CurrentAngleDifferencesWriteFile; + void CalculateDifferenceAngles(); + void WriteDifferenceAnglesHeader(); + void WriteDifferenceAnglesDataSet(std::string pos1, std::string pos2, int idx1, int idx2, double angle); + + //different help methods to read a csv logging file + std::vector GetNavigationDatasFromFile(std::string filename); + std::vector GetFileContentLineByLine(std::string filename); + mitk::NavigationData::Pointer GetNavigationDataOutOfOneLine(std::string line); + + //CSV to XML members + std::vector m_CSVtoXMLInputFilenameVector; + std::vector m_CSVtoXMLOutputFilenameVector; + + //returns the number of converted lines + int ConvertOneFile(std::string inputFilename, std::string outputFilename); + + /** @brief calculates the angle in the plane perpendicular to the rotation axis of the two quaterions. */ + double GetAngleBetweenTwoQuaterions(mitk::Quaternion a, mitk::Quaternion b); + + /** @brief calculates the slerp average of a set of quaternions which is stored in the navigation data evaluation filter */ + mitk::Quaternion GetSLERPAverage(mitk::NavigationDataEvaluationFilter::Pointer); +}; + + + +#endif // _QMITKIGTTRACKINGDATAEVALUATIONVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingDataEvaluationViewControls.ui b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingDataEvaluationViewControls.ui new file mode 100644 index 0000000000..e2b4e65966 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingDataEvaluationViewControls.ui @@ -0,0 +1,941 @@ + + + QmitkIGTTrackingDataEvaluationViewControls + + + + 0 + 0 + 378 + 955 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + 0 + + + + Evaluation + + + + + + Input File List (recorded NavigationData / *.csv): + + + + + + + + + + + + Add Path: + + + + + + + D:/Experimente/ + + + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-style:italic;">(use text files with a complete filename in every line)</span></p></body></html> + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 110 + 0 + + + + Load New List + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 110 + 0 + + + + Add To Current List + + + + + + + + + + + Number of samples to analyze: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1000000 + + + 150 + + + + + + + + + + + Result CSV Filename: + + + + + + + D:/tmp/output.csv + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 200 + 50 + + + + + 200 + 50 + + + + START EVALUATION + + + + + + + + + Qt::Horizontal + + + + + + + Visualization Tools: + + + + + + + Generate PointSet of Mean Positions + + + + + + + Generate PointSets of Single Positions + + + + + + + Generate Lines for Rotation + + + + + + + + + Prefix for Data Nodes: + + + + + + + + + + + + Qt::Vertical + + + QSizePolicy::Expanding + + + + 20 + 220 + + + + + + + + + Settings + + + + + + Output Settings + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-style:italic; text-decoration: underline;">Position</span></p></body></html> + + + + + + + Mean (x,y,z) + + + + + + + Standard Deviation (x,y,z) + + + + + + + Sample Standard Deviation (x,y,z) + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-style:italic; text-decoration: underline;">Orientation</span></p></body></html> + + + + + + + Quaternion Mean (qx,qy,qz,qr) + + + + + + + Quaternion Mean (SLERP) + + + + + + + Quaternion Standard Deviation (qx,qy,qz,qr) + + + + + + + Euler Mean (tx,ty,tz) + + + + + + + Difference Angles to all other Positions + + + + + + + Difference Angles to all other Positions (SLERP) + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-style:italic; text-decoration: underline;">Position Error</span></p></body></html> + + + + + + + Mean + + + + + + + Standard Deviation + + + + + + + Sample Standard Deviation + + + + + + + RMS + + + + + + + Median + + + + + + + Min/Max + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-style:italic; text-decoration: underline;">Orientation Error</span></p></body></html> + + + + + + + Euler RMS + + + + + + + + + + + + Scaling Factor for Visualization: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1.000000000000000 + + + + + + + + + Qt::Vertical + + + + 20 + 344 + + + + + + + + + Tools + + + + + + Point Set Ground Truth Generator + + + + + + + + Generate + + + + + + + 1 + + + 999 + + + 10 + + + + + + + X + + + + + + + 1 + + + 999 + + + 9 + + + + + + + Point Set + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + Inter Point Distance (in mm): + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1 + + + 99999 + + + 50 + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Generate + + + + + + + + + + + + Result CSV File to NavigationData Converter + + + + + + Convert Single File + + + true + + + + + + + Input CSV Logging File: + + + + + + + C:/Tools/test.csv + + + + + + + Output Navigation Data File: + + + + + + + C:/Tools/testoutput.xml + + + + + + + Qt::Horizontal + + + + + + + Convert File List + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-style:italic;">(use text files with a complete filename in every line)</span></p></body></html> + + + + + + + + + not loaded + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 100 + 0 + + + + Load Input List + + + + + + + + + + + not loaded + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 100 + 0 + + + + Load Output List + + + + + + + + + Qt::Horizontal + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Output Format + + + + + + XML + + + true + + + + + + + CSV + + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Convert + + + + + + + + + + + + Orientation Calculation (out of three positions) + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Generate Reference From Current List + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Write Orientation Quaternions To File + + + + + + + + + + + + Qt::Vertical + + + + 20 + 632 + + + + + + + + + + + + + + diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.cpp b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.cpp new file mode 100644 index 0000000000..4d9416ddea --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.cpp @@ -0,0 +1,666 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +// Blueberry +#include +#include + +// Qmitk +#include "QmitkIGTTrackingSemiAutomaticMeasurementView.h" +#include "QmitkStdMultiWidget.h" + +// Qt +#include +#include +#include +#include + +// MITK +#include +#include +#include + +// POCO +#include +#include + +const std::string QmitkIGTTrackingSemiAutomaticMeasurementView::VIEW_ID = "org.mitk.views.igttrackingsemiautomaticmeasurement"; + +QmitkIGTTrackingSemiAutomaticMeasurementView::QmitkIGTTrackingSemiAutomaticMeasurementView() + : QmitkFunctionality() + , m_Controls(0) + , m_MultiWidget(NULL) +{ + m_NextFile = 0; + m_FilenameVector = std::vector(); + m_Timer = new QTimer(this); + m_logging = false; + m_referenceValid = true; + m_tracking = false; + m_EvaluationFilter = mitk::NavigationDataEvaluationFilter::New(); +} + +QmitkIGTTrackingSemiAutomaticMeasurementView::~QmitkIGTTrackingSemiAutomaticMeasurementView() +{ +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::CreateResults() +{ + QString LogFileName = m_Controls->m_OutputPath->text() + "_results.log"; + mitk::LoggingBackend::Unregister(); + mitk::LoggingBackend::SetLogFile(LogFileName.toStdString().c_str()); + mitk::LoggingBackend::Register(); + + double RMSmean = 0; + for (int i = 0; i < m_RMSValues.size(); i++) + { + MITK_INFO << "RMS at " << this->m_FilenameVector.at(i) << ": " << m_RMSValues.at(i); + RMSmean += m_RMSValues.at(i); + } + RMSmean /= m_RMSValues.size(); + MITK_INFO << "RMS mean over " << m_RMSValues.size() << " values: " << RMSmean; + + mitk::DataNode::Pointer newNode = mitk::DataNode::New(); + newNode->SetName("Tracking Results"); + newNode->SetData(this->m_MeanPoints); + this->GetDataStorage()->Add(newNode); + + if (m_MeanPoints->GetSize() == 12) + { + MITK_INFO << "Computing distance error for Compact FG..."; + std::vector distances; + mitk::Point3D test; + //row 1 + distances.push_back(m_MeanPoints->GetPoint(0).EuclideanDistanceTo(m_MeanPoints->GetPoint(1))); //0 + distances.push_back(m_MeanPoints->GetPoint(1).EuclideanDistanceTo(m_MeanPoints->GetPoint(2))); //1 + distances.push_back(m_MeanPoints->GetPoint(2).EuclideanDistanceTo(m_MeanPoints->GetPoint(3))); //2 + //row 2 + distances.push_back(m_MeanPoints->GetPoint(4).EuclideanDistanceTo(m_MeanPoints->GetPoint(5))); //3 + distances.push_back(m_MeanPoints->GetPoint(5).EuclideanDistanceTo(m_MeanPoints->GetPoint(6))); //4 + distances.push_back(m_MeanPoints->GetPoint(6).EuclideanDistanceTo(m_MeanPoints->GetPoint(7))); //5 + //row 3 + distances.push_back(m_MeanPoints->GetPoint(8).EuclideanDistanceTo(m_MeanPoints->GetPoint(9))); //6 + distances.push_back(m_MeanPoints->GetPoint(9).EuclideanDistanceTo(m_MeanPoints->GetPoint(10))); //7 + distances.push_back(m_MeanPoints->GetPoint(10).EuclideanDistanceTo(m_MeanPoints->GetPoint(11))); //8 + //column 1 + distances.push_back(m_MeanPoints->GetPoint(0).EuclideanDistanceTo(m_MeanPoints->GetPoint(4))); //9 + distances.push_back(m_MeanPoints->GetPoint(4).EuclideanDistanceTo(m_MeanPoints->GetPoint(8))); //10 + //column 2 + distances.push_back(m_MeanPoints->GetPoint(1).EuclideanDistanceTo(m_MeanPoints->GetPoint(5))); //11 + distances.push_back(m_MeanPoints->GetPoint(5).EuclideanDistanceTo(m_MeanPoints->GetPoint(9))); //12 + //column 3 + distances.push_back(m_MeanPoints->GetPoint(2).EuclideanDistanceTo(m_MeanPoints->GetPoint(6))); //13 + distances.push_back(m_MeanPoints->GetPoint(6).EuclideanDistanceTo(m_MeanPoints->GetPoint(10))); //14 + //column 4 + distances.push_back(m_MeanPoints->GetPoint(3).EuclideanDistanceTo(m_MeanPoints->GetPoint(7))); //15 + distances.push_back(m_MeanPoints->GetPoint(7).EuclideanDistanceTo(m_MeanPoints->GetPoint(11))); //16 + + std::vector errors; + double meanError = 0; + for (int i = 0; i < distances.size(); i++) + { + double currentError = distances.at(i) - (double)50.0; + errors.push_back(currentError); + meanError += currentError; + MITK_INFO << "Error" << i << " : " << currentError; + } + meanError /= distances.size(); + MITK_INFO << "Mean error : " << meanError; + } +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::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::QmitkIGTTrackingSemiAutomaticMeasurementViewControls; + m_Controls->setupUi(parent); + + //buttons + connect(m_Controls->m_LoadMeasurementToolStorage, SIGNAL(clicked()), this, SLOT(OnLoadMeasurementStorage())); + connect(m_Controls->m_LoadReferenceToolStorage, SIGNAL(clicked()), this, SLOT(OnLoadReferenceStorage())); + connect(m_Controls->m_StartTracking, SIGNAL(clicked()), this, SLOT(OnStartTracking())); + connect(m_Controls->m_LoadList, SIGNAL(clicked()), this, SLOT(OnMeasurementLoadFile())); + connect(m_Controls->m_StartNextMeasurement, SIGNAL(clicked()), this, SLOT(StartNextMeasurement())); + connect(m_Controls->m_ReapeatLastMeasurement, SIGNAL(clicked()), this, SLOT(RepeatLastMeasurement())); + connect(m_Controls->m_SetReference, SIGNAL(clicked()), this, SLOT(OnSetReference())); + connect(m_Controls->m_UseReferenceTrackingSystem, SIGNAL(toggled(bool)), this, SLOT(OnUseReferenceToggled(bool))); + connect(m_Controls->m_CreateResults, SIGNAL(clicked()), this, SLOT(CreateResults())); + + //event filter + qApp->installEventFilter(this); + + //timers + connect(m_Timer, SIGNAL(timeout()), this, SLOT(UpdateTimer())); + } + + //initialize some view + m_Controls->m_StopTracking->setEnabled(false); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::StdMultiWidgetAvailable(QmitkStdMultiWidget &stdMultiWidget) +{ + m_MultiWidget = &stdMultiWidget; +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::OnUseReferenceToggled(bool state) +{ + if (state) + { + m_Controls->m_ReferenceBox->setEnabled(true); + m_Controls->m_SetReference->setEnabled(true); + } + + else + { + m_Controls->m_ReferenceBox->setEnabled(false); + m_Controls->m_SetReference->setEnabled(false); + } +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::StdMultiWidgetNotAvailable() +{ + m_MultiWidget = NULL; +} + +mitk::NavigationToolStorage::Pointer QmitkIGTTrackingSemiAutomaticMeasurementView::ReadStorage(std::string file) +{ + mitk::NavigationToolStorage::Pointer returnValue; + + //initialize tool storage + returnValue = mitk::NavigationToolStorage::New(); + + //read tool storage from disk + mitk::NavigationToolStorageDeserializer::Pointer myDeserializer = mitk::NavigationToolStorageDeserializer::New(GetDataStorage()); + returnValue = myDeserializer->Deserialize(file); + if (returnValue.IsNull()) + { + QMessageBox msgBox; + msgBox.setText(myDeserializer->GetErrorMessage().c_str()); + msgBox.exec(); + + returnValue = NULL; + } + + return returnValue; +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::OnSetReference() +{ + //initialize reference + m_ReferenceStartPositions = std::vector(); + m_ReferenceTrackingDeviceSource->Update(); + QString Label = "Positions At Start: "; + for (int i = 0; i < m_ReferenceTrackingDeviceSource->GetNumberOfOutputs(); i++) + { + mitk::Point3D position = m_ReferenceTrackingDeviceSource->GetOutput(i)->GetPosition(); + Label = Label + "Tool" + QString::number(i) + ":[" + QString::number(position[0]) + ":" + QString::number(position[1]) + ":" + QString::number(position[1]) + "] "; + m_ReferenceStartPositions.push_back(position); + } + m_Controls->m_ReferencePosAtStart->setText(Label); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::OnLoadMeasurementStorage() +{ + //read in filename + QString filename = QFileDialog::getOpenFileName(NULL, tr("Open Toolfile"), "/", tr("All Files (*.*)")); + if (filename.isNull()) return; + + m_MeasurementStorage = ReadStorage(filename.toStdString()); + + //update label + Poco::Path myPath = Poco::Path(filename.toStdString()); //use this to seperate filename from path + QString toolLabel = QString("Tool Storage: ") + QString::number(m_MeasurementStorage->GetToolCount()) + " Tools from " + myPath.getFileName().c_str(); + m_Controls->m_MeasurementToolStorageLabel->setText(toolLabel); + + //update status widget + m_Controls->m_ToolStatusWidget->RemoveStatusLabels(); + m_Controls->m_ToolStatusWidget->PreShowTools(m_MeasurementStorage); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::OnLoadReferenceStorage() +{ + //read in filename + static QString oldFile; + if (oldFile.isNull()) oldFile = "/"; + QString filename = QFileDialog::getOpenFileName(NULL, tr("Open Toolfile"), oldFile, tr("All Files (*.*)")); + if (filename.isNull()) return; + oldFile = filename; + + m_ReferenceStorage = ReadStorage(filename.toStdString()); + + //update label + Poco::Path myPath = Poco::Path(filename.toStdString()); //use this to seperate filename from path + QString toolLabel = QString("Tool Storage: ") + QString::number(m_ReferenceStorage->GetToolCount()) + " Tools from " + myPath.getFileName().c_str(); + m_Controls->m_ReferenceToolStorageLabel->setText(toolLabel); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::OnStartTracking() +{ + //check if everything is ready to start tracking + if (m_MeasurementStorage.IsNull()) + { + MessageBox("Error: No measurement tools loaded yet!"); + return; + } + else if (m_ReferenceStorage.IsNull() && m_Controls->m_UseReferenceTrackingSystem->isChecked()) + { + MessageBox("Error: No refernce tools loaded yet!"); + return; + } + else if (m_MeasurementStorage->GetToolCount() == 0) + { + MessageBox("Error: No way to track without tools!"); + return; + } + else if (m_Controls->m_UseReferenceTrackingSystem->isChecked() && (m_ReferenceStorage->GetToolCount() == 0)) + { + MessageBox("Error: No way to track without tools!"); + return; + } + + //build the first IGT pipeline (MEASUREMENT) + mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory1 = mitk::TrackingDeviceSourceConfigurator::New(this->m_MeasurementStorage, this->m_Controls->m_MeasurementTrackingDeviceConfigurationWidget->GetTrackingDevice()); + m_MeasurementTrackingDeviceSource = myTrackingDeviceSourceFactory1->CreateTrackingDeviceSource(this->m_MeasurementToolVisualizationFilter); + if (m_MeasurementTrackingDeviceSource.IsNull()) + { + MessageBox(myTrackingDeviceSourceFactory1->GetErrorMessage()); + return; + } + //connect the tool visualization widget + for (int i = 0; i < m_MeasurementTrackingDeviceSource->GetNumberOfOutputs(); i++) + { + m_Controls->m_ToolStatusWidget->AddNavigationData(m_MeasurementTrackingDeviceSource->GetOutput(i)); + m_EvaluationFilter->SetInput(i, m_MeasurementTrackingDeviceSource->GetOutput(i)); + } + m_Controls->m_ToolStatusWidget->ShowStatusLabels(); + m_Controls->m_ToolStatusWidget->SetShowPositions(true); + m_Controls->m_ToolStatusWidget->SetShowQuaternions(true); + + //build the second IGT pipeline (REFERENCE) + if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) + { + mitk::TrackingDeviceSourceConfigurator::Pointer myTrackingDeviceSourceFactory2 = mitk::TrackingDeviceSourceConfigurator::New(this->m_ReferenceStorage, this->m_Controls->m_ReferenceDeviceConfigurationWidget->GetTrackingDevice()); + m_ReferenceTrackingDeviceSource = myTrackingDeviceSourceFactory2->CreateTrackingDeviceSource(); + if (m_ReferenceTrackingDeviceSource.IsNull()) + { + MessageBox(myTrackingDeviceSourceFactory2->GetErrorMessage()); + return; + } + } + + //initialize tracking + try + { + m_MeasurementTrackingDeviceSource->Connect(); + m_MeasurementTrackingDeviceSource->StartTracking(); + if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) + { + m_ReferenceTrackingDeviceSource->Connect(); + m_ReferenceTrackingDeviceSource->StartTracking(); + } + } + catch (...) + { + MessageBox("Error while starting the tracking device!"); + return; + } + + //set reference + if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) OnSetReference(); + + //start timer + m_Timer->start(1000 / (m_Controls->m_SamplingRate->value())); + + m_Controls->m_StartTracking->setEnabled(false); + m_Controls->m_StartTracking->setEnabled(true); + + m_tracking = true; +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::OnStopTracking() +{ + if (this->m_logging) FinishMeasurement(); + m_MeasurementTrackingDeviceSource->Disconnect(); + m_MeasurementTrackingDeviceSource->StopTracking(); + if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) + { + m_ReferenceTrackingDeviceSource->Disconnect(); + m_ReferenceTrackingDeviceSource->StopTracking(); + } + m_Timer->stop(); + m_Controls->m_StartTracking->setEnabled(true); + m_Controls->m_StartTracking->setEnabled(false); + m_tracking = false; +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::OnMeasurementLoadFile() +{ + m_FilenameVector = std::vector(); + m_FilenameVector.clear(); + m_NextFile = 0; + + //read in filename + QString filename = QFileDialog::getOpenFileName(NULL, tr("Open Measurement Filename List"), "/", tr("All Files (*.*)")); + if (filename.isNull()) return; + + //save old locale + char * oldLocale; + oldLocale = setlocale(LC_ALL, 0); + + //define own locale + std::locale C("C"); + setlocale(LC_ALL, "C"); + + //read file + std::ifstream file; + file.open(filename.toStdString().c_str(), std::ios::in); + if (file.good()) + { + //read out file + file.seekg(0L, std::ios::beg); // move to begin of file + while (!file.eof()) + { + std::string buffer; + std::getline(file, buffer); // read out file line by line + if (buffer.size() > 0) m_FilenameVector.push_back(buffer); + } + } + + //fill list at GUI + m_Controls->m_MeasurementList->clear(); + for (unsigned int i = 0; i < m_FilenameVector.size(); i++) { new QListWidgetItem(tr(m_FilenameVector.at(i).c_str()), m_Controls->m_MeasurementList); } + + //update label next measurement + std::stringstream label; + label << "Next Measurement: " << m_FilenameVector.at(0); + m_Controls->m_NextMeasurement->setText(label.str().c_str()); + + //reset results files + m_MeanPoints = mitk::PointSet::New(); + m_RMSValues = std::vector(); + m_EvaluationFilter = mitk::NavigationDataEvaluationFilter::New(); + if (m_MeasurementToolVisualizationFilter.IsNotNull()) m_EvaluationFilter->SetInput(0, m_MeasurementToolVisualizationFilter->GetOutput(0)); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::UpdateTimer() +{ + if (m_EvaluationFilter.IsNotNull() && m_logging) m_EvaluationFilter->Update(); + else m_MeasurementToolVisualizationFilter->Update(); + + m_Controls->m_ToolStatusWidget->Refresh(); + + //update reference + if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) + { + m_ReferenceTrackingDeviceSource->Update(); + QString Label = "Current Positions: "; + bool distanceThresholdExceeded = false; + for (int i = 0; i < m_ReferenceTrackingDeviceSource->GetNumberOfOutputs(); i++) + { + mitk::Point3D position = m_ReferenceTrackingDeviceSource->GetOutput(i)->GetPosition(); + Label = Label + "Tool" + QString::number(i) + ":[" + QString::number(position[0]) + ":" + QString::number(position[1]) + ":" + QString::number(position[1]) + "] "; + if (position.EuclideanDistanceTo(m_ReferenceStartPositions.at(i)) > m_Controls->m_ReferenceThreshold->value()) distanceThresholdExceeded = true; + } + m_Controls->m_ReferenceCurrentPos->setText(Label); + if (distanceThresholdExceeded) + { + m_Controls->m_ReferenceOK->setText("NOT OK!"); + m_referenceValid = false; + } + else + { + m_Controls->m_ReferenceOK->setText("OK"); + m_referenceValid = true; + } + } + + //update logging + if (m_logging) + { + //check for missing objects + if (m_MeasurementLoggingFilterXML.IsNull() || + m_MeasurementLoggingFilterCSV.IsNull() + ) + { + return; + } + + //log/measure + m_MeasurementLoggingFilterXML->Update(); + m_MeasurementLoggingFilterCSV->Update(); + + if (m_Controls->m_UseReferenceTrackingSystem->isChecked() && + m_ReferenceLoggingFilterXML.IsNotNull() && + m_ReferenceLoggingFilterCSV.IsNotNull()) + { + m_ReferenceLoggingFilterXML->Update(); + m_ReferenceLoggingFilterCSV->Update(); + } + m_loggedFrames++; + LogAdditionalCSVFile(); + + //check if all frames are logged ... if yes finish the measurement + if (m_loggedFrames > m_Controls->m_SamplesPerMeasurement->value()) { FinishMeasurement(); } + + //update logging label + QString loggingLabel = "Collected Samples: " + QString::number(m_loggedFrames); + m_Controls->m_CollectedSamples->setText(loggingLabel); + } +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::StartNextMeasurement() +{ + if (this->m_NextFile >= m_FilenameVector.size()) + { + MessageBox("Last Measurement reached!"); + return; + } + + m_loggedFrames = 0; + m_logging = true; + + //check if directory exists, if not create one + Poco::File myPath(std::string(m_Controls->m_OutputPath->text().toUtf8()).c_str()); + if (!myPath.exists()) myPath.createDirectory(); + + QString LogFileName = m_Controls->m_OutputPath->text() + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".log"; + mitk::LoggingBackend::Unregister(); + mitk::LoggingBackend::SetLogFile(LogFileName.toStdString().c_str()); + mitk::LoggingBackend::Register(); + + //initialize logging filters + m_MeasurementLoggingFilterXML = mitk::NavigationDataRecorderDeprecated::New(); + m_MeasurementLoggingFilterXML->SetRecordingMode(mitk::NavigationDataRecorderDeprecated::NormalFile); + m_MeasurementLoggingFilterCSV = mitk::NavigationDataRecorderDeprecated::New(); + m_MeasurementLoggingFilterCSV->SetRecordingMode(mitk::NavigationDataRecorderDeprecated::NormalFile); + m_MeasurementLoggingFilterXML->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::xml); + m_MeasurementLoggingFilterCSV->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::csv); + QString MeasurementFilenameXML = m_Controls->m_OutputPath->text() + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".xml"; + QString MeasurementFilenameCSV = m_Controls->m_OutputPath->text() + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".csv"; + m_MeasurementLoggingFilterXML->SetFileName(MeasurementFilenameXML.toStdString()); + m_MeasurementLoggingFilterCSV->SetFileName(MeasurementFilenameCSV.toStdString()); + m_MeasurementLoggingFilterXML->SetRecordCountLimit(m_Controls->m_SamplesPerMeasurement->value()); + m_MeasurementLoggingFilterCSV->SetRecordCountLimit(m_Controls->m_SamplesPerMeasurement->value()); + + if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) + { + m_ReferenceLoggingFilterXML = mitk::NavigationDataRecorderDeprecated::New(); + m_ReferenceLoggingFilterXML->SetRecordingMode(mitk::NavigationDataRecorderDeprecated::NormalFile); + m_ReferenceLoggingFilterCSV = mitk::NavigationDataRecorderDeprecated::New(); + m_ReferenceLoggingFilterCSV->SetRecordingMode(mitk::NavigationDataRecorderDeprecated::NormalFile); + m_ReferenceLoggingFilterXML->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::xml); + m_ReferenceLoggingFilterCSV->SetOutputFormat(mitk::NavigationDataRecorderDeprecated::csv); + QString ReferenceFilenameXML = m_Controls->m_OutputPath->text() + "Reference_" + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".xml"; + QString ReferenceFilenameCSV = m_Controls->m_OutputPath->text() + "Reference_" + QString(m_FilenameVector.at(m_NextFile).c_str()) + ".csv"; + m_ReferenceLoggingFilterXML->SetFileName(ReferenceFilenameXML.toStdString()); + m_ReferenceLoggingFilterCSV->SetFileName(ReferenceFilenameCSV.toStdString()); + m_ReferenceLoggingFilterXML->SetRecordCountLimit(m_Controls->m_SamplesPerMeasurement->value()); + m_ReferenceLoggingFilterCSV->SetRecordCountLimit(m_Controls->m_SamplesPerMeasurement->value()); + } + + //start additional csv logging + StartLoggingAdditionalCSVFile(m_FilenameVector.at(m_NextFile)); + + //connect filter + for (int i = 0; i < m_MeasurementToolVisualizationFilter->GetNumberOfOutputs(); i++) + { + m_MeasurementLoggingFilterXML->AddNavigationData(m_MeasurementToolVisualizationFilter->GetOutput(i)); + m_MeasurementLoggingFilterCSV->AddNavigationData(m_MeasurementToolVisualizationFilter->GetOutput(i)); + } + if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) for (int i = 0; i < m_ReferenceTrackingDeviceSource->GetNumberOfOutputs(); i++) + { + m_ReferenceLoggingFilterXML->AddNavigationData(m_ReferenceTrackingDeviceSource->GetOutput(i)); + m_ReferenceLoggingFilterCSV->AddNavigationData(m_ReferenceTrackingDeviceSource->GetOutput(i)); + } + + //start filter + m_MeasurementLoggingFilterXML->StartRecording(); + m_MeasurementLoggingFilterCSV->StartRecording(); + if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) + { + m_ReferenceLoggingFilterXML->StartRecording(); + m_ReferenceLoggingFilterCSV->StartRecording(); + } + + //disable all buttons + DisableAllButtons(); + + //update label next measurement + std::stringstream label; + if ((m_NextFile + 1) >= m_FilenameVector.size()) label << "Next Measurement: "; + else label << "Next Measurement: " << m_FilenameVector.at(m_NextFile + 1); + m_Controls->m_NextMeasurement->setText(label.str().c_str()); + + //update label last measurement + std::stringstream label2; + label2 << "Last Measurement: " << m_FilenameVector.at(m_NextFile); + m_Controls->m_LastMeasurement->setText(label2.str().c_str()); + + m_NextFile++; +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::RepeatLastMeasurement() +{ + m_NextFile--; + StartNextMeasurement(); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::MessageBox(std::string s) +{ + QMessageBox msgBox; + msgBox.setText(s.c_str()); + msgBox.exec(); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::DisableAllButtons() +{ + m_Controls->m_LoadList->setEnabled(false); + m_Controls->m_StartNextMeasurement->setEnabled(false); + m_Controls->m_ReapeatLastMeasurement->setEnabled(false); + m_Controls->m_SamplingRate->setEnabled(false); + m_Controls->m_SamplesPerMeasurement->setEnabled(false); + m_Controls->m_ReferenceThreshold->setEnabled(false); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::EnableAllButtons() +{ + m_Controls->m_LoadList->setEnabled(true); + m_Controls->m_StartNextMeasurement->setEnabled(true); + m_Controls->m_ReapeatLastMeasurement->setEnabled(true); + m_Controls->m_SamplingRate->setEnabled(true); + m_Controls->m_SamplesPerMeasurement->setEnabled(true); + m_Controls->m_ReferenceThreshold->setEnabled(true); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::FinishMeasurement() +{ + m_logging = false; + + m_MeasurementLoggingFilterXML->StopRecording(); + m_MeasurementLoggingFilterCSV->StopRecording(); + if (m_Controls->m_UseReferenceTrackingSystem->isChecked()) + { + m_ReferenceLoggingFilterXML->StopRecording(); + m_ReferenceLoggingFilterCSV->StopRecording(); + } + StopLoggingAdditionalCSVFile(); + + int id = m_NextFile - 1; + mitk::Point3D positionMean = m_EvaluationFilter->GetPositionMean(0); + MITK_INFO << "Evaluated " << m_EvaluationFilter->GetNumberOfAnalysedNavigationData(0) << " samples."; + double rms = m_EvaluationFilter->GetPositionErrorRMS(0); + MITK_INFO << "RMS: " << rms; + MITK_INFO << "Position Mean: " << positionMean; + m_MeanPoints->SetPoint(id, positionMean); + if (m_RMSValues.size() <= id) m_RMSValues.push_back(rms); + else m_RMSValues[id] = rms; + + m_EvaluationFilter->ResetStatistic(); + + EnableAllButtons(); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::StartLoggingAdditionalCSVFile(std::string filePostfix) +{ + //write logfile header + QString header = "Nr;MITK_Time;Valid_Reference;"; + QString tool = QString("MeasureTool_") + QString(m_MeasurementTrackingDeviceSource->GetOutput(0)->GetName()); + header = header + tool + "[x];" + tool + "[y];" + tool + "[z];" + tool + "[qx];" + tool + "[qy];" + tool + "[qz];" + tool + "[qr]\n"; + + //open logfile and write header + m_logFileCSV.open(std::string(m_Controls->m_OutputPath->text().toUtf8()).append("/LogFileCombined").append(filePostfix.c_str()).append(".csv").c_str(), std::ios::out); + m_logFileCSV << header.toStdString().c_str(); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::LogAdditionalCSVFile() +{ + mitk::Point3D pos = m_MeasurementTrackingDeviceSource->GetOutput(0)->GetPosition(); + mitk::Quaternion rot = m_MeasurementTrackingDeviceSource->GetOutput(0)->GetOrientation(); + std::string valid = ""; + if (m_referenceValid) valid = "true"; + else valid = "false"; + std::stringstream timestamp; + timestamp << m_MeasurementTrackingDeviceSource->GetOutput(0)->GetTimeStamp(); + QString dataSet = QString::number(m_loggedFrames) + ";" + QString(timestamp.str().c_str()) + ";" + QString(valid.c_str()) + ";" + QString::number(pos[0]) + ";" + QString::number(pos[1]) + ";" + QString::number(pos[2]) + ";" + QString::number(rot.x()) + ";" + QString::number(rot.y()) + ";" + QString::number(rot.z()) + ";" + QString::number(rot.r()) + "\n"; + m_logFileCSV << dataSet.toStdString(); +} + +void QmitkIGTTrackingSemiAutomaticMeasurementView::StopLoggingAdditionalCSVFile() +{ + m_logFileCSV.close(); +} + +bool QmitkIGTTrackingSemiAutomaticMeasurementView::eventFilter(QObject *obj, QEvent *ev) +{ + if (ev->type() == QEvent::KeyPress) + { + QKeyEvent *k = (QKeyEvent *)ev; + bool up = false; + bool down = false; + if (k->key() == 16777238) up = true; //page up + else if (k->key() == 16777239) down = true; //page down + + if (down && m_tracking && !m_logging) + { + StartNextMeasurement(); + } + } + + return false; +} diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.h b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.h new file mode 100644 index 0000000000..3ec59713ba --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.h @@ -0,0 +1,132 @@ +/*=================================================================== + +The Medical Imaging Interaction Toolkit (MITK) + +Copyright (c) German Cancer Research Center, +Division of Medical and Biological Informatics. +All rights reserved. + +This software is distributed WITHOUT ANY WARRANTY; without +even the implied warranty of MERCHANTABILITY or FITNESS FOR +A PARTICULAR PURPOSE. + +See LICENSE.txt or http://www.mitk.org for details. + +===================================================================*/ + +#ifndef QmitkIGTTrackingSemiAutomaticMeasurementView_h +#define QmitkIGTTrackingSemiAutomaticMeasurementView_h + +#include + +#include + +//QT +#include + +//MITK +#include +#include +#include +#include +#include + +#include "ui_QmitkIGTTrackingSemiAutomaticMeasurementViewControls.h" + +/*! + \brief QmitkIGTTrackingSemiAutomaticMeasurementView + + \warning This application module is not yet documented. Use "svn blame/praise/annotate" and ask the author to provide basic documentation. + + \sa QmitkFunctionality + \ingroup Functionalities + */ +class QmitkIGTTrackingSemiAutomaticMeasurementView : 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; + + QmitkIGTTrackingSemiAutomaticMeasurementView(); + virtual ~QmitkIGTTrackingSemiAutomaticMeasurementView(); + + virtual void CreateQtPartControl(QWidget *parent); + + virtual void StdMultiWidgetAvailable(QmitkStdMultiWidget &stdMultiWidget); + virtual void StdMultiWidgetNotAvailable(); + + protected slots: + + void OnLoadMeasurementStorage(); + void OnLoadReferenceStorage(); + void OnStartTracking(); + void OnStopTracking(); + void OnMeasurementLoadFile(); + void OnSetReference(); + void StartNextMeasurement(); + void RepeatLastMeasurement(); + void UpdateTimer(); + void CreateResults(); + void OnUseReferenceToggled(bool state); + +protected: + + Ui::QmitkIGTTrackingSemiAutomaticMeasurementViewControls* m_Controls; + + QmitkStdMultiWidget* m_MultiWidget; + + //the tool storages + mitk::NavigationToolStorage::Pointer m_MeasurementStorage; + mitk::NavigationToolStorage::Pointer m_ReferenceStorage; + + //members for the filter pipeline + mitk::TrackingDeviceSource::Pointer m_MeasurementTrackingDeviceSource; + mitk::NavigationDataObjectVisualizationFilter::Pointer m_MeasurementToolVisualizationFilter; + mitk::NavigationDataRecorderDeprecated::Pointer m_MeasurementLoggingFilterXML; + mitk::NavigationDataRecorderDeprecated::Pointer m_MeasurementLoggingFilterCSV; + mitk::TrackingDeviceSource::Pointer m_ReferenceTrackingDeviceSource; + mitk::NavigationDataRecorderDeprecated::Pointer m_ReferenceLoggingFilterXML; + mitk::NavigationDataRecorderDeprecated::Pointer m_ReferenceLoggingFilterCSV; + + //members for file name list + std::vector m_FilenameVector; + int m_NextFile; + + //help methods + mitk::NavigationToolStorage::Pointer ReadStorage(std::string file); + void MessageBox(std::string s); + void DisableAllButtons(); + void EnableAllButtons(); + void FinishMeasurement(); + void StartLoggingAdditionalCSVFile(std::string filePostfix); + void LogAdditionalCSVFile(); + void StopLoggingAdditionalCSVFile(); + + //timer + QTimer* m_Timer; + + //memebers for reference checking + std::vector m_ReferenceStartPositions; + bool m_referenceValid; + + //logging members + int m_loggedFrames; + bool m_logging; + std::fstream m_logFileCSV; + + //event filter for key presses + bool eventFilter(QObject *obj, QEvent *ev); + + //results members + mitk::PointSet::Pointer m_MeanPoints; + std::vector m_RMSValues; + mitk::NavigationDataEvaluationFilter::Pointer m_EvaluationFilter; + + bool m_tracking; +}; + +#endif // _QMITKIGTTRACKINGSEMIAUTOMATICMEASUREMENTVIEW_H_INCLUDED diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementViewControls.ui b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementViewControls.ui new file mode 100644 index 0000000000..50168cb767 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementViewControls.ui @@ -0,0 +1,555 @@ + + + QmitkIGTTrackingSemiAutomaticMeasurementViewControls + + + + 0 + 0 + 419 + 931 + + + + + 0 + 0 + + + + QmitkTemplate + + + + + + 0 + + + + Tracking Initialization + + + + + + Measurement Tracking System + + + + + + + + + + + Tool Storage: <none> + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Load Tool Storage + + + + + + + + + + + + Reference Trackingsystem + + + + + + + + + + + Tool Storage: <none> + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Load Tool Storage + + + + + + + + + + + + Start Tracking + + + + + + + Stop Tracking + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + Measurement + + + + + + Measurement List: + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Load List + + + + + + + + + + + Output Path: + + + + + + + C:/temp/ + + + + + + + + + Last Measurement: <none> + + + + + + + Next Measurement: <none> + + + + + + + Collected Samples: <none> + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 200 + 0 + + + + Start Next Measurement + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 200 + 0 + + + + Repeat Last Measurement + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 200 + 0 + + + + Create Results + + + + + + + + + Qt::Vertical + + + + 20 + 281 + + + + + + + + Qt::Horizontal + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; text-decoration: underline;">Measurement Sensors:</span></p></body></html> + + + + + + + + + + Qt::Horizontal + + + + + + + <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> +<html><head><meta name="qrichtext" content="1" /><style type="text/css"> +p, li { white-space: pre-wrap; } +</style></head><body style=" font-family:'MS Shell Dlg 2'; font-size:8.25pt; font-weight:400; font-style:normal;"> +<p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-size:8pt; font-weight:600; text-decoration: underline;">Reference Sensors:</span></p></body></html> + + + + + + + Set Reference + + + + + + + Reference Postion: <none> + + + + + + + Current Positions: <none> + + + + + + + <!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:28pt; font-weight:600;">OK</span></p></body></html> + + + Qt::AlignCenter + + + + + + + + Settings + + + + + + + + Sampling Rate (Times Per Second): + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 999.000000000000000 + + + 15.000000000000000 + + + + + + + + + + + Samples Per Measurement: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1000 + + + 150 + + + + + + + + + + + Threshold For Reference Tools: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + 1.000000000000000 + + + + + + + + + Use Reference Tracking System + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + + QmitkToolTrackingStatusWidget + QWidget +