diff --git a/Plugins/PluginList.cmake b/Plugins/PluginList.cmake index c1e21f2ab0..6a1b81d629 100644 --- a/Plugins/PluginList.cmake +++ b/Plugins/PluginList.cmake @@ -1,73 +1,73 @@ # Plug-ins must be ordered according to their dependencies set(MITK_PLUGINS org.blueberry.core.runtime:ON org.blueberry.core.expressions:OFF org.blueberry.core.commands:OFF org.blueberry.core.jobs:OFF org.blueberry.ui.qt:OFF org.blueberry.ui.qt.help:OFF org.blueberry.ui.qt.log:ON org.blueberry.ui.qt.objectinspector:OFF #org.blueberry.test:ON #org.blueberry.uitest:ON #Testing/org.blueberry.core.runtime.tests:ON #Testing/org.blueberry.osgi.tests:ON org.mitk.core.services:ON org.mitk.gui.common:ON org.mitk.planarfigure:ON org.mitk.core.ext:OFF org.mitk.core.jobs:OFF org.mitk.diffusionimaging:OFF org.mitk.simulation:OFF org.mitk.gui.qt.application:ON org.mitk.gui.qt.coreapplication:OFF org.mitk.gui.qt.ext:OFF org.mitk.gui.qt.extapplication:OFF org.mitk.gui.qt.common:ON org.mitk.gui.qt.stdmultiwidgeteditor:ON org.mitk.gui.qt.common.legacy:OFF org.mitk.gui.qt.cmdlinemodules:OFF org.mitk.gui.qt.diffusionimagingapp:OFF org.mitk.gui.qt.datamanager:ON org.mitk.gui.qt.datamanagerlight:OFF org.mitk.gui.qt.properties:ON org.mitk.gui.qt.basicimageprocessing:OFF org.mitk.gui.qt.dicom:OFF org.mitk.gui.qt.diffusionimaging:OFF org.mitk.gui.qt.dosevisualization:OFF org.mitk.gui.qt.geometrytools:OFF org.mitk.gui.qt.igtexamples:OFF org.mitk.gui.qt.igttracking:OFF org.mitk.gui.qt.igtlplugin:OFF org.mitk.gui.qt.imagecropper:OFF org.mitk.gui.qt.imagenavigator:ON org.mitk.gui.qt.viewnavigator:OFF org.mitk.gui.qt.materialeditor:OFF org.mitk.gui.qt.measurementtoolbox:OFF org.mitk.gui.qt.moviemaker:OFF org.mitk.gui.qt.pointsetinteraction:OFF org.mitk.gui.qt.pointsetinteractionmultispectrum:OFF org.mitk.gui.qt.python:OFF org.mitk.gui.qt.registration:OFF org.mitk.gui.qt.remeshing:OFF org.mitk.gui.qt.segmentation:OFF org.mitk.gui.qt.simulation:OFF org.mitk.gui.qt.aicpregistration:OFF org.mitk.gui.qt.toftutorial:OFF org.mitk.gui.qt.tofutil:OFF org.mitk.gui.qt.tubegraph:OFF org.mitk.gui.qt.ugvisualization:OFF org.mitk.gui.qt.ultrasound:OFF org.mitk.gui.qt.volumevisualization:OFF org.mitk.gui.qt.eventrecorder:OFF org.mitk.gui.qt.xnat:OFF org.mitk.gui.qt.spectrocamrecorder:OFF org.mitk.gui.qt.classificationsegmentation:OFF - org.mitk.gui.qt.igttrackingsemiautomaticmeasurement:OFF + org.mitk.gui.qt.igt.app.hummelprotocolmeasurements:OFF ) diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/CMakeLists.txt b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/CMakeLists.txt new file mode 100644 index 0000000000..31e4af6511 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/CMakeLists.txt @@ -0,0 +1,7 @@ +project(org_mitk_gui_qt_igtapphummelprotocolmeasurements) + +mitk_create_plugin( + EXPORT_DIRECTIVE IGTTRACKINGSEMIAUTOMATICMEASUREMENT_EXPORT + EXPORTED_INCLUDE_SUFFIXES src + MODULE_DEPENDS MitkIGT MitkIGTUI MitkCameraCalibration +) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/Manual.dox b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/Manual.dox new file mode 100644 index 0000000000..bd69086489 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/Manual.dox @@ -0,0 +1,24 @@ +/** +\bundlemainpage{org.mitk.gui.qt.igttrackingsemiautomaticmeasurement} IGT Tracking Semi Automatic Measurement + +\imageMacro{icon.png,"Icon of IGT Tracking Semi Automatic Measurement",2.00} + +Available sections: + - \ref org.mitk.gui.qt.igttrackingsemiautomaticmeasurementOverview + +\section org.mitk.gui.qt.igttrackingsemiautomaticmeasurementOverview +Dieses PlugIn dient zur semiautomatischen Aufzeichnung von Messreihen mit Trackingsystemen. Entsprechend konfiguriert ist es auch für das +Hummel-Protokoll einsetzbar. Zentrale Komponente des PlugIns ist eine IGT Pipeline zur Messdatenaufzeichnung, wie in Abbildung 1 dargestellt. + +\imageMacro{pipeline.png,"Icon of IGT Tracking Semi Automatic Measurement",10.00} + +Ein Screenshot der Benutzeroberfläche des PlugIns ist in Abbildung 2 zu sehen. Das Initialisieren und Starten des Trackingsystems erfolgt dabei im nicht dargestellten Tab "Tracking Initialization", der im Wesentlichen aus dem TrackingDeviceConfigurationWidget besteht. Zur Durchführung der Messungen unterstützt das PlugIn das Laden einer Liste mit Dateinamen für die Messungen, wie im oberen Teil des Screenshots zu sehen. Diese Liste wird abgearbeitet, wobei mit dem Button "Start Next Measurement" jeweils die nächste Messung gestartet wird. Die während der Messung aufgezeichneten Daten werden in eine Datei das Ausgabeverzeichnis +geschrieben. Dabei entspricht der Dateiname dem aktuellen Namen aus der Liste. Die Anzahl der aufzuzeichnenden Messwerte pro Messung kann in den +Einstellungen angegeben werden. Gab es bei einer Messung einen Fehler kann die Messung durch Auswahl des entsprechenden Buttons auch wiederholt werden. + +\imageMacro{screenshot.png,"Icon of IGT Tracking Semi Automatic Measurement",10.00} + +Das PlugIn unterstützt außerdem die Ansteuerung eines zweiten Trackingsystems. Dieses System soll einen am Phantom angebrachtes Tool (Reference Sensor) tracken und so sicherstellen, dass sich das Phantom +während der Messung nicht bewegt. Wurde eine Bewegung des Phantoms festgestellt wird im unteren Teil des PlugIns "NOT OK" angezeigt und die Messung muss ggf. wiederholt werden. +*/ + diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/icon.png b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/icon.png new file mode 100644 index 0000000000..05bc3385c4 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/icon.png differ diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/pipeline.png b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/pipeline.png new file mode 100644 index 0000000000..c241b19f0c Binary files /dev/null and b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/pipeline.png differ diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/screenshot.png b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/screenshot.png new file mode 100644 index 0000000000..9aa1ad96e3 Binary files /dev/null and b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/Manual/screenshot.png differ diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/doxygen/modules.dox b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/doxygen/modules.dox new file mode 100644 index 0000000000..8b13789179 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/documentation/doxygen/modules.dox @@ -0,0 +1 @@ + diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/files.cmake b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/files.cmake new file mode 100644 index 0000000000..6b1d22112c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/files.cmake @@ -0,0 +1,42 @@ +SET(SRC_CPP_FILES + +) + +SET(INTERNAL_CPP_FILES + QmitkIGTTrackingSemiAutomaticMeasurementView.cpp + QmitkIGTTrackingDataEvaluationView.cpp + mitkPluginActivator.cpp + mitkNavigationDataCSVSequentialPlayer.cpp + +) + +SET(UI_FILES + src/internal/QmitkIGTTrackingSemiAutomaticMeasurementViewControls.ui + src/internal/QmitkIGTTrackingDataEvaluationViewControls.ui +) + +SET(MOC_H_FILES + src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.h + src/internal/QmitkIGTTrackingDataEvaluationView.h + src/internal/mitkPluginActivator.h +) + +SET(CACHED_RESOURCE_FILES + resources/icon.xpm + resources/icon-eval.xpm + plugin.xml +) + +SET(QRC_FILES + resources/QmitkIGTTrackingSemiAutomaticMeasurementView.qrc +) + +SET(CPP_FILES) + +foreach(file ${SRC_CPP_FILES}) + SET(CPP_FILES ${CPP_FILES} src/${file}) +endforeach(file ${SRC_CPP_FILES}) + +foreach(file ${INTERNAL_CPP_FILES}) + SET(CPP_FILES ${CPP_FILES} src/internal/${file}) +endforeach(file ${INTERNAL_CPP_FILES}) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/manifest_headers.cmake b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/manifest_headers.cmake new file mode 100644 index 0000000000..d460e62c3f --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/manifest_headers.cmake @@ -0,0 +1,5 @@ +set(Plugin-Name "IGT APP: Hummel Protocol Measurements") +set(Plugin-Version "0.1") +set(Plugin-Vendor "DKFZ, Medical and Biological Informatics") +set(Plugin-ContactAddress "http://www.mitk.org") +set(Require-Plugin org.mitk.gui.qt.common.legacy) \ No newline at end of file diff --git a/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/plugin.xml b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/plugin.xml new file mode 100644 index 0000000000..5f7d7e2ab2 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/plugin.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + \ No newline at end of file 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..66f36f2fda --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkNavigationDataCSVSequentialPlayer.cpp @@ -0,0 +1,214 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-02-10 18:08:54 +0100 (Di, 10 Feb 2009) $ +Version: $Revision: 16228 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkNavigationDataCSVSequentialPlayer.h" +#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 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(1).toDouble(); + + 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(); + } + 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(1).toDouble(); + + //if (myLineList.at(2).toStdString() == "true") + //valid-flag wurde hier nicht gespeichert + 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); //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..50bb773d18 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkNavigationDataCSVSequentialPlayer.h @@ -0,0 +1,98 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date: 2009-02-10 18:08:54 +0100 (Di, 10 Feb 2009) $ +Version: $Revision: 16228 $ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#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_ */ \ No newline at end of file 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..b1ca328364 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkPluginActivator.cpp @@ -0,0 +1,38 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#include "mitkPluginActivator.h" + +#include + +#include "QmitkIGTTrackingSemiAutomaticMeasurementView.h" + +namespace mitk { + void PluginActivator::start(ctkPluginContext* context) + { + BERRY_REGISTER_EXTENSION_CLASS(QmitkIGTTrackingSemiAutomaticMeasurementView, 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 \ No newline at end of file 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..ecf559f1d4 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/mitkPluginActivator.h @@ -0,0 +1,44 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + + +#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 + +// 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; iSetFiletype(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; jGetNumberOfOutputs(); j++) {myEvaluationFilter->SetInput(j,myPlayer->GetOutput(j));} + + + //update pipline until number of samlples is reached + for (int j=0; jm_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; iSetFiletype(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 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" ); + */ //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; im_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; iSetFiletype(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; jGetNumberOfOutputs(); j++) {myEvaluationFilter->SetInput(j,myPlayer->GetOutput(j));} + + + + //update pipline until number of samlples is reached + for (int j=0; jm_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; iSetFiletype(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; jm_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; iSetFiletype(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; jGetNumberOfOutputs(); j++) {myEvaluationFilter->SetInput(j,myPlayer->GetOutput(j));} + + //update pipline until number of samlples is reached + for (int j=0; jm_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; iSetFiletype(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; jGetNumberOfOutputs(); j++) {myEvaluationFilter->SetInput(j,myPlayer->GetOutput(j));} + + //update pipline until number of samlples is reached + for (int j=0; jm_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; im_PointNumber1->value(); i++) + { + for (int j=0; jm_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; iGraft(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; iSetFiletype(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; jGetNumberOfOutputs(); j++) {myEvaluationFilter->SetInput(j,myPlayer->GetOutput(j));} + //update pipline until number of samlples is reached + for (int j=0; jm_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; im_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 / PI) * 180; + m_CurrentAngleDifferencesWriteFile << "Angle between " << pos1 << " and " << pos2 << ";" << idx1 << ";" << idx2 << ";" << angle << ";" << angle_degree << "\n"; + } + +double QmitkIGTTrackingDataEvaluationView::GetAngleBetweenTwoQuaterions(mitk::Quaternion a, mitk::Quaternion b) + { + double 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 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; iGetNumberOfAnalysedNavigationData(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..a928c578b3 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingDataEvaluationView.h @@ -0,0 +1,125 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#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..9095e6a5af --- /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:/Experimente/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..9a0c25196c --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.cpp @@ -0,0 +1,667 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +// 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..85fe08d498 --- /dev/null +++ b/Plugins/org.mitk.gui.qt.igt.app.hummelprotocolmeasurements/src/internal/QmitkIGTTrackingSemiAutomaticMeasurementView.h @@ -0,0 +1,133 @@ +/*========================================================================= + +Program: Medical Imaging & Interaction Toolkit +Language: C++ +Date: $Date$ +Version: $Revision$ + +Copyright (c) German Cancer Research Center, Division of Medical and +Biological Informatics. All rights reserved. +See MITKCopyright.txt or http://www.mitk.org/copyright.html for details. + +This software is distributed WITHOUT ANY WARRANTY; without even +the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +PURPOSE. See the above copyright notices for more information. + +=========================================================================*/ + +#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 +