init
This commit is contained in:
+39
@@ -0,0 +1,39 @@
|
||||
PROJECT(openvibe-plugins-evaluation)
|
||||
|
||||
SET(PROJECT_VERSION_MAJOR ${OV_GLOBAL_VERSION_MAJOR})
|
||||
SET(PROJECT_VERSION ${OV_GLOBAL_VERSION_STRING})
|
||||
|
||||
FILE(GLOB_RECURSE SRC_FILES src/*.cpp src/*.h src/*.inl)
|
||||
ADD_LIBRARY(${PROJECT_NAME} SHARED ${SRC_FILES})
|
||||
SET_TARGET_PROPERTIES(${PROJECT_NAME} PROPERTIES
|
||||
VERSION ${PROJECT_VERSION}
|
||||
SOVERSION ${PROJECT_VERSION_MAJOR}
|
||||
FOLDER ${PLUGINS_FOLDER}
|
||||
COMPILE_FLAGS "-DOVP_Exports -DOVP_Shared")
|
||||
|
||||
# ---------------------------------
|
||||
INCLUDE("FindOpenViBE")
|
||||
INCLUDE("FindOpenViBECommon")
|
||||
INCLUDE("FindOpenViBEToolkit")
|
||||
INCLUDE("FindOpenViBEModuleEBML")
|
||||
INCLUDE("FindOpenViBEModuleXML")
|
||||
INCLUDE("FindThirdPartyGTK")
|
||||
INCLUDE("FindOpenViBEVisualizationToolkit")
|
||||
|
||||
# ---------------------------------
|
||||
# Test applications
|
||||
# ---------------------------------
|
||||
IF(OV_COMPILE_TESTS)
|
||||
ADD_SUBDIRECTORY(test)
|
||||
ENDIF(OV_COMPILE_TESTS)
|
||||
|
||||
# -----------------------------
|
||||
# Install files
|
||||
# -----------------------------
|
||||
INSTALL(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
|
||||
INSTALL(DIRECTORY share/ DESTINATION ${DIST_DATADIR}/openvibe/plugins/evaluation)
|
||||
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_ClassifierAccuracyMeasure Classifier accuracy measure
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ClassifierAccuracyMeasure_Description|
|
||||
The real-time classifier accuracies are displayed on vertical progress bars. The accuracy is computed given the results from classifiers, compared to the targets received.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ClassifierAccuracyMeasure_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ClassifierAccuracyMeasure_Inputs|
|
||||
This box must have at least 2 inputs: one for the targets, and another one for a classifier processor results. User can add more classifier inputs at will.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ClassifierAccuracyMeasure_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ClassifierAccuracyMeasure_Input1|
|
||||
The targets the classifier aims at, using stimulation labels.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ClassifierAccuracyMeasure_Input1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ClassifierAccuracyMeasure_Input2|
|
||||
The classifier results coming from a classifier processor, using stimulation labels.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ClassifierAccuracyMeasure_Input2|
|
||||
__________________________________________________________________
|
||||
|
||||
Online visualization settings
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ClassifierAccuracyMeasure_OnlineVisualizationSettings|
|
||||
Online settings :
|
||||
|
||||
Setting1 : Reset scores
|
||||
|
||||
Setting2 : Show accuracies as percentages
|
||||
|
||||
* |OVP_DocEnd_BoxAlgorithm_ClassifierAccuracyMeasure_OnlineVisualizationSettings|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ClassifierAccuracyMeasure_Examples|
|
||||
* |OVP_DocEnd_BoxAlgorithm_ClassifierAccuracyMeasure_Examples|
|
||||
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ClassifierAccuracyMeasure_Miscellaneous|
|
||||
* |OVP_DocEnd_BoxAlgorithm_ClassifierAccuracyMeasure_Miscellaneous|
|
||||
*/
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_ConfusionMatrix Confusion Matrix
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Description|
|
||||
The Confusion Matrix box performs real-time computation of the confusion matrix of a given classifier.
|
||||
Confusion matrix can be used to measure the performance of a classifier.
|
||||
The confusion matrix output can be filled with either percentages or values. Optional colum and row can be added to
|
||||
give the sums of each row and column.
|
||||
The confusion matrix output can be displayed usig a \ref BoxAlgorithm_MatrixDisplay.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Input1|
|
||||
The stimulations that comes from the instruction flow, i.e. the targets that the classifier aims at.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Input1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Input2|
|
||||
The classification results coming from a classifier. These stimulations will be compared to teh target to perform the computation.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Input2|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Outputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Output1|
|
||||
The Confusion matrix.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Settings|
|
||||
More box settings can be added for a multi class classifier. The default configuration uses 2 classes.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Setting1|
|
||||
Tells the box to put percentages or values in the matrix.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Setting2|
|
||||
If checked, this option adds one row and one column that gives the sums of each row and column in the matrix.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Setting2|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Setting3|
|
||||
The stimulation label for the first class.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Setting3|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Setting4|
|
||||
The stimulation label for the second class.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Setting4|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Examples|
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ConfusionMatrix_Miscellaneous|
|
||||
* |OVP_DocEnd_BoxAlgorithm_ConfusionMatrix_Miscellaneous|
|
||||
*/
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_KappaCoef Kappa Coefficient
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Description|
|
||||
* This box computes the Cohen kappa coefficient that allows to compare the accordance of two classifiers (https://en.wikipedia.org/wiki/Cohen%27s_kappa),
|
||||
* The box compares the results of the classifier (second input) to the 100% match classifier (first input).
|
||||
*
|
||||
* The result is streamed on the first output, and is displayed in real time in a standalone visualization.
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Description|
|
||||
*
|
||||
*
|
||||
_______________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Input1|
|
||||
* The first input receives the expected stimulation.
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Input1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Input2|
|
||||
* This input receives the stimualtions found by the classifier.
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Input2|
|
||||
__________________________________________________________________
|
||||
|
||||
Outputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Outputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Outputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Output1|
|
||||
* This output contains the current value of the Kappa coefficient.
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Output1|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Settings|
|
||||
* Each setting except the first one corresponds to the stimulation code of a class. A stimulation must be unique.
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Setting1|
|
||||
* This setting indicates the amount of classes handled by the box. This setting will change the amount of setting.
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Setting2|
|
||||
* This setting indicates the stimulation corresponding to the first class.
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Setting2|
|
||||
*
|
||||
* * |OVP_DocBegin_BoxAlgorithm_KappaCoef_Setting3|
|
||||
* This setting indicates the stimulation corresponding to the second class.
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Setting3|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Miscellaneous|
|
||||
* All stimulations can be send to the box. They will be filtered.
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Miscellaneous|
|
||||
*/
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_ROCCurve ROC Curve
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ROCCurve_Description|
|
||||
* This box computes the ROC (Receiver Operating Characteristic) curve for a classifier (https://fr.wikipedia.org/wiki/Receiver_Operating_Characteristic). One curve will be computes
|
||||
* by class. This box is designed to work with the probability output of the \ref Doc_BoxAlgorithm_ClassifierProcessor.
|
||||
*
|
||||
* The box will compute the curve when it receives the computation trigger on the first input.
|
||||
*
|
||||
* The result is displayed when computed in a standalone visualization.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Description|
|
||||
*
|
||||
*
|
||||
_______________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ROCCurve_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ROCCurve_Input1|
|
||||
The first input receives the expected stimulations stream.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Input1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ROCCurve_Input2|
|
||||
This input receives the probability output stream of the processor box.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Input2|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ROCCurve_Settings|
|
||||
* Each setting after the second one corresponds to the stimulation code of a class. A stimulation must be unique.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ROCCurve_Setting1|
|
||||
* Stimulation trigger for the computation.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Setting1|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ROCCurve_Setting2|
|
||||
* This setting indicates the amount of classes handled by the box. This setting will change the amount of setting.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Setting2|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ROCCurve_Setting3|
|
||||
* This setting indicates the stimulation corresponding to the first class.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Setting3|
|
||||
*
|
||||
* * |OVP_DocBegin_BoxAlgorithm_ROCCurve_Setting4|
|
||||
* This setting indicates the stimulation corresponding to the second class.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Setting4|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_ROCCurve_Miscellaneous|
|
||||
* All stimulations can be send to the box. They will be filtered.
|
||||
* |OVP_DocEnd_BoxAlgorithm_ROCCurve_Miscellaneous|
|
||||
*/
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
* \page BoxAlgorithm_GeneralStatisticsGenerator General Statistic Generator
|
||||
__________________________________________________________________
|
||||
|
||||
Detailed description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_GeneralStatisticsGenerator_Description|
|
||||
* The box analyses a the two input stream (stimulations and signal).
|
||||
*
|
||||
* The box will provide for each channel of the signal the min, the max value and the mean.
|
||||
* The box will provide a list of stimulations and provide for them the amount of time they appeared.
|
||||
*
|
||||
* |OVP_DocEnd_BoxAlgorithm_GeneralStatisticsGenerator_Description|
|
||||
__________________________________________________________________
|
||||
|
||||
Inputs description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_GeneralStatisticsGenerator_Inputs|
|
||||
* |OVP_DocEnd_BoxAlgorithm_GeneralStatisticsGenerator_Inputs|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_GeneralStatisticsGenerator_Input1|
|
||||
* The signal stream to analyse.
|
||||
* |OVP_DocEnd_BoxAlgorithm_GeneralStatisticsGenerator_Input1|
|
||||
*
|
||||
* |OVP_DocBegin_BoxAlgorithm_GeneralStatisticsGenerator_Input2|
|
||||
* The stimulation stream to analyse.
|
||||
* |OVP_DocEnd_BoxAlgorithm_GeneralStatisticsGenerator_Input2|
|
||||
__________________________________________________________________
|
||||
|
||||
Settings description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_GeneralStatisticsGenerator_Settings|
|
||||
* |OVP_DocEnd_BoxAlgorithm_GeneralStatisticsGenerator_Settings|
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_GeneralStatisticsGenerator_Setting1|
|
||||
* Path to the file where the results will be wrote.
|
||||
* |OVP_DocEnd_BoxAlgorithm_GeneralStatisticsGenerator_Setting1|
|
||||
__________________________________________________________________
|
||||
|
||||
Examples description
|
||||
__________________________________________________________________
|
||||
|
||||
* |OVP_DocBegin_BoxAlgorithm_GeneralStatisticsGenerator_Examples|
|
||||
* The resulting file should look like this :
|
||||
\verbatim
|
||||
<Statistic>
|
||||
<Stimulations-list>
|
||||
<Stimulation>
|
||||
<Identifier>(0x00000000, 0x00008100)</Identifier>
|
||||
<Label>OVTK_StimulationId_Label_00</Label>
|
||||
<Count>500</Count>
|
||||
</Stimulation>
|
||||
</Stimulations-list>
|
||||
<Channel-list>
|
||||
<Channel>
|
||||
<Name>sinusOsc 1</Name>
|
||||
<Maximum>2.99595</Maximum>
|
||||
<Minimum>-2.99582</Minimum>
|
||||
<Mean>0.00374409</Mean>
|
||||
</Channel>
|
||||
<Channel>
|
||||
<Name>sinusOsc 2</Name>
|
||||
<Maximum>2.99555</Maximum>
|
||||
<Minimum>-2.99594</Minimum>
|
||||
<Mean>0.00215169</Mean>
|
||||
</Channel>
|
||||
<Channel>
|
||||
<Name>sinusOsc 3</Name>
|
||||
<Maximum>2.99594</Maximum>
|
||||
<Minimum>-2.99592</Minimum>
|
||||
<Mean>0.000474523</Mean>
|
||||
</Channel>
|
||||
<Channel>
|
||||
<Name>sinusOsc 4</Name>
|
||||
<Maximum>2.99591</Maximum>
|
||||
<Minimum>-2.99594</Minimum>
|
||||
<Mean>0.00127219</Mean>
|
||||
</Channel>
|
||||
</Channel-list>
|
||||
</Statistic>
|
||||
\endverbatim
|
||||
* |OVP_DocEnd_BoxAlgorithm_GeneralStatisticsGenerator_Examples|
|
||||
__________________________________________________________________
|
||||
|
||||
Miscellaneous description
|
||||
__________________________________________________________________
|
||||
* |OVP_DocBegin_BoxAlgorithm_KappaCoef_Miscellaneous|
|
||||
* |OVP_DocEnd_BoxAlgorithm_KappaCoef_Miscellaneous|
|
||||
*
|
||||
*/
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
<?xml version="1.0"?>
|
||||
<interface>
|
||||
<!-- interface-requires gtk+ 2.6 -->
|
||||
<!-- interface-naming-policy toplevel-contextual -->
|
||||
<object class="GtkWindow" id="classifier-accuracy-measure">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<child>
|
||||
<object class="GtkTable" id="classifier-accuracy-measure-table">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="border_width">8</property>
|
||||
<property name="column_spacing">8</property>
|
||||
<property name="row_spacing">8</property>
|
||||
<property name="homogeneous">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="classifier-accuracy-measure-toolbar">
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="title" translatable="yes">Classifier Accuracy Measure</property>
|
||||
<property name="type_hint">dialog</property>
|
||||
<child>
|
||||
<object class="GtkToolbar" id="classifier-accuracy-measure-settings">
|
||||
<property name="visible">True</property>
|
||||
<property name="show_arrow">False</property>
|
||||
<child>
|
||||
<object class="GtkToolButton" id="reset-score-button">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">reset</property>
|
||||
<property name="stock_id">gtk-refresh</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkSeparatorToolItem" id="separator">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="show-percentages-toggle-button">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">percentages</property>
|
||||
<property name="stock_id">gtk-justify-center</property>
|
||||
<property name="active">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkToggleToolButton" id="show-scores-toggle-button">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="label" translatable="yes">scores</property>
|
||||
<property name="stock_id">gtk-justify-center</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="homogeneous">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<object class="GtkWindow" id="dummy-window">
|
||||
<child>
|
||||
<object class="GtkVPaned" id="vertical-pannel">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<child>
|
||||
<object class="GtkProgressBar" id="progress-bar-classifier-accuracy">
|
||||
<property name="visible">True</property>
|
||||
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
|
||||
<property name="show_text">True</property>
|
||||
<property name="text_xalign">0</property>
|
||||
<property name="text_yalign">0</property>
|
||||
<property name="fraction">0.20000000298023224</property>
|
||||
<property name="orientation">bottom-to-top</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">False</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-classifier-name">
|
||||
<property name="visible">True</property>
|
||||
<property name="label" translatable="yes">Classifier</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="resize">True</property>
|
||||
<property name="shrink">True</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</interface>
|
||||
+218
@@ -0,0 +1,218 @@
|
||||
#include "ovpCAlgorithmConfusionMatrix.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
|
||||
#ifdef DEBUG
|
||||
static void dumpMatrix(Kernel::ILogManager& mng, const CMatrix& mat, const CString& desc)
|
||||
{
|
||||
mng << Kernel::LogLevel_Info << desc << "\n";
|
||||
for (size_t i = 0; i < mat.getDimensionSize(0); i++)
|
||||
{
|
||||
mng << Kernel::LogLevel_Info << "Row " << i << ": ";
|
||||
for (size_t j = 0; j < mat.getDimensionSize(1); j++) { mng << mat.getBuffer()[i * mat.getDimensionSize(1) + j] << " "; }
|
||||
mng << "\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool CAlgorithmConfusionMatrix::initialize()
|
||||
{
|
||||
ip_targetStimSet.initialize(getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_TargetStimulationSet));
|
||||
ip_classifierStimSet.initialize(getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassifierStimulationSet));
|
||||
ip_classesCodes.initialize(getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassCodes));
|
||||
ip_usePercentages.initialize(getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Percentage));
|
||||
ip_useSums.initialize(getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Sums));
|
||||
op_confusionMatrix.initialize(getOutputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_OutputParameterId_ConfusionMatrix));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAlgorithmConfusionMatrix::uninitialize()
|
||||
{
|
||||
#ifdef DEBUG
|
||||
dumpMatrix(this->getLogManager(), m_confusionMatrix, "Confusion matrix");
|
||||
#endif
|
||||
|
||||
ip_targetStimSet.uninitialize();
|
||||
ip_classifierStimSet.uninitialize();
|
||||
ip_classesCodes.uninitialize();
|
||||
ip_usePercentages.uninitialize();
|
||||
ip_useSums.uninitialize();
|
||||
op_confusionMatrix.uninitialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAlgorithmConfusionMatrix::process()
|
||||
{
|
||||
const size_t nClass = size_t(ip_classesCodes->getStimulationCount());
|
||||
|
||||
if (this->isInputTriggerActive(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetTarget))
|
||||
{
|
||||
for (size_t i = 0; i < ip_classesCodes->getStimulationCount(); ++i)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "class code " << i << ": " << ip_classesCodes->getStimulationIdentifier(i) << "\n";
|
||||
}
|
||||
|
||||
m_nClassificationAttemptPerClass.clear();
|
||||
for (size_t i = 0; i < ip_classesCodes->getStimulationCount(); ++i)
|
||||
{
|
||||
m_nClassificationAttemptPerClass.insert(std::make_pair(ip_classesCodes->getStimulationIdentifier(i), 0));
|
||||
}
|
||||
|
||||
if (ip_useSums) { op_confusionMatrix->resize(nClass + 1, nClass + 1); }
|
||||
else { op_confusionMatrix->resize(nClass, nClass); }
|
||||
|
||||
for (size_t i = 0; i < nClass; ++i)
|
||||
{
|
||||
const char* name = this->getTypeManager().getEnumerationEntryNameFromValue(OV_TypeId_Stimulation,
|
||||
ip_classesCodes->getStimulationIdentifier(i)).toASCIIString();
|
||||
op_confusionMatrix->setDimensionLabel(0, i, (std::string("Target Class\n") + name));
|
||||
op_confusionMatrix->setDimensionLabel(1, i, (std::string("Result Class\n") + name));
|
||||
}
|
||||
|
||||
if (ip_useSums)
|
||||
{
|
||||
op_confusionMatrix->setDimensionLabel(0, nClass, "Sums");
|
||||
op_confusionMatrix->setDimensionLabel(1, nClass, "Sums");
|
||||
}
|
||||
|
||||
m_confusionMatrix.resize(nClass, nClass);
|
||||
|
||||
// initialization
|
||||
for (size_t i = 0; i < op_confusionMatrix->getDimensionSize(0); ++i)
|
||||
{
|
||||
for (size_t j = 0; j < op_confusionMatrix->getDimensionSize(1); ++j)
|
||||
{
|
||||
op_confusionMatrix->getBuffer()[i * op_confusionMatrix->getDimensionSize(1) + j] = 0.0;
|
||||
if (i < m_confusionMatrix.getDimensionSize(0) && j < m_confusionMatrix.getDimensionSize(1))
|
||||
{
|
||||
m_confusionMatrix.getBuffer()[i * m_confusionMatrix.getDimensionSize(1) + j] = 0.0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this->isInputTriggerActive(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetClassifier)) { }
|
||||
|
||||
if (this->isInputTriggerActive(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedTarget))
|
||||
{
|
||||
for (size_t s = 0; s < ip_targetStimSet->getStimulationCount(); ++s)
|
||||
{
|
||||
uint64_t id = ip_targetStimSet->getStimulationIdentifier(s);
|
||||
if (isClass(id))
|
||||
{
|
||||
uint64_t date = ip_targetStimSet->getStimulationDate(s);
|
||||
m_targetsTimeLines.insert(std::pair<uint64_t, uint64_t>(date, id));
|
||||
getLogManager() << Kernel::LogLevel_Trace << "Current target is " << m_targetsTimeLines.rbegin()->second << "\n";
|
||||
}
|
||||
else { getLogManager() << Kernel::LogLevel_Trace << "The target received is not a valid class: " << id << "\n"; }
|
||||
}
|
||||
}
|
||||
|
||||
if (this->isInputTriggerActive(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedClassifier))
|
||||
{
|
||||
for (size_t s = 0; s < ip_classifierStimSet->getStimulationCount(); ++s)
|
||||
{
|
||||
//We need to locate the stimulation on the timeline
|
||||
uint64_t id = ip_classifierStimSet->getStimulationIdentifier(s);
|
||||
if (!isClass(id))//If we don't have
|
||||
{
|
||||
getLogManager() << Kernel::LogLevel_Trace << "The result received is not a valid class: " << id << "\n";
|
||||
continue;
|
||||
}
|
||||
uint64_t targeted = 0;
|
||||
const uint64_t date = ip_classifierStimSet->getStimulationDate(s);
|
||||
|
||||
bool found = false;
|
||||
for (auto it = m_targetsTimeLines.begin(); it != m_targetsTimeLines.end() && !found; ++it)
|
||||
{
|
||||
auto nextTarget = it;
|
||||
++nextTarget;
|
||||
if ((nextTarget == m_targetsTimeLines.end() || date < nextTarget->first) && date > it->first)
|
||||
{
|
||||
targeted = it->second;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (found)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace << "Result received : " << id << ". Corresponding target : " << targeted << ".\n";
|
||||
|
||||
if (!op_confusionMatrix->getBuffer())
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "The confusion matrix buffer has not yet been initialized\n";
|
||||
return false;
|
||||
}
|
||||
|
||||
// now we found the target, let's update the confusion matrix
|
||||
// we need to update the whole line vector for the targeted class
|
||||
const size_t nOldAttempt = m_nClassificationAttemptPerClass[targeted];
|
||||
m_nClassificationAttemptPerClass[targeted]++; // the confusion matrix can treat this result
|
||||
|
||||
size_t i = getClassIndex(targeted);// the good line index
|
||||
const size_t resultIdx = getClassIndex(id);
|
||||
for (size_t j = 0; j < nClass; ++j)
|
||||
{
|
||||
double newValue = 0.0;
|
||||
const double oldValue = op_confusionMatrix->getBuffer()[i * op_confusionMatrix->getDimensionSize(0) + j];
|
||||
if (j == resultIdx)
|
||||
{
|
||||
newValue = (oldValue * nOldAttempt + 1) / (m_nClassificationAttemptPerClass[targeted]);
|
||||
m_confusionMatrix.getBuffer()[i * nClass + j]++;
|
||||
}
|
||||
else { newValue = (oldValue * nOldAttempt) / (m_nClassificationAttemptPerClass[targeted]); }
|
||||
if (ip_usePercentages) { op_confusionMatrix->getBuffer()[i * op_confusionMatrix->getDimensionSize(0) + j] = newValue; }
|
||||
else // the count value
|
||||
{
|
||||
op_confusionMatrix->getBuffer()[i * op_confusionMatrix->getDimensionSize(0) + j] = m_confusionMatrix.getBuffer()[i * nClass + j];
|
||||
}
|
||||
}
|
||||
|
||||
//we compute the sums if needed
|
||||
if (ip_useSums)
|
||||
{
|
||||
const size_t size = op_confusionMatrix->getDimensionSize(0);
|
||||
double total = 0.0;
|
||||
for (i = 0; i < nClass; ++i)
|
||||
{
|
||||
double sumRow = 0.0;
|
||||
double sumCol = 0.0;
|
||||
for (size_t j = 0; j < nClass; ++j)
|
||||
{
|
||||
sumRow += op_confusionMatrix->getBuffer()[i * size + j];
|
||||
sumCol += op_confusionMatrix->getBuffer()[j * size + i];
|
||||
}
|
||||
op_confusionMatrix->getBuffer()[i * size + size - 1] = sumRow;
|
||||
op_confusionMatrix->getBuffer()[(size - 1) * size + i] = sumCol;
|
||||
total += sumRow;
|
||||
}
|
||||
op_confusionMatrix->getBuffer()[(size - 1) * size + size - 1] =
|
||||
total; // the lower-right entry, i.e. the last in the buffer
|
||||
}
|
||||
}
|
||||
else { getLogManager() << Kernel::LogLevel_Warning << " No target available.\n"; }
|
||||
}
|
||||
this->activateOutputTrigger(OVP_Algorithm_ConfusionMatrixAlgorithm_OutputTriggerId_ConfusionPerformed, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CAlgorithmConfusionMatrix::isClass(const uint64_t id) const
|
||||
{
|
||||
for (size_t i = 0; i < ip_classesCodes->getStimulationCount(); ++i) { if (ip_classesCodes->getStimulationIdentifier(i) == id) { return true; } }
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t CAlgorithmConfusionMatrix::getClassIndex(const uint64_t id) const
|
||||
{
|
||||
for (size_t i = 0; i < ip_classesCodes->getStimulationCount(); ++i) { if (ip_classesCodes->getStimulationIdentifier(i) == id) { return i; } }
|
||||
return -1;
|
||||
}
|
||||
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <map>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
class CAlgorithmConfusionMatrix final : virtual public Toolkit::TAlgorithm<IAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TAlgorithm<IAlgorithm>, OVP_ClassId_Algorithm_ConfusionMatrix)
|
||||
|
||||
protected:
|
||||
|
||||
Kernel::TParameterHandler<bool> ip_usePercentages;
|
||||
Kernel::TParameterHandler<bool> ip_useSums;
|
||||
|
||||
// input TARGET
|
||||
Kernel::TParameterHandler<IStimulationSet*> ip_targetStimSet;
|
||||
// deduced timeline:
|
||||
std::map<uint64_t, uint64_t> m_targetsTimeLines;
|
||||
|
||||
// input CLASSIFIER
|
||||
Kernel::TParameterHandler<IStimulationSet*> ip_classifierStimSet;
|
||||
|
||||
//CONFUSION MATRIX computing
|
||||
Kernel::TParameterHandler<IStimulationSet*> ip_classesCodes;
|
||||
Kernel::TParameterHandler<CMatrix*> op_confusionMatrix;
|
||||
|
||||
CMatrix m_confusionMatrix; // the values, not percentage
|
||||
std::map<uint64_t, size_t> m_nClassificationAttemptPerClass;
|
||||
|
||||
private:
|
||||
|
||||
bool isClass(const uint64_t id) const;
|
||||
size_t getClassIndex(const uint64_t id) const;
|
||||
};
|
||||
|
||||
class CAlgorithmConfusionMatrixDesc final : virtual public IAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Confusion Matrix Algorithm"); }
|
||||
CString getAuthorName() const override { return CString("Laurent Bonnet"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA/IRISA"); }
|
||||
|
||||
CString getShortDescription() const override { return CString("Make a confusion matrix out of classification results coming from one classifier."); }
|
||||
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Classification"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_Algorithm_ConfusionMatrix; }
|
||||
IPluginObject* create() override { return new CAlgorithmConfusionMatrix; }
|
||||
|
||||
bool getAlgorithmPrototype(Kernel::IAlgorithmProto& prototype) const override
|
||||
{
|
||||
prototype.addInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_TargetStimulationSet, "Targets",
|
||||
Kernel::ParameterType_StimulationSet);
|
||||
prototype.addInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassifierStimulationSet, "Classification results",
|
||||
Kernel::ParameterType_StimulationSet);
|
||||
prototype.addInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassCodes, "Class codes", Kernel::ParameterType_StimulationSet);
|
||||
prototype.addInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Percentage, "Percentage", Kernel::ParameterType_Boolean);
|
||||
prototype.addInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Sums, "Sums", Kernel::ParameterType_Boolean);
|
||||
|
||||
prototype.addOutputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_OutputParameterId_ConfusionMatrix, "Confusion matrix",
|
||||
Kernel::ParameterType_Matrix);
|
||||
|
||||
prototype.addInputTrigger(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetTarget, "Reset Target");
|
||||
prototype.addInputTrigger(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetClassifier, "Reset Classifier");
|
||||
prototype.addInputTrigger(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedTarget, "Feed Target");
|
||||
prototype.addInputTrigger(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedClassifier, "Feed Classifier");
|
||||
|
||||
prototype.addOutputTrigger(OVP_Algorithm_ConfusionMatrixAlgorithm_OutputTriggerId_ConfusionPerformed, "Confusion computing performed");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IAlgorithmDesc, OVP_ClassId_Algorithm_ConfusionMatrixDesc)
|
||||
};
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+275
@@ -0,0 +1,275 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "ovpCBoxAlgorithmClassifierAccuracyMeasure.h"
|
||||
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
|
||||
static void reset_scores_button_cb(GtkToolButton* /*button*/, gpointer data)
|
||||
{
|
||||
for (auto& progress : static_cast<CBoxAlgorithmClassifierAccuracyMeasure*>(data)->m_ProgressBar)
|
||||
{
|
||||
progress.score = 0;
|
||||
progress.nStimulation = 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void show_percentages_toggle_button_cb(GtkToggleToolButton* button, gpointer data)
|
||||
{
|
||||
static_cast<CBoxAlgorithmClassifierAccuracyMeasure*>(data)->m_ShowPercentages = (gtk_toggle_tool_button_get_active(button) ? true : false);
|
||||
}
|
||||
|
||||
static void show_scores_toggle_button_cb(GtkToggleToolButton* button, gpointer data)
|
||||
{
|
||||
static_cast<CBoxAlgorithmClassifierAccuracyMeasure*>(data)->m_ShowScores = (gtk_toggle_tool_button_get_active(button) ? true : false);
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmClassifierAccuracyMeasure::initialize()
|
||||
{
|
||||
const size_t nInput = this->getStaticBoxContext().getInputCount();
|
||||
|
||||
m_ProgressBar.resize(getStaticBoxContext().getInputCount() - 1); //-1 because the first input is the target
|
||||
|
||||
//classifier decoders
|
||||
for (size_t i = 1; i < nInput; ++i)
|
||||
{
|
||||
m_classifierStimDecoders.push_back(new Toolkit::TStimulationDecoder<CBoxAlgorithmClassifierAccuracyMeasure>());
|
||||
m_classifierStimDecoders.back()->initialize(*this, i);
|
||||
}
|
||||
|
||||
m_targetStimDecoder.initialize(*this, 0);
|
||||
|
||||
//widgets
|
||||
m_mainWidgetInterface = gtk_builder_new();
|
||||
gtk_builder_add_from_file(m_mainWidgetInterface,
|
||||
Directories::getDataDir() + "/plugins/evaluation/openvibe-simple-visualization-ClassifierAccuracyMeasure.ui", nullptr);
|
||||
|
||||
m_toolbarWidgetInterface = gtk_builder_new();
|
||||
gtk_builder_add_from_file(m_toolbarWidgetInterface,
|
||||
Directories::getDataDir() + "/plugins/evaluation/openvibe-simple-visualization-ClassifierAccuracyMeasure.ui", nullptr);
|
||||
|
||||
gtk_builder_connect_signals(m_mainWidgetInterface, nullptr);
|
||||
gtk_builder_connect_signals(m_toolbarWidgetInterface, nullptr);
|
||||
|
||||
g_signal_connect(G_OBJECT(gtk_builder_get_object(m_toolbarWidgetInterface, "reset-score-button")), "clicked", G_CALLBACK(reset_scores_button_cb), this);
|
||||
g_signal_connect(G_OBJECT(gtk_builder_get_object(m_toolbarWidgetInterface, "show-percentages-toggle-button")), "toggled",
|
||||
G_CALLBACK(show_percentages_toggle_button_cb), this);
|
||||
g_signal_connect(G_OBJECT(gtk_builder_get_object(m_toolbarWidgetInterface, "show-scores-toggle-button")), "toggled",
|
||||
G_CALLBACK(show_scores_toggle_button_cb), this);
|
||||
g_signal_connect(G_OBJECT(gtk_builder_get_object(m_toolbarWidgetInterface, "classifier-accuracy-measure-toolbar")), "delete_event",
|
||||
G_CALLBACK(gtk_widget_hide), nullptr);
|
||||
|
||||
m_mainWidget = GTK_WIDGET(gtk_builder_get_object(m_mainWidgetInterface, "classifier-accuracy-measure-table"));
|
||||
m_toolbarWidget = GTK_WIDGET(gtk_builder_get_object(m_toolbarWidgetInterface, "classifier-accuracy-measure-toolbar"));
|
||||
|
||||
m_visualizationCtx = dynamic_cast<VisualizationToolkit::IVisualizationContext*>(this->createPluginObject(OVP_ClassId_Plugin_VisualizationCtx));
|
||||
m_visualizationCtx->setWidget(*this, m_mainWidget);
|
||||
m_visualizationCtx->setToolbar(*this, m_toolbarWidget);
|
||||
|
||||
m_ShowPercentages = (gtk_toggle_tool_button_get_active(
|
||||
GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(m_toolbarWidgetInterface, "show-percentages-toggle-button"))) ? true : false);
|
||||
m_ShowScores = (gtk_toggle_tool_button_get_active(GTK_TOGGLE_TOOL_BUTTON(gtk_builder_get_object(m_toolbarWidgetInterface, "show-scores-toggle-button")))
|
||||
? true : false);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmClassifierAccuracyMeasure::uninitialize()
|
||||
{
|
||||
const size_t nInput = this->getStaticBoxContext().getInputCount();
|
||||
//decoders
|
||||
for (size_t i = 0; i < nInput - 1; ++i)
|
||||
{
|
||||
m_classifierStimDecoders[i]->uninitialize();
|
||||
delete m_classifierStimDecoders[i];
|
||||
}
|
||||
m_classifierStimDecoders.clear();
|
||||
|
||||
m_targetStimDecoder.uninitialize();
|
||||
|
||||
//widgets
|
||||
g_object_unref(m_toolbarWidgetInterface);
|
||||
m_toolbarWidgetInterface = nullptr;
|
||||
|
||||
g_object_unref(m_mainWidgetInterface);
|
||||
m_mainWidgetInterface = nullptr;
|
||||
|
||||
if (m_visualizationCtx)
|
||||
{
|
||||
this->releasePluginObject(m_visualizationCtx);
|
||||
m_visualizationCtx = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmClassifierAccuracyMeasure::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmClassifierAccuracyMeasure::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
const Kernel::IBox& staticBoxContext = this->getStaticBoxContext();
|
||||
const size_t nInput = staticBoxContext.getInputCount();
|
||||
|
||||
//input chunk 0 = targets
|
||||
// we iterate over the "target" chunks and update the timeline
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
m_targetStimDecoder.decode(i);
|
||||
|
||||
if (m_targetStimDecoder.isHeaderReceived())
|
||||
{
|
||||
//header received
|
||||
//adding the progress bars to the window
|
||||
GtkTable* table = GTK_TABLE(gtk_builder_get_object(m_mainWidgetInterface, "classifier-accuracy-measure-table"));
|
||||
gtk_table_resize(table, 1, guint(nInput - 1));
|
||||
|
||||
//@TODO i variable redefine replace alll i in the loop ( it's logical but must be verified
|
||||
for (guint j = 0; j < nInput - 1; ++j)
|
||||
{
|
||||
GtkBuilder* builderBar = gtk_builder_new();
|
||||
gtk_builder_add_from_file(
|
||||
builderBar, Directories::getDataDir() + "/plugins/evaluation/openvibe-simple-visualization-ClassifierAccuracyMeasure.ui", nullptr);
|
||||
|
||||
GtkBuilder* builderLabel = gtk_builder_new();
|
||||
gtk_builder_add_from_file(
|
||||
builderLabel, Directories::getDataDir() + "/plugins/evaluation/openvibe-simple-visualization-ClassifierAccuracyMeasure.ui", nullptr);
|
||||
|
||||
GtkWidget* bar = GTK_WIDGET(gtk_builder_get_object(builderBar, "progress-bar-classifier-accuracy"));
|
||||
GtkWidget* label = GTK_WIDGET(gtk_builder_get_object(builderLabel, "label-classifier-name"));
|
||||
|
||||
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(bar)), bar);
|
||||
gtk_table_attach(table, bar, j, j + 1, 0, 6, GtkAttachOptions(GTK_EXPAND | GTK_FILL), GtkAttachOptions(GTK_EXPAND | GTK_FILL), 0, 0);
|
||||
gtk_container_remove(GTK_CONTAINER(gtk_widget_get_parent(label)), label);
|
||||
gtk_table_attach(table, label, j, j + 1, 6, 7, GtkAttachOptions(GTK_EXPAND | GTK_FILL), GtkAttachOptions(GTK_EXPAND | GTK_FILL), 0, 0);
|
||||
|
||||
g_object_unref(builderBar);
|
||||
g_object_unref(builderLabel);
|
||||
|
||||
progress_bar_t progressBar;
|
||||
progressBar.progressBar = GTK_PROGRESS_BAR(bar);
|
||||
progressBar.score = 0;
|
||||
progressBar.nStimulation = 0;
|
||||
progressBar.labelClassifier = GTK_LABEL(label);
|
||||
|
||||
gtk_progress_bar_set_fraction(progressBar.progressBar, 0);
|
||||
CString inputName;
|
||||
staticBoxContext.getInputName(j + 1, inputName);
|
||||
gtk_progress_bar_set_text(progressBar.progressBar, inputName.toASCIIString());
|
||||
gtk_label_set_text(progressBar.labelClassifier, inputName.toASCIIString());
|
||||
m_ProgressBar[j] = (progressBar);
|
||||
}
|
||||
|
||||
m_currentProcessingTimeLimit = 0;
|
||||
}
|
||||
|
||||
if (m_targetStimDecoder.isBufferReceived())
|
||||
{
|
||||
//buffer received
|
||||
//A new target comes, let's update the timeline with it
|
||||
const IStimulationSet* dstStimSet = m_targetStimDecoder.getOutputStimulationSet();
|
||||
for (size_t s = 0; s < dstStimSet->getStimulationCount(); ++s)
|
||||
{
|
||||
const uint64_t id = dstStimSet->getStimulationIdentifier(s);
|
||||
const uint64_t date = dstStimSet->getStimulationDate(s);
|
||||
m_targetsTimeLines.insert(std::pair<uint64_t, uint64_t>(date, id));
|
||||
getLogManager() << Kernel::LogLevel_Trace << "New target inserted (" << id << "," << CTime(date) << ")\n";
|
||||
}
|
||||
|
||||
//we updtae the time limit for processing classifier stim
|
||||
const uint64_t chunkEndTime = boxContext.getInputChunkEndTime(0, i);
|
||||
m_currentProcessingTimeLimit = MAX(chunkEndTime, m_currentProcessingTimeLimit);
|
||||
}
|
||||
|
||||
if (m_targetStimDecoder.isEndReceived()) { }
|
||||
|
||||
boxContext.markInputAsDeprecated(0, i);
|
||||
}
|
||||
|
||||
//input index 1-n = n classifier results
|
||||
for (size_t ip = 1; ip < staticBoxContext.getInputCount(); ++ip)
|
||||
{
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(ip); ++i)
|
||||
{
|
||||
// lets get the chunck end time
|
||||
const uint64_t chunkEndTime = boxContext.getInputChunkEndTime(ip, i);
|
||||
// if the incoming chunk is in the timeline
|
||||
if (chunkEndTime <= m_currentProcessingTimeLimit)
|
||||
{
|
||||
if (!m_targetsTimeLines.empty())
|
||||
{
|
||||
// we can process it
|
||||
m_classifierStimDecoders[ip - 1]->decode(i);
|
||||
|
||||
if (m_classifierStimDecoders[ip - 1]->isHeaderReceived()) { } //header received
|
||||
if (m_classifierStimDecoders[ip - 1]->isBufferReceived())
|
||||
{
|
||||
//buffer received
|
||||
const IStimulationSet* stimSet = m_classifierStimDecoders[ip - 1]->getOutputStimulationSet();
|
||||
for (size_t s = 0; s < stimSet->getStimulationCount(); ++s)
|
||||
{
|
||||
//We need to locate the stimulation on the timeline
|
||||
uint64_t id = stimSet->getStimulationIdentifier(s);
|
||||
const uint64_t date = stimSet->getStimulationDate(s);
|
||||
|
||||
getLogManager() << Kernel::LogLevel_Trace << "New Classifier state received (" << id << "," << CTime(date) << ") from Classifier "
|
||||
<< ip << "\n";
|
||||
|
||||
auto it = m_targetsTimeLines.begin();
|
||||
bool cont = true;
|
||||
while (it != m_targetsTimeLines.end() && cont)
|
||||
{
|
||||
auto nextTarget = it;
|
||||
++nextTarget;
|
||||
if ((nextTarget == m_targetsTimeLines.end() || date < nextTarget->first)
|
||||
&& date > it->first)
|
||||
{
|
||||
if (id == it->second)
|
||||
{
|
||||
//+1 for this classifier !
|
||||
m_ProgressBar[ip - 1].score++;
|
||||
}
|
||||
m_ProgressBar[ip - 1].nStimulation++;
|
||||
cont = false;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
|
||||
//auto it = m_targetsTimeLines.lower_bound(l_stimulationFromClassifierDate);
|
||||
}
|
||||
|
||||
std::stringstream ss;
|
||||
ss << std::fixed;
|
||||
ss << std::setprecision(2);
|
||||
if (m_ShowScores) { ss << "score : " << m_ProgressBar[ip - 1].score << "/" << m_ProgressBar[ip - 1].nStimulation << "\n"; }
|
||||
double percent = 0.0;
|
||||
if (m_ProgressBar[ip - 1].nStimulation != 0) { percent = m_ProgressBar[ip - 1].score * 1. / m_ProgressBar[ip - 1].nStimulation; }
|
||||
if (m_ShowPercentages) { ss << percent * 100 << "%\n"; }
|
||||
|
||||
gtk_progress_bar_set_fraction(m_ProgressBar[ip - 1].progressBar, percent);
|
||||
gtk_progress_bar_set_text(m_ProgressBar[ip - 1].progressBar, ss.str().c_str());
|
||||
}
|
||||
|
||||
if (m_targetStimDecoder.isEndReceived()) { }
|
||||
}
|
||||
|
||||
boxContext.markInputAsDeprecated(ip, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
#include <visualization-toolkit/ovviz_all.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
class CBoxAlgorithmClassifierAccuracyMeasure final : public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_ClassifierAccuracyMeasure)
|
||||
|
||||
protected:
|
||||
|
||||
//codecs
|
||||
// for the TARGET
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmClassifierAccuracyMeasure> m_targetStimDecoder;
|
||||
// For the CLASSIFIERS
|
||||
std::vector<Toolkit::TStimulationDecoder<CBoxAlgorithmClassifierAccuracyMeasure>*> m_classifierStimDecoders;
|
||||
|
||||
|
||||
// deduced timeline:
|
||||
std::map<uint64_t, uint64_t> m_targetsTimeLines;
|
||||
uint64_t m_currentProcessingTimeLimit = 0;
|
||||
|
||||
|
||||
// Outputs: visualization in a gtk window
|
||||
GtkBuilder* m_mainWidgetInterface = nullptr;
|
||||
GtkBuilder* m_toolbarWidgetInterface = nullptr;
|
||||
GtkWidget* m_mainWidget = nullptr;
|
||||
GtkWidget* m_toolbarWidget = nullptr;
|
||||
|
||||
public:
|
||||
typedef struct
|
||||
{
|
||||
GtkLabel* labelClassifier;
|
||||
GtkProgressBar* progressBar;
|
||||
size_t score;
|
||||
size_t nStimulation;
|
||||
} progress_bar_t;
|
||||
|
||||
std::vector<progress_bar_t> m_ProgressBar;
|
||||
bool m_ShowPercentages = false;
|
||||
bool m_ShowScores = false;
|
||||
|
||||
private:
|
||||
VisualizationToolkit::IVisualizationContext* m_visualizationCtx = nullptr;
|
||||
};
|
||||
|
||||
class CBoxAlgorithmClassifierAccuracyMeasureListener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
bool onInputNameChanged(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
if (index == 0) { box.setInputName(0, "Targets"); } // forced
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onInputAdded(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
box.setInputType(index, OV_TypeId_Stimulations); // all inputs must be stimulations
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
|
||||
class CBoxAlgorithmClassifierAccuracyMeasureDesc final : public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Classifier Accuracy Measure"); }
|
||||
CString getAuthorName() const override { return CString("Laurent Bonnet"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA/IRISA"); }
|
||||
|
||||
CString getShortDescription() const override { return CString("Displays real-time classifier accuracies as vertical progress bars"); }
|
||||
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Evaluation/Classification"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-sort-ascending"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_ClassifierAccuracyMeasure; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmClassifierAccuracyMeasure; }
|
||||
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmClassifierAccuracyMeasureListener; }
|
||||
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
|
||||
|
||||
bool hasFunctionality(const EPluginFunctionality functionality) const override { return functionality == EPluginFunctionality::Visualization; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Targets", OV_TypeId_Stimulations);
|
||||
prototype.addInput("Classifier 1", OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddInput);
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifyInput);
|
||||
|
||||
prototype.addInputSupport(OV_TypeId_Stimulations);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_ClassifierAccuracyMeasureDesc)
|
||||
};
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyGTK
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
#include "ovpCBoxAlgorithmConfusionMatrix.h"
|
||||
|
||||
#include "../algorithms/ovpCAlgorithmConfusionMatrix.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
|
||||
bool CBoxAlgorithmConfusionMatrix::initialize()
|
||||
{
|
||||
//Initialize input/output
|
||||
m_targetStimDecoder.initialize(*this, 0);
|
||||
m_classifierStimDecoder.initialize(*this, 1);
|
||||
|
||||
m_encoder.initialize(*this, 0);
|
||||
|
||||
//CONFUSION MATRIX ALGORITHM
|
||||
m_algorithm = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_ConfusionMatrix));
|
||||
m_algorithm->initialize();
|
||||
|
||||
Kernel::TParameterHandler<bool> percentHandler(m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Percentage));
|
||||
percentHandler = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
|
||||
Kernel::TParameterHandler<bool> sumsHandler(m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Sums));
|
||||
if (!bool(percentHandler)) { sumsHandler = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 1); }
|
||||
else
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Debug << "Asking for percentage. The value of the setting \"Sums\" will be ignored.\n";
|
||||
sumsHandler = false;
|
||||
}
|
||||
|
||||
|
||||
const size_t nClass = getBoxAlgorithmContext()->getStaticBoxContext()->getSettingCount() - FIRST_CLASS_SETTING_INDEX;
|
||||
std::vector<size_t> classCodes;
|
||||
classCodes.resize(nClass);
|
||||
for (size_t i = 0; i < nClass; ++i)
|
||||
{
|
||||
// classes are settings from 2 to n
|
||||
classCodes[i] = uint64_t(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i + FIRST_CLASS_SETTING_INDEX));
|
||||
}
|
||||
// verification...
|
||||
for (size_t i = 0; i < nClass; ++i)
|
||||
{
|
||||
for (size_t j = i + 1; j < nClass; ++j)
|
||||
{
|
||||
if (classCodes[i] == classCodes[j])
|
||||
{
|
||||
const CString classValue = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i + FIRST_CLASS_SETTING_INDEX);
|
||||
getLogManager() << Kernel::LogLevel_Error << "You must use unique classes to compute a confusion matrix. Class " << i + 1 << " and " << j + 1 <<
|
||||
" are the same (" << classValue << ").\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Kernel::TParameterHandler<IStimulationSet*> classesCodesHandler(m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassCodes));
|
||||
for (size_t i = 0; i < classCodes.size(); ++i) { classesCodesHandler->appendStimulation(classCodes[i], 0, 0); }
|
||||
|
||||
//Link all input/output
|
||||
Kernel::TParameterHandler<IStimulationSet*> classifierStimSetHandler(
|
||||
m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassifierStimulationSet));
|
||||
classifierStimSetHandler.setReferenceTarget(m_classifierStimDecoder.getOutputStimulationSet());
|
||||
|
||||
Kernel::TParameterHandler<IStimulationSet*> targetStimSetHandler(
|
||||
m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_TargetStimulationSet));
|
||||
targetStimSetHandler.setReferenceTarget(m_targetStimDecoder.getOutputStimulationSet());
|
||||
|
||||
Kernel::TParameterHandler<CMatrix*> matrixHandler(m_algorithm->getOutputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_OutputParameterId_ConfusionMatrix));
|
||||
m_encoder.getInputMatrix().setReferenceTarget(matrixHandler);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmConfusionMatrix::uninitialize()
|
||||
{
|
||||
m_algorithm->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_algorithm);
|
||||
|
||||
m_encoder.uninitialize();
|
||||
m_targetStimDecoder.uninitialize();
|
||||
m_classifierStimDecoder.uninitialize();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmConfusionMatrix::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmConfusionMatrix::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
//Input 0: Targets
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
m_targetStimDecoder.decode(i);
|
||||
|
||||
if (m_targetStimDecoder.isHeaderReceived())
|
||||
{
|
||||
m_algorithm->process(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetTarget);
|
||||
|
||||
m_encoder.encodeHeader();
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i));
|
||||
m_currentProcessingTimeLimit = 0;
|
||||
}
|
||||
|
||||
if (m_targetStimDecoder.isBufferReceived())
|
||||
{
|
||||
uint64_t chunkEndTime = boxContext.getInputChunkEndTime(0, i);
|
||||
m_currentProcessingTimeLimit = (chunkEndTime > m_currentProcessingTimeLimit ? chunkEndTime : m_currentProcessingTimeLimit);
|
||||
m_algorithm->process(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedTarget);
|
||||
}
|
||||
|
||||
if (m_targetStimDecoder.isEndReceived())
|
||||
{
|
||||
m_encoder.encodeEnd();
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i));
|
||||
}
|
||||
}
|
||||
|
||||
//Input 1: Classifier results
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(1); ++i)
|
||||
{
|
||||
const uint64_t tEnd = boxContext.getInputChunkEndTime(1, i);
|
||||
if (tEnd <= m_currentProcessingTimeLimit)
|
||||
{
|
||||
m_classifierStimDecoder.decode(i);
|
||||
|
||||
if (m_classifierStimDecoder.isHeaderReceived()) { m_algorithm->process(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetClassifier); }
|
||||
|
||||
if (m_classifierStimDecoder.isBufferReceived())
|
||||
{
|
||||
m_algorithm->process(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedClassifier);
|
||||
if (m_algorithm->isOutputTriggerActive(OVP_Algorithm_ConfusionMatrixAlgorithm_OutputTriggerId_ConfusionPerformed))
|
||||
{
|
||||
m_encoder.encodeBuffer();
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(1, i), boxContext.getInputChunkEndTime(1, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_classifierStimDecoder.isEndReceived())
|
||||
{
|
||||
m_encoder.encodeEnd();
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(1, i), boxContext.getInputChunkEndTime(1, i));
|
||||
}
|
||||
|
||||
boxContext.markInputAsDeprecated(1, i);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <iomanip>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
class CBoxAlgorithmConfusionMatrix final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_ConfusionMatrix)
|
||||
|
||||
protected:
|
||||
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmConfusionMatrix> m_targetStimDecoder;
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmConfusionMatrix> m_classifierStimDecoder;
|
||||
|
||||
Toolkit::TStreamedMatrixEncoder<CBoxAlgorithmConfusionMatrix> m_encoder;
|
||||
|
||||
Kernel::IAlgorithmProxy* m_algorithm = nullptr;
|
||||
|
||||
uint64_t m_currentProcessingTimeLimit = 0;
|
||||
};
|
||||
|
||||
class CBoxAlgorithmConfusionMatrixListener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
|
||||
bool onSettingAdded(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
std::stringstream value;
|
||||
value << "OVTK_StimulationId_Label_" << std::setfill('0') << std::setw(2) << index - 2;
|
||||
box.setSettingName(index, ("Class " + std::to_string(index - 1)).c_str());
|
||||
box.setSettingType(index, OV_TypeId_Stimulation);
|
||||
box.setSettingValue(index, value.str().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool onSettingRemoved(Kernel::IBox& box, const size_t /*index*/) override
|
||||
{
|
||||
const size_t nSetting = box.getSettingCount();
|
||||
const size_t nClass = nSetting - FIRST_CLASS_SETTING_INDEX;
|
||||
|
||||
for (size_t i = 0; i < nClass; ++i) { box.setSettingName(FIRST_CLASS_SETTING_INDEX + i, ("Class " + std::to_string(i + 1)).c_str()); }
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
|
||||
class CBoxAlgorithmConfusionMatrixDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Confusion Matrix"); }
|
||||
CString getAuthorName() const override { return CString("Laurent Bonnet"); }
|
||||
CString getAuthorCompanyName() const override { return CString("INRIA/IRISA"); }
|
||||
|
||||
CString getShortDescription() const override { return CString("Make a confusion matrix out of classification results coming from one classifier."); }
|
||||
|
||||
CString getDetailedDescription() const override { return CString(""); }
|
||||
CString getCategory() const override { return CString("Evaluation/Classification"); }
|
||||
CString getVersion() const override { return CString("1.0"); }
|
||||
CString getStockItemName() const override { return CString("gtk-execute"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_ConfusionMatrix; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmConfusionMatrix; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Targets", OV_TypeId_Stimulations);
|
||||
prototype.addInput("Classification results", OV_TypeId_Stimulations);
|
||||
prototype.addOutput("Confusion Matrix", OV_TypeId_StreamedMatrix);
|
||||
|
||||
prototype.addSetting("Percentages", OV_TypeId_Boolean, "true");
|
||||
prototype.addSetting("Sums", OV_TypeId_Boolean, "false");
|
||||
|
||||
prototype.addSetting("Class 1", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_00");
|
||||
prototype.addSetting("Class 2", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_01");
|
||||
|
||||
prototype.addFlag(Kernel::BoxFlag_CanAddSetting);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmConfusionMatrixListener; }
|
||||
virtual void releaseBoxListener(IBoxListener* listener) { delete listener; }
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_ConfusionMatrixDesc)
|
||||
};
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "ovpCBoxAlgorithmKappaCoefficient.h"
|
||||
#include "../algorithms/ovpCAlgorithmConfusionMatrix.h"
|
||||
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <iomanip>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
|
||||
static const size_t CLASS_LABEL_OFFSET = 1;
|
||||
|
||||
bool CBoxAlgorithmKappaCoef::initialize()
|
||||
{
|
||||
//Initialize input/output
|
||||
m_targetStimDecoder.initialize(*this, 0);
|
||||
m_classifierStimDecoder.initialize(*this, 1);
|
||||
|
||||
m_encoder.initialize(*this, 0);
|
||||
|
||||
//Confusion matrix algorithm
|
||||
m_algorithm = &this->getAlgorithmManager().getAlgorithm(this->getAlgorithmManager().createAlgorithm(OVP_ClassId_Algorithm_ConfusionMatrix));
|
||||
m_algorithm->initialize();
|
||||
|
||||
Kernel::TParameterHandler<bool> percentHandler(m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Percentage));
|
||||
percentHandler = false;
|
||||
|
||||
Kernel::TParameterHandler<bool> sumsHandler(m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Sums));
|
||||
sumsHandler = true;
|
||||
|
||||
m_amountClass = getBoxAlgorithmContext()->getStaticBoxContext()->getSettingCount() - CLASS_LABEL_OFFSET;
|
||||
std::vector<size_t> classCodes;
|
||||
classCodes.resize(m_amountClass);
|
||||
for (size_t i = 0; i < m_amountClass; ++i)
|
||||
{
|
||||
// classes are settings from 2 to n
|
||||
classCodes[i] = uint64_t(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i + CLASS_LABEL_OFFSET));
|
||||
}
|
||||
|
||||
// Let's check that each identifier is unique
|
||||
for (size_t i = 0; i < m_amountClass; ++i)
|
||||
{
|
||||
for (size_t j = i + 1; j < m_amountClass; ++j)
|
||||
{
|
||||
if (classCodes[i] == classCodes[j])
|
||||
{
|
||||
const CString value = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i + CLASS_LABEL_OFFSET);
|
||||
getLogManager() << Kernel::LogLevel_Error << "You must use unique classes to compute a Kappa coefficient. Class " << i + 1 << " and " << j + 1
|
||||
<< " are the same (" << value.toASCIIString() << ").\n";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Kernel::TParameterHandler<IStimulationSet*> classesCodesHandler(
|
||||
m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassCodes));
|
||||
for (size_t i = 0; i < classCodes.size(); ++i) { classesCodesHandler->appendStimulation(classCodes[i], 0, 0); }
|
||||
|
||||
//Link all input/output
|
||||
Kernel::TParameterHandler<IStimulationSet*> classifierStimSetHandler(
|
||||
m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassifierStimulationSet));
|
||||
classifierStimSetHandler.setReferenceTarget(m_classifierStimDecoder.getOutputStimulationSet());
|
||||
|
||||
Kernel::TParameterHandler<IStimulationSet*> targetStimSetHandler(
|
||||
m_algorithm->getInputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_TargetStimulationSet));
|
||||
targetStimSetHandler.setReferenceTarget(m_targetStimDecoder.getOutputStimulationSet());
|
||||
|
||||
op_confusionMatrix.initialize(m_algorithm->getOutputParameter(OVP_Algorithm_ConfusionMatrixAlgorithm_OutputParameterId_ConfusionMatrix));
|
||||
|
||||
GtkTable* table = GTK_TABLE(gtk_table_new(2, 1, false));
|
||||
|
||||
m_kappaLabel = gtk_label_new("x");
|
||||
gtk_table_attach(table, m_kappaLabel, 0, 1, 0, 5, GtkAttachOptions(GTK_EXPAND | GTK_FILL), GtkAttachOptions(GTK_EXPAND | GTK_FILL), 0, 0);
|
||||
|
||||
|
||||
m_visualizationCtx = dynamic_cast<VisualizationToolkit::IVisualizationContext*>(this->createPluginObject(OVP_ClassId_Plugin_VisualizationCtx));
|
||||
m_visualizationCtx->setWidget(*this, GTK_WIDGET(table));
|
||||
|
||||
PangoContext* ctx = gtk_widget_get_pango_context(GTK_WIDGET(m_kappaLabel));
|
||||
PangoFontDescription* fontDesc = pango_context_get_font_description(ctx);
|
||||
pango_font_description_set_size(fontDesc, 40 * PANGO_SCALE);
|
||||
gtk_widget_modify_font(m_kappaLabel, fontDesc);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmKappaCoef::uninitialize()
|
||||
{
|
||||
//Log for the automatic test
|
||||
this->getLogManager() << Kernel::LogLevel_Info << "Final value of Kappa " << m_kappaCoef << "\n";
|
||||
m_algorithm->uninitialize();
|
||||
this->getAlgorithmManager().releaseAlgorithm(*m_algorithm);
|
||||
|
||||
m_encoder.uninitialize();
|
||||
m_targetStimDecoder.uninitialize();
|
||||
m_classifierStimDecoder.uninitialize();
|
||||
|
||||
if (m_visualizationCtx)
|
||||
{
|
||||
this->releasePluginObject(m_visualizationCtx);
|
||||
m_visualizationCtx = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CBoxAlgorithmKappaCoef::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmKappaCoef::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
//Input 0: Targets
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
m_targetStimDecoder.decode(i);
|
||||
|
||||
if (m_targetStimDecoder.isHeaderReceived())
|
||||
{
|
||||
m_algorithm->process(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetTarget);
|
||||
|
||||
m_encoder.getInputMatrix()->resize(1);
|
||||
m_encoder.getInputMatrix()->setDimensionLabel(0, 0, "Kappa");
|
||||
|
||||
m_encoder.encodeHeader();
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i));
|
||||
m_currentProcessingTimeLimit = 0;
|
||||
}
|
||||
|
||||
if (m_targetStimDecoder.isBufferReceived())
|
||||
{
|
||||
uint64_t end = boxContext.getInputChunkEndTime(0, i);
|
||||
m_currentProcessingTimeLimit = (end > m_currentProcessingTimeLimit ? end : m_currentProcessingTimeLimit);
|
||||
m_algorithm->process(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedTarget);
|
||||
}
|
||||
|
||||
if (m_targetStimDecoder.isEndReceived())
|
||||
{
|
||||
m_encoder.encodeEnd();
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(0, i), boxContext.getInputChunkEndTime(0, i));
|
||||
}
|
||||
}
|
||||
|
||||
//Input 1: Classifier results
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(1); ++i)
|
||||
{
|
||||
const uint64_t end = boxContext.getInputChunkEndTime(1, i);
|
||||
if (end <= m_currentProcessingTimeLimit)
|
||||
{
|
||||
m_classifierStimDecoder.decode(i);
|
||||
|
||||
if (m_classifierStimDecoder.isHeaderReceived()) { m_algorithm->process(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetClassifier); }
|
||||
|
||||
if (m_classifierStimDecoder.isBufferReceived())
|
||||
{
|
||||
m_algorithm->process(OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedClassifier);
|
||||
if (m_algorithm->isOutputTriggerActive(OVP_Algorithm_ConfusionMatrixAlgorithm_OutputTriggerId_ConfusionPerformed))
|
||||
{
|
||||
//The confusion matrix has changed so we need to update the kappa coefficient
|
||||
double* matrix = op_confusionMatrix->getBuffer();
|
||||
//First we need the amount of sample that have been classified
|
||||
const size_t total = size_t(matrix[(m_amountClass + 1) * (m_amountClass + 1) - 1]);
|
||||
|
||||
//Now we gonna compute the two sum we need to compute the kappa coefficient
|
||||
//It's more easy to use a double loop
|
||||
double observed = 0;
|
||||
double expected = 0;
|
||||
|
||||
for (size_t j = 0; j < m_amountClass; ++j)
|
||||
{
|
||||
//We need to take the column sum in account
|
||||
observed += matrix[j * (m_amountClass + 1) + j];
|
||||
expected += (matrix[(m_amountClass + 1) * j + m_amountClass] * matrix[(m_amountClass + 1) * m_amountClass + j]);
|
||||
}
|
||||
observed /= total;
|
||||
expected /= (total * total);
|
||||
|
||||
m_kappaCoef = (observed - expected) / (1 - expected);
|
||||
|
||||
updateKappaValue();
|
||||
m_encoder.getInputMatrix()->getBuffer()[0] = m_kappaCoef;
|
||||
m_encoder.encodeBuffer();
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(1, i), boxContext.getInputChunkEndTime(1, i));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_classifierStimDecoder.isEndReceived())
|
||||
{
|
||||
m_encoder.encodeEnd();
|
||||
boxContext.markOutputAsReadyToSend(0, boxContext.getInputChunkStartTime(1, i), boxContext.getInputChunkEndTime(1, i));
|
||||
}
|
||||
|
||||
boxContext.markInputAsDeprecated(1, i);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBoxAlgorithmKappaCoef::updateKappaValue() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(2) << m_kappaCoef;
|
||||
gtk_label_set(GTK_LABEL(m_kappaLabel), ss.str().c_str());
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+165
@@ -0,0 +1,165 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
//You may have to change this path to match your folder organisation
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <visualization-toolkit/ovviz_all.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
/**
|
||||
* \class CBoxAlgorithmKappaCoef
|
||||
* \author Serrière Guillaume (Inria)
|
||||
* \date Tue May 5 12:45:13 2015
|
||||
* \brief The class CBoxAlgorithmKappaCoef describes the box Kappa coefficient.
|
||||
*
|
||||
*/
|
||||
class CBoxAlgorithmKappaCoef final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_KappaCoef)
|
||||
|
||||
protected:
|
||||
void updateKappaValue() const;
|
||||
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmKappaCoef> m_targetStimDecoder;
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmKappaCoef> m_classifierStimDecoder;
|
||||
|
||||
Toolkit::TStreamedMatrixEncoder<CBoxAlgorithmKappaCoef> m_encoder;
|
||||
|
||||
Kernel::TParameterHandler<CMatrix*> op_confusionMatrix;
|
||||
|
||||
Kernel::IAlgorithmProxy* m_algorithm = nullptr;
|
||||
|
||||
size_t m_amountClass = 0;
|
||||
uint64_t m_currentProcessingTimeLimit = 0;
|
||||
double m_kappaCoef = 0;
|
||||
|
||||
GtkWidget* m_kappaLabel = nullptr;
|
||||
private:
|
||||
VisualizationToolkit::IVisualizationContext* m_visualizationCtx = nullptr;
|
||||
};
|
||||
|
||||
|
||||
// The box listener can be used to call specific callbacks whenever the box structure changes : input added, name changed, etc.
|
||||
// Please uncomment below the callbacks you want to use.
|
||||
class CBoxAlgorithmKappaCoefListener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
|
||||
bool onSettingValueChanged(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
if (index == 0)
|
||||
{
|
||||
CString nClass;
|
||||
box.getSettingValue(index, nClass);
|
||||
|
||||
if (nClass.length() == 0) { return true; }
|
||||
|
||||
size_t nSetting;
|
||||
std::stringstream ss(nClass.toASCIIString());
|
||||
ss >> nSetting;
|
||||
|
||||
//First of all we prevent for the value to goes under 1.
|
||||
if (nSetting < 1)
|
||||
{
|
||||
box.setSettingValue(index, "1");
|
||||
nSetting = 1;
|
||||
}
|
||||
size_t nCurrent = box.getSettingCount() - 1;
|
||||
//We have two choice 1/We need to add class, 2/We need to remove some
|
||||
if (nCurrent < nSetting)
|
||||
{
|
||||
while (nCurrent < nSetting)
|
||||
{
|
||||
box.addSetting(("Stimulation of class " + std::to_string(nCurrent + 1)).c_str(), OVTK_TypeId_Stimulation, "");
|
||||
++nCurrent;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (nCurrent > nSetting)
|
||||
{
|
||||
box.removeSetting(box.getSettingCount() - 1);
|
||||
--nCurrent;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
|
||||
/**
|
||||
* \class CBoxAlgorithmKappaCoefDesc
|
||||
* \author Serrière Guillaume (Inria)
|
||||
* \date Tue May 5 12:45:13 2015
|
||||
* \brief Descriptor of the box Kappa coefficient.
|
||||
*
|
||||
*/
|
||||
class CBoxAlgorithmKappaCoefDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("Kappa coefficient"); }
|
||||
CString getAuthorName() const override { return CString("Serrière Guillaume"); }
|
||||
CString getAuthorCompanyName() const override { return CString("Inria"); }
|
||||
CString getShortDescription() const override { return CString("Compute the kappa coefficient for the classifier."); }
|
||||
CString getDetailedDescription() const override { return CString("The box computes kappa coefficient for a classifier."); }
|
||||
CString getCategory() const override { return CString("Evaluation/Classification"); }
|
||||
CString getVersion() const override { return CString("0.1"); }
|
||||
CString getStockItemName() const override { return CString("gtk-yes"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_KappaCoef; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmKappaCoef; }
|
||||
|
||||
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmKappaCoefListener; }
|
||||
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
|
||||
|
||||
bool hasFunctionality(const EPluginFunctionality functionality) const override { return functionality == EPluginFunctionality::Visualization; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Expected stimulations", OV_TypeId_Stimulations);
|
||||
prototype.addInput("Found stimulations", OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addOutput("Confusion Matrix", OV_TypeId_StreamedMatrix);
|
||||
|
||||
prototype.addSetting("Number of classes", OV_TypeId_Integer, "2");
|
||||
prototype.addSetting("Stimulation of class 1", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_01");
|
||||
prototype.addSetting("Stimulation of class 2", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_02");
|
||||
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifySetting);
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_KappaCoefDesc)
|
||||
};
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyGTK
|
||||
+200
@@ -0,0 +1,200 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "ovpCBoxAlgorithmROCCurve.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
|
||||
static bool compareCTimelineStimulationPair(const CTimestampLabelPair& rElt1, const CTimestampLabelPair& rElt2) { return rElt1.first < rElt2.first; }
|
||||
|
||||
static bool compareValueAndStimulationTimelinePair(const CTimestampLabelPair& rElt1, const CTimestampValuesPair& rElt2) { return rElt1.first < rElt2.first; }
|
||||
|
||||
static bool compareRocValuePair(const CRocPairValue& rElt1, const CRocPairValue& rElt2) { return rElt1.second > rElt2.second; }
|
||||
|
||||
static bool isPositive(const CRocPairValue& rElt1) { return rElt1.first; }
|
||||
|
||||
bool CBoxAlgorithmROCCurve::initialize()
|
||||
{
|
||||
m_expectedDecoder.initialize(*this, 0);
|
||||
m_classificationDecoder.initialize(*this, 1);
|
||||
|
||||
m_computationTrigger = CIdentifier(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0));
|
||||
|
||||
m_widget = GTK_WIDGET(gtk_notebook_new());
|
||||
|
||||
for (size_t i = 2; i < this->getStaticBoxContext().getSettingCount(); ++i)
|
||||
{
|
||||
CIdentifier classLabel(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i));
|
||||
CString className = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i);
|
||||
|
||||
m_classStimSet.insert(classLabel);
|
||||
|
||||
m_drawerList.push_back(new CROCCurveDraw(GTK_NOTEBOOK(m_widget), i - 1, className));
|
||||
}
|
||||
|
||||
m_visualizationCtx = dynamic_cast<VisualizationToolkit::IVisualizationContext*>(this->createPluginObject(OVP_ClassId_Plugin_VisualizationCtx));
|
||||
m_visualizationCtx->setWidget(*this, m_widget);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmROCCurve::uninitialize()
|
||||
{
|
||||
m_expectedDecoder.uninitialize();
|
||||
m_classificationDecoder.uninitialize();
|
||||
|
||||
for (size_t i = 0; i < m_drawerList.size(); ++i) { delete m_drawerList[i]; }
|
||||
|
||||
//The m_valueTimeline vector contains each dynamically instantiate values that need to be free'd
|
||||
for (size_t i = 0; i < m_valueTimeline.size(); ++i) { delete m_valueTimeline[i].second; }
|
||||
|
||||
if (m_visualizationCtx)
|
||||
{
|
||||
this->releasePluginObject(m_visualizationCtx);
|
||||
m_visualizationCtx = nullptr;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CBoxAlgorithmROCCurve::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CBoxAlgorithmROCCurve::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
//First let's deal with the expected.
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
m_expectedDecoder.decode(i);
|
||||
|
||||
if (m_expectedDecoder.isHeaderReceived()) { m_stimTimeline.clear(); }
|
||||
|
||||
if (m_expectedDecoder.isBufferReceived())
|
||||
{
|
||||
IStimulationSet* stimSet = m_expectedDecoder.getOutputStimulationSet();
|
||||
for (size_t k = 0; k < stimSet->getStimulationCount(); ++k)
|
||||
{
|
||||
CIdentifier id = stimSet->getStimulationIdentifier(k);
|
||||
if (m_classStimSet.find(id) != m_classStimSet.end()) { m_stimTimeline.push_back(CTimestampLabelPair(stimSet->getStimulationDate(k), id.id())); }
|
||||
//We need to check if we receive the computation trigger
|
||||
if (id == m_computationTrigger) { computeROCCurves(); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(1); ++i)
|
||||
{
|
||||
m_classificationDecoder.decode(i);
|
||||
if (m_classificationDecoder.isHeaderReceived()) { m_valueTimeline.clear(); }
|
||||
if (m_classificationDecoder.isBufferReceived())
|
||||
{
|
||||
CMatrix* matrixValue = m_classificationDecoder.getOutputMatrix();
|
||||
//The matrix is suppose to have only one dimension
|
||||
double* arrayValue;
|
||||
|
||||
if (matrixValue->getBufferElementCount() == 0)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "Received zero-sized buffer\n";
|
||||
return false;
|
||||
}
|
||||
if (matrixValue->getBufferElementCount() > 1)
|
||||
{
|
||||
arrayValue = new double[matrixValue->getBufferElementCount()];
|
||||
for (size_t k = 0; k < matrixValue->getBufferElementCount(); ++k) { arrayValue[k] = matrixValue->getBuffer()[k]; }
|
||||
}
|
||||
else
|
||||
{
|
||||
arrayValue = new double[2];
|
||||
arrayValue[0] = matrixValue->getBuffer()[0];
|
||||
arrayValue[1] = 1 - matrixValue->getBuffer()[0];
|
||||
}
|
||||
|
||||
uint64_t timestamp = boxContext.getInputChunkEndTime(1, i); //the time in stimulation correspond to the end of the chunck (cf processorbox code)
|
||||
m_valueTimeline.push_back(CTimestampValuesPair(timestamp, arrayValue));
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmROCCurve::computeROCCurves()
|
||||
{
|
||||
//Now we assiociate all values to the corresponding label
|
||||
std::sort(m_stimTimeline.begin(), m_stimTimeline.end(), compareCTimelineStimulationPair);//ensure the timeline is ok
|
||||
|
||||
for (auto& val : m_valueTimeline)
|
||||
{
|
||||
auto bound = std::lower_bound(m_stimTimeline.begin(), m_stimTimeline.end(), val, compareValueAndStimulationTimelinePair);
|
||||
if (bound != m_stimTimeline.begin())
|
||||
{
|
||||
--bound;
|
||||
m_labelValueList.push_back(CLabelValuesPair(bound->second, val.second));
|
||||
}
|
||||
else
|
||||
{
|
||||
//Impossible to find the corresponding stimulation
|
||||
this->getLogManager() << Kernel::LogLevel_Warning << "A result of classification cannot be connected to a class. The result will be discarded.\n";
|
||||
}
|
||||
}
|
||||
|
||||
//We cannot use the set because we need the correct order
|
||||
for (size_t i = 2; i < this->getStaticBoxContext().getSettingCount(); ++i)
|
||||
{
|
||||
CIdentifier classLabel(FSettingValueAutoCast(*this->getBoxAlgorithmContext(), i));
|
||||
computeOneROCCurve(classLabel, i - 2);
|
||||
}
|
||||
//Now we ask to the current page to draw itself
|
||||
const gint currPage = gtk_notebook_current_page(GTK_NOTEBOOK(m_widget));
|
||||
if (currPage < 0)
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Trace <<
|
||||
"No page is selected. The designer is probably in no visualization mode. Skipping the drawing phase\n";
|
||||
}
|
||||
else { m_drawerList[currPage]->forceRedraw(); }
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmROCCurve::computeOneROCCurve(const CIdentifier& classID, const size_t classIdx)
|
||||
{
|
||||
std::vector<CRocPairValue> values;
|
||||
for (const auto& v : m_labelValueList)
|
||||
{
|
||||
CRocPairValue value;
|
||||
value.first = v.first == classID.id();
|
||||
value.second = v.second[classIdx];
|
||||
values.push_back(value);
|
||||
}
|
||||
std::sort(values.begin(), values.end(), compareRocValuePair);
|
||||
|
||||
size_t nTruePositive = 0;
|
||||
size_t nFalsePositive = 0;
|
||||
|
||||
const size_t nPositive = std::count_if(values.begin(), values.end(), isPositive);
|
||||
const size_t nNegative = values.size() - nPositive;
|
||||
|
||||
std::vector<CCoordinate>& coordinateVector = m_drawerList[classIdx]->getCoordinateVector();
|
||||
|
||||
for (const auto& value : values)
|
||||
{
|
||||
value.first ? ++nTruePositive : ++nFalsePositive;
|
||||
coordinateVector.push_back(CCoordinate(double(nFalsePositive) / nNegative, double(nTruePositive) / nPositive));
|
||||
}
|
||||
m_drawerList[classIdx]->generateCurve();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+181
@@ -0,0 +1,181 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include "ovpCROCCurveDraw.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include <visualization-toolkit/ovviz_all.h>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
typedef std::pair<uint64_t, uint64_t> CTimestampLabelPair;
|
||||
typedef std::pair<uint64_t, double*> CTimestampValuesPair;
|
||||
typedef std::pair<uint64_t, double*> CLabelValuesPair;
|
||||
|
||||
typedef std::pair<bool, double> CRocPairValue;
|
||||
|
||||
/**
|
||||
* \class CBoxAlgorithmROCCurve
|
||||
* \author Serrière Guillaume (Inria)
|
||||
* \date Thu May 28 11:49:24 2015
|
||||
* \brief The class CBoxAlgorithmROCCurve describes the box ROC curve.
|
||||
* The roc curve is a graphical plot that represents the performance of a classifier. This curve is created by plotting the true positive
|
||||
* rate against the false positive rate at various threshold settings.
|
||||
*
|
||||
*/
|
||||
class CBoxAlgorithmROCCurve final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
bool processInput(const size_t index) override;
|
||||
|
||||
bool process() override;
|
||||
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_ROCCurve)
|
||||
|
||||
private:
|
||||
bool computeROCCurves();
|
||||
bool computeOneROCCurve(const CIdentifier& classID, const size_t classIdx);
|
||||
|
||||
// Input decoder:
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmROCCurve> m_expectedDecoder;
|
||||
Toolkit::TStreamedMatrixDecoder<CBoxAlgorithmROCCurve> m_classificationDecoder;
|
||||
|
||||
std::set<CIdentifier> m_classStimSet;
|
||||
CIdentifier m_computationTrigger = CIdentifier::undefined();
|
||||
|
||||
std::vector<CTimestampLabelPair> m_stimTimeline;
|
||||
std::vector<CTimestampValuesPair> m_valueTimeline;
|
||||
|
||||
std::vector<CLabelValuesPair> m_labelValueList;
|
||||
|
||||
//Display section
|
||||
GtkWidget* m_widget = nullptr;
|
||||
std::vector<CROCCurveDraw*> m_drawerList;
|
||||
|
||||
VisualizationToolkit::IVisualizationContext* m_visualizationCtx = nullptr;
|
||||
};
|
||||
|
||||
// The box listener can be used to call specific callbacks whenever the box structure changes : input added, name changed, etc.
|
||||
// Please uncomment below the callbacks you want to use.
|
||||
class CBoxAlgorithmROCCurveListener final : public Toolkit::TBoxListener<IBoxListener>
|
||||
{
|
||||
public:
|
||||
|
||||
bool onSettingValueChanged(Kernel::IBox& box, const size_t index) override
|
||||
{
|
||||
if (index == 1)
|
||||
{
|
||||
CString nClass;
|
||||
box.getSettingValue(index, nClass);
|
||||
//Could happen if we rewritte a number
|
||||
if (nClass.length() == 0) { return true; }
|
||||
|
||||
size_t nSetting;
|
||||
std::stringstream ss(nClass.toASCIIString());
|
||||
ss >> nSetting;
|
||||
|
||||
//First of all we prevent for the value to goes under 1.
|
||||
if (nSetting < 1)
|
||||
{
|
||||
box.setSettingValue(index, "1");
|
||||
nSetting = 1;
|
||||
}
|
||||
|
||||
size_t nCurrent = box.getSettingCount() - 2;
|
||||
//We have two choice 1/We need to add class, 2/We need to remove some
|
||||
if (nCurrent < nSetting)
|
||||
{
|
||||
while (nCurrent < nSetting)
|
||||
{
|
||||
box.addSetting(("Class " + std::to_string(nCurrent + 1) + " identifier").c_str(), OVTK_TypeId_Stimulation, "");
|
||||
++nCurrent;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (nCurrent > nSetting)
|
||||
{
|
||||
box.removeSetting(box.getSettingCount() - 1);
|
||||
--nCurrent;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxListener<IBoxListener>, CIdentifier::undefined())
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \class CBoxAlgorithmROCCurveDesc
|
||||
* \author Serrière Guillaume (Inria)
|
||||
* \date Thu May 28 11:49:24 2015
|
||||
* \brief Descriptor of the box ROC curve.
|
||||
*
|
||||
*/
|
||||
class CBoxAlgorithmROCCurveDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("ROC curve"); }
|
||||
CString getAuthorName() const override { return CString("Serrière Guillaume"); }
|
||||
CString getAuthorCompanyName() const override { return CString("Inria"); }
|
||||
CString getShortDescription() const override { return CString("Compute the ROC curve for each class."); }
|
||||
CString getDetailedDescription() const override { return CString("The box computes the ROC curve for each class."); }
|
||||
CString getCategory() const override { return CString("Evaluation/Classification"); }
|
||||
CString getVersion() const override { return CString("0.1"); }
|
||||
CString getStockItemName() const override { return CString("gtk-yes"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_ROCCurve; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmROCCurve; }
|
||||
|
||||
IBoxListener* createBoxListener() const override { return new CBoxAlgorithmROCCurveListener; }
|
||||
void releaseBoxListener(IBoxListener* listener) const override { delete listener; }
|
||||
|
||||
bool hasFunctionality(const EPluginFunctionality functionality) const override { return functionality == EPluginFunctionality::Visualization; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Expected labels", OV_TypeId_Stimulations);
|
||||
prototype.addInput("Probability values", OV_TypeId_StreamedMatrix);
|
||||
|
||||
prototype.addSetting("Computation trigger", OV_TypeId_Stimulation, "OVTK_StimulationId_ExperimentStop");
|
||||
prototype.addSetting("Number of classes", OV_TypeId_Integer, "2");
|
||||
prototype.addSetting("Class 1 identifier", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_01");
|
||||
prototype.addSetting("Class 2 identifier", OV_TypeId_Stimulation, "OVTK_StimulationId_Label_02");
|
||||
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifySetting);
|
||||
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_ROCCurveDesc)
|
||||
};
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyGTK
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
#include "ovpCBoxAlgorithmStatisticGenerator.h"
|
||||
|
||||
#include <sstream>
|
||||
|
||||
#include <xml/IXMLHandler.h>
|
||||
#include <xml/IXMLNode.h>
|
||||
#include <limits>
|
||||
#include <iomanip>
|
||||
|
||||
namespace {
|
||||
const char* const STATISTIC_ROOT_NODE_NAME = "Statistic";
|
||||
const char* const STIMULATION_LIST_NODE_NAME = "Stimulations-list";
|
||||
const char* const STIMULATION_NODE_NAME = "Stimulation";
|
||||
const char* const IDENTIFIER_CODE_NODE_NAME = "Identifier";
|
||||
const char* const IDENTIFIER_LABEL_NODE_NAME = "Label";
|
||||
const char* const AMOUNT_NODE_NAME = "Count";
|
||||
|
||||
const char* const CHANNEL_LIST_NODE_NAME = "Channel-list";
|
||||
const char* const CHANNEL_NODE_NAME = "Channel";
|
||||
const char* const CHANNEL_LABEL_NODE_NAME = "Name";
|
||||
const char* const CHANNEL_MIN_NODE_NAME = "Minimum";
|
||||
const char* const CHANNEL_MAX_NODE_NAME = "Maximum";
|
||||
const char* const CHANNEL_MEAN_NODE_NAME = "Mean";
|
||||
} // namespace
|
||||
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
|
||||
bool CBoxAlgorithmStatisticGenerator::initialize()
|
||||
{
|
||||
m_signalDecoder.initialize(*this, 0);
|
||||
m_stimDecoder.initialize(*this, 1);
|
||||
|
||||
m_stimulations.clear();
|
||||
m_hasBeenStreamed = false;
|
||||
m_filename = FSettingValueAutoCast(*this->getBoxAlgorithmContext(), 0);
|
||||
|
||||
if (m_filename == CString(""))
|
||||
{
|
||||
this->getLogManager() << Kernel::LogLevel_Error << "The filename is empty\n";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoxAlgorithmStatisticGenerator::uninitialize()
|
||||
{
|
||||
bool res = true;
|
||||
|
||||
m_signalDecoder.uninitialize();
|
||||
m_stimDecoder.uninitialize();
|
||||
|
||||
if (m_hasBeenStreamed)
|
||||
{
|
||||
XML::IXMLNode* rootNode = XML::createNode(STATISTIC_ROOT_NODE_NAME);
|
||||
XML::IXMLNode* stimNode = XML::createNode(STIMULATION_LIST_NODE_NAME);
|
||||
for (const auto& s : m_stimulations)
|
||||
{
|
||||
XML::IXMLNode* node = XML::createNode(STIMULATION_NODE_NAME);
|
||||
XML::IXMLNode* idNode = XML::createNode(IDENTIFIER_CODE_NODE_NAME);
|
||||
XML::IXMLNode* labelNode = XML::createNode(IDENTIFIER_LABEL_NODE_NAME);
|
||||
XML::IXMLNode* amountNode = XML::createNode(AMOUNT_NODE_NAME);
|
||||
|
||||
CIdentifier id = s.first;
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(10) << m_stimulations[id];
|
||||
|
||||
idNode->setPCData(id.str().c_str());
|
||||
labelNode->setPCData(this->getTypeManager().getEnumerationEntryNameFromValue(OV_TypeId_Stimulation, id.id()).toASCIIString());
|
||||
amountNode->setPCData(ss.str().c_str());
|
||||
|
||||
node->addChild(idNode);
|
||||
node->addChild(labelNode);
|
||||
node->addChild(amountNode);
|
||||
stimNode->addChild(node);
|
||||
}
|
||||
rootNode->addChild(stimNode);
|
||||
|
||||
|
||||
XML::IXMLNode* channelsNode = XML::createNode(CHANNEL_LIST_NODE_NAME);
|
||||
for (size_t i = 0; i < m_signalInfos.size(); ++i)
|
||||
{
|
||||
signal_info_t& signalInfo = m_signalInfos[i];
|
||||
XML::IXMLNode* node = XML::createNode(CHANNEL_NODE_NAME);
|
||||
XML::IXMLNode* nodeName = XML::createNode(CHANNEL_LABEL_NODE_NAME);
|
||||
|
||||
nodeName->setPCData(signalInfo.name.toASCIIString());
|
||||
node->addChild(nodeName);
|
||||
node->addChild(getDoubleNode(CHANNEL_MAX_NODE_NAME, signalInfo.max));
|
||||
node->addChild(getDoubleNode(CHANNEL_MIN_NODE_NAME, signalInfo.min));
|
||||
node->addChild(getDoubleNode(CHANNEL_MEAN_NODE_NAME, signalInfo.sum / signalInfo.nSample));
|
||||
|
||||
channelsNode->addChild(node);
|
||||
}
|
||||
rootNode->addChild(channelsNode);
|
||||
|
||||
XML::IXMLHandler* handler = XML::createXMLHandler();
|
||||
if (!handler->writeXMLInFile(*rootNode, m_filename.toASCIIString())) { res = false; }
|
||||
|
||||
handler->release();
|
||||
rootNode->release();
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
bool CBoxAlgorithmStatisticGenerator::processInput(const size_t /*index*/)
|
||||
{
|
||||
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CBoxAlgorithmStatisticGenerator::process()
|
||||
{
|
||||
Kernel::IBoxIO& boxContext = this->getDynamicBoxContext();
|
||||
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(0); ++i)
|
||||
{
|
||||
m_signalDecoder.decode(i);
|
||||
if (m_signalDecoder.isHeaderReceived())
|
||||
{
|
||||
const size_t mountChannel = m_signalDecoder.getOutputMatrix()->getDimensionSize(0);
|
||||
m_hasBeenStreamed = true;
|
||||
for (size_t j = 0; j < mountChannel; ++j)
|
||||
{
|
||||
signal_info_t info = {
|
||||
m_signalDecoder.getOutputMatrix()->getDimensionLabel(0, j), std::numeric_limits<double>::max(), -std::numeric_limits<double>::max(), 0, 0
|
||||
};
|
||||
m_signalInfos.push_back(info);
|
||||
}
|
||||
}
|
||||
if (m_signalDecoder.isBufferReceived())
|
||||
{
|
||||
const size_t nSample = m_signalDecoder.getOutputMatrix()->getDimensionSize(1);
|
||||
double* buffer = m_signalDecoder.getOutputMatrix()->getBuffer();
|
||||
for (size_t j = 0; j < m_signalInfos.size(); ++j)
|
||||
{
|
||||
signal_info_t& info = m_signalInfos[j];
|
||||
for (size_t k = 0; k < nSample; ++k)
|
||||
{
|
||||
const double sample = buffer[j * nSample + k];
|
||||
info.sum += sample;
|
||||
|
||||
if (sample < info.min) { info.min = sample; }
|
||||
if (sample > info.max) { info.max = sample; }
|
||||
}
|
||||
info.nSample += nSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < boxContext.getInputChunkCount(1); ++i)
|
||||
{
|
||||
m_stimDecoder.decode(i);
|
||||
if (m_stimDecoder.isHeaderReceived()) { m_hasBeenStreamed = true; }
|
||||
if (m_stimDecoder.isBufferReceived())
|
||||
{
|
||||
IStimulationSet& stimSet = *(m_stimDecoder.getOutputStimulationSet());
|
||||
for (size_t j = 0; j < stimSet.getStimulationCount(); ++j) { m_stimulations[stimSet.getStimulationIdentifier(j)]++; }
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
XML::IXMLNode* CBoxAlgorithmStatisticGenerator::getDoubleNode(const char* const nodeName, const double value)
|
||||
{
|
||||
XML::IXMLNode* tmp = XML::createNode(nodeName);
|
||||
std::stringstream ss;
|
||||
ss << std::fixed << std::setprecision(10) << value;
|
||||
tmp->setPCData(ss.str().c_str());
|
||||
return tmp;
|
||||
}
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
#include "../ovp_defines.h"
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
typedef struct
|
||||
{
|
||||
CString name;
|
||||
double min;
|
||||
double max;
|
||||
double sum;
|
||||
size_t nSample;
|
||||
} signal_info_t;
|
||||
|
||||
/**
|
||||
* \class CBoxAlgorithmStatisticGenerator
|
||||
* \author Serrière Guillaume (Inria)
|
||||
* \date Thu Apr 30 15:24:39 2015
|
||||
* \brief The class CBoxAlgorithmStatisticGenerator describes the box Statistic generator.
|
||||
*
|
||||
*/
|
||||
class CBoxAlgorithmStatisticGenerator final : virtual public Toolkit::TBoxAlgorithm<IBoxAlgorithm>
|
||||
{
|
||||
public:
|
||||
void release() override { delete this; }
|
||||
|
||||
bool initialize() override;
|
||||
bool uninitialize() override;
|
||||
|
||||
bool processInput(const size_t index) override;
|
||||
bool process() override;
|
||||
|
||||
_IsDerivedFromClass_Final_(Toolkit::TBoxAlgorithm<IBoxAlgorithm>, OVP_ClassId_BoxAlgorithm_StatisticGenerator)
|
||||
|
||||
private:
|
||||
static XML::IXMLNode* getDoubleNode(const char* nodeName, double value);
|
||||
|
||||
// Input decoder:
|
||||
Toolkit::TSignalDecoder<CBoxAlgorithmStatisticGenerator> m_signalDecoder;
|
||||
Toolkit::TStimulationDecoder<CBoxAlgorithmStatisticGenerator> m_stimDecoder;
|
||||
|
||||
CString m_filename;
|
||||
std::map<CIdentifier, size_t> m_stimulations;
|
||||
std::vector<signal_info_t> m_signalInfos;
|
||||
|
||||
bool m_hasBeenStreamed = false;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* \class CBoxAlgorithmStatisticGeneratorDesc
|
||||
* \author Serrière Guillaume (Inria)
|
||||
* \date Thu Apr 30 15:24:39 2015
|
||||
* \brief Descriptor of the box Statistic generator.
|
||||
*
|
||||
*/
|
||||
class CBoxAlgorithmStatisticGeneratorDesc final : virtual public IBoxAlgorithmDesc
|
||||
{
|
||||
public:
|
||||
|
||||
void release() override { }
|
||||
|
||||
CString getName() const override { return CString("General statistics generator"); }
|
||||
CString getAuthorName() const override { return CString("Serrière Guillaume"); }
|
||||
CString getAuthorCompanyName() const override { return CString("Inria"); }
|
||||
CString getShortDescription() const override { return CString("Generate statistics on signal."); }
|
||||
|
||||
CString getDetailedDescription() const override { return CString("Generate some general purpose statistics on signal and store them in a file."); }
|
||||
|
||||
CString getCategory() const override { return CString("Evaluation"); }
|
||||
CString getVersion() const override { return CString("0.1"); }
|
||||
CString getStockItemName() const override { return CString("gtk-yes"); }
|
||||
|
||||
CIdentifier getCreatedClass() const override { return OVP_ClassId_BoxAlgorithm_StatisticGenerator; }
|
||||
IPluginObject* create() override { return new CBoxAlgorithmStatisticGenerator; }
|
||||
|
||||
bool getBoxPrototype(Kernel::IBoxProto& prototype) const override
|
||||
{
|
||||
prototype.addInput("Signal",OV_TypeId_Signal);
|
||||
prototype.addInput("Stimulations",OV_TypeId_Stimulations);
|
||||
|
||||
prototype.addSetting("Filename for saving",OV_TypeId_Filename, "${Path_UserData}/statistics-dump.xml");
|
||||
|
||||
prototype.addFlag(Kernel::BoxFlag_CanModifySetting);
|
||||
|
||||
prototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
_IsDerivedFromClass_Final_(IBoxAlgorithmDesc, OVP_ClassId_BoxAlgorithm_StatisticGeneratorDesc)
|
||||
};
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
+203
@@ -0,0 +1,203 @@
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include "ovpCROCCurveDraw.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
|
||||
static void size_allocate_cb(GtkWidget* /*widget*/, GdkRectangle* rectangle, gpointer data) { static_cast<CROCCurveDraw*>(data)->resizeEvent(rectangle); }
|
||||
static void area_expose_cb(GtkWidget* /*widget*/, GdkEventExpose* /*event*/, gpointer data) { static_cast<CROCCurveDraw*>(data)->exposeEnvent(); }
|
||||
|
||||
CROCCurveDraw::CROCCurveDraw(GtkNotebook* notebook, const size_t classIndex, CString& className)
|
||||
{
|
||||
m_margin = 50;
|
||||
m_classIdx = classIndex;
|
||||
m_hasBeenInit = false;
|
||||
m_hasBeenExposed = false;
|
||||
m_drawableArea = gtk_drawing_area_new();
|
||||
gtk_widget_set_size_request(m_drawableArea, 700, 600);
|
||||
|
||||
g_signal_connect(G_OBJECT(m_drawableArea), "expose_event", G_CALLBACK(area_expose_cb), this);
|
||||
g_signal_connect(G_OBJECT(m_drawableArea), "size-allocate", G_CALLBACK(size_allocate_cb), this);
|
||||
|
||||
GtkWidget* label = gtk_label_new(className.toASCIIString());
|
||||
gtk_notebook_append_page(notebook, m_drawableArea, label);
|
||||
|
||||
|
||||
//get left ruler widget's font description
|
||||
PangoContext* ctx = gtk_widget_get_pango_context(m_drawableArea);
|
||||
PangoFontDescription* fontDesc = pango_context_get_font_description(ctx);
|
||||
|
||||
//adapt the allocated height per label to the font's height (plus 4 pixel to add some spacing)
|
||||
if (pango_font_description_get_size_is_absolute(fontDesc)) { m_pixelsPerLeftRulerLabel = pango_font_description_get_size(fontDesc) + 4; }
|
||||
else { m_pixelsPerLeftRulerLabel = pango_font_description_get_size(fontDesc) / PANGO_SCALE + 4; }
|
||||
}
|
||||
|
||||
void CROCCurveDraw::generateCurve()
|
||||
{
|
||||
GtkAllocation allocation;
|
||||
gtk_widget_get_allocation(m_drawableArea, &allocation);
|
||||
|
||||
const size_t width = allocation.width - 2 * m_margin;
|
||||
const size_t height = allocation.height - 2 * m_margin;
|
||||
|
||||
m_pointList.clear();
|
||||
for (size_t i = 0; i < m_coordinateList.size(); ++i)
|
||||
{
|
||||
GdkPoint point;
|
||||
point.x = gint(m_coordinateList[i].first * width + m_margin);
|
||||
point.y = gint((allocation.height - m_margin) - m_coordinateList[i].second * height);
|
||||
m_pointList.push_back(point);
|
||||
}
|
||||
m_hasBeenInit = true;
|
||||
}
|
||||
|
||||
void CROCCurveDraw::exposeEnvent()
|
||||
{
|
||||
m_hasBeenExposed = true;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CROCCurveDraw::resizeEvent(GdkRectangle* /*rectangle*/)
|
||||
{
|
||||
GtkAllocation alloc;
|
||||
gtk_widget_get_allocation(m_drawableArea, &alloc);
|
||||
|
||||
if (!m_hasBeenInit) { return; }
|
||||
|
||||
generateCurve();
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CROCCurveDraw::redraw()
|
||||
{
|
||||
if (!m_hasBeenInit || !m_hasBeenExposed) { return; }
|
||||
|
||||
GtkAllocation allocation;
|
||||
gtk_widget_get_allocation(m_drawableArea, &allocation);
|
||||
|
||||
gdk_draw_rectangle(m_drawableArea->window, GTK_WIDGET(m_drawableArea)->style->white_gc, TRUE, 0, 0, allocation.width, allocation.height);
|
||||
|
||||
|
||||
GdkColor lineColor = { 0, 35000, 35000, 35000 };
|
||||
GdkGC* gc = gdk_gc_new((m_drawableArea)->window);
|
||||
gdk_gc_set_rgb_fg_color(gc, &lineColor);
|
||||
|
||||
|
||||
//Left ruler
|
||||
gdk_draw_line((m_drawableArea)->window, gc, gint(m_margin), gint(m_margin), gint(m_margin), gint(allocation.height - m_margin));
|
||||
drawLeftMark(m_margin, m_margin, "1");
|
||||
drawLeftMark(m_margin, allocation.height / 2, "0.5");
|
||||
drawLeftMark(m_margin, allocation.height - m_margin, "0");
|
||||
|
||||
//*** Black magic section to rotate the text of the left ruler. The solution comes from the internet (gtk doc), it works so
|
||||
// don't touch it unless you are sure of what you are doing
|
||||
PangoContext* context = gtk_widget_get_pango_context(m_drawableArea);
|
||||
GdkScreen* screen = gdk_drawable_get_screen(m_drawableArea->window);
|
||||
PangoRenderer* renderer = gdk_pango_renderer_get_default(screen);
|
||||
gdk_pango_renderer_set_drawable(GDK_PANGO_RENDERER(renderer), m_drawableArea->window);
|
||||
GdkGC* rotationGc = gdk_gc_new(m_drawableArea->window);
|
||||
gdk_pango_renderer_set_gc(GDK_PANGO_RENDERER(renderer), rotationGc);
|
||||
int width, height;
|
||||
PangoMatrix matrix = PANGO_MATRIX_INIT;
|
||||
pango_matrix_translate(&matrix, 0, double(allocation.height + 100) / 2);
|
||||
PangoLayout* layout = pango_layout_new(context);
|
||||
pango_layout_set_text(layout, "True Positive Rate", -1);
|
||||
PangoFontDescription* desc = pango_context_get_font_description(context);
|
||||
pango_layout_set_font_description(layout, desc);
|
||||
GdkColor color = { 0, 0, 0, 0 };
|
||||
gdk_pango_renderer_set_override_color(GDK_PANGO_RENDERER(renderer), PANGO_RENDER_PART_FOREGROUND, &color);
|
||||
|
||||
pango_matrix_rotate(&matrix, 90);
|
||||
pango_context_set_matrix(context, &matrix);
|
||||
pango_layout_context_changed(layout);
|
||||
pango_layout_get_size(layout, &width, &height);
|
||||
pango_renderer_draw_layout(renderer, layout, 15, (allocation.height + height) / 2);
|
||||
|
||||
gdk_pango_renderer_set_override_color(GDK_PANGO_RENDERER(renderer), PANGO_RENDER_PART_FOREGROUND, nullptr);
|
||||
gdk_pango_renderer_set_drawable(GDK_PANGO_RENDERER(renderer), nullptr);
|
||||
gdk_pango_renderer_set_gc(GDK_PANGO_RENDERER(renderer), nullptr);
|
||||
|
||||
pango_matrix_rotate(&matrix, -90);
|
||||
pango_context_set_matrix(context, &matrix);
|
||||
pango_layout_context_changed(layout);
|
||||
|
||||
g_object_unref(layout);
|
||||
g_object_unref(context);
|
||||
g_object_unref(rotationGc);
|
||||
//** End of black magic section
|
||||
|
||||
//Bottom ruler
|
||||
gdk_draw_line((m_drawableArea)->window, gc, gint(m_margin), gint(allocation.height - m_margin), gint(allocation.width - m_margin),
|
||||
gint(allocation.height - m_margin));
|
||||
drawBottomMark(m_margin, allocation.height - m_margin, "0");
|
||||
drawBottomMark(allocation.width / 2, allocation.height - m_margin, "0.5");
|
||||
drawBottomMark(allocation.width - m_margin, allocation.height - m_margin, "1");
|
||||
|
||||
int textW;
|
||||
int textH;
|
||||
PangoLayout* text = gtk_widget_create_pango_layout(m_drawableArea, "False positive rate");
|
||||
pango_layout_set_justify(text, PANGO_ALIGN_CENTER);
|
||||
pango_layout_get_pixel_size(text, &textW, &textH);
|
||||
gdk_draw_layout(m_drawableArea->window, GTK_WIDGET(m_drawableArea)->style->black_gc, allocation.width / 2 - textW / 2, allocation.height - 15, text);
|
||||
g_object_unref(text);
|
||||
|
||||
|
||||
if (m_pointList.empty())
|
||||
{
|
||||
gdk_draw_lines((m_drawableArea)->window, GTK_WIDGET(m_drawableArea)->style->black_gc, &(m_pointList[0]), gint(m_pointList.size()));
|
||||
}
|
||||
|
||||
gdk_gc_set_line_attributes(gc, 1, GDK_LINE_ON_OFF_DASH, GDK_CAP_BUTT, GDK_JOIN_BEVEL);
|
||||
gdk_draw_line((m_drawableArea)->window, gc, gint(m_margin), gint(allocation.height - m_margin), gint(allocation.width - m_margin), gint(m_margin));
|
||||
|
||||
g_object_unref(gc);
|
||||
}
|
||||
|
||||
void CROCCurveDraw::drawLeftMark(const size_t w, const size_t h, const char* label) const
|
||||
{
|
||||
gint textW;
|
||||
gint textH;
|
||||
PangoLayout* text = gtk_widget_create_pango_layout(m_drawableArea, label);
|
||||
pango_layout_set_width(text, 28);
|
||||
pango_layout_set_justify(text, PANGO_ALIGN_LEFT);
|
||||
|
||||
pango_layout_get_pixel_size(text, &textW, &textH);
|
||||
|
||||
gdk_draw_layout(m_drawableArea->window, GTK_WIDGET(m_drawableArea)->style->black_gc, gint(w - 20) - (textW / 2), gint(h) - (textH / 2), text);
|
||||
|
||||
GdkColor lineColor = { 0, 35000, 35000, 35000 };
|
||||
GdkGC* gc = gdk_gc_new((m_drawableArea)->window);
|
||||
gdk_gc_set_rgb_fg_color(gc, &lineColor);
|
||||
gdk_draw_line(m_drawableArea->window, gc, w - 5, h, w, h);
|
||||
|
||||
g_object_unref(gc);
|
||||
}
|
||||
|
||||
void CROCCurveDraw::drawBottomMark(const size_t w, const size_t h, const char* label) const
|
||||
{
|
||||
int textW;
|
||||
int textH;
|
||||
PangoLayout* text = gtk_widget_create_pango_layout(m_drawableArea, label);
|
||||
pango_layout_set_width(text, 28);
|
||||
pango_layout_set_justify(text, PANGO_ALIGN_LEFT);
|
||||
|
||||
pango_layout_get_pixel_size(text, &textW, &textH);
|
||||
|
||||
gdk_draw_layout(m_drawableArea->window, GTK_WIDGET(m_drawableArea)->style->black_gc, gint(w) - (textW / 2), gint(h + 14), text);
|
||||
|
||||
GdkColor lineColor = { 0, 35000, 35000, 35000 };
|
||||
GdkGC* gc = gdk_gc_new((m_drawableArea)->window);
|
||||
gdk_gc_set_rgb_fg_color(gc, &lineColor);
|
||||
gdk_draw_line(m_drawableArea->window, gc, gint(w), gint(h + 5), gint(w), gint(h));
|
||||
|
||||
g_object_unref(gc);
|
||||
}
|
||||
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
#endif // TARGET_HAS_ThirdPartyGTK
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
#pragma once
|
||||
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
|
||||
#include <openvibe/ov_all.h>
|
||||
#include <toolkit/ovtk_all.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
#include <vector>
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
typedef std::pair<double, double> CCoordinate;
|
||||
|
||||
//The aim of the class is to handle the graphical part of a RocCurve
|
||||
class CROCCurveDraw final
|
||||
{
|
||||
public:
|
||||
CROCCurveDraw(GtkNotebook* notebook, size_t classIndex, CString& className);
|
||||
~CROCCurveDraw() { }
|
||||
std::vector<CCoordinate>& getCoordinateVector() { return m_coordinateList; }
|
||||
|
||||
void generateCurve();
|
||||
|
||||
//Callbak functions, should not be called
|
||||
void resizeEvent(GdkRectangle* rectangle);
|
||||
void exposeEnvent();
|
||||
|
||||
//This function is called when the cruve should be redraw for an external reason
|
||||
void forceRedraw() { redraw(); }
|
||||
|
||||
private:
|
||||
size_t m_margin = 0;
|
||||
size_t m_classIdx = 0;
|
||||
std::vector<GdkPoint> m_pointList;
|
||||
std::vector<CCoordinate> m_coordinateList;
|
||||
size_t m_pixelsPerLeftRulerLabel = 0;
|
||||
|
||||
GtkWidget* m_drawableArea = nullptr;
|
||||
bool m_hasBeenInit = false;
|
||||
|
||||
//For a mytical reason, gtk says that the DrawableArea is not a DrawableArea unless it's been exposed at least once...
|
||||
// So we need to if the DrawableArea as been exposed
|
||||
bool m_hasBeenExposed = false;
|
||||
|
||||
void redraw();
|
||||
void drawLeftMark(size_t w, size_t h, const char* label) const;
|
||||
void drawBottomMark(size_t w, size_t h, const char* label) const;
|
||||
};
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
|
||||
|
||||
#endif // TARGET_HAS_ThirdPartyGTK
|
||||
@@ -0,0 +1,40 @@
|
||||
#pragma once
|
||||
|
||||
// Boxes
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#define OVP_ClassId_BoxAlgorithm_ClassifierAccuracyMeasure OpenViBE::CIdentifier(0x48395CE7, 0x17D62550)
|
||||
#define OVP_ClassId_BoxAlgorithm_ClassifierAccuracyMeasureDesc OpenViBE::CIdentifier(0x067F38CC, 0x084A6ED3)
|
||||
#define OVP_ClassId_Algorithm_ConfusionMatrix OpenViBE::CIdentifier(0x699F416B, 0x3BAE4324)
|
||||
#define OVP_ClassId_Algorithm_ConfusionMatrixDesc OpenViBE::CIdentifier(0x4CDD225D, 0x6C9A59DB)
|
||||
#define OVP_ClassId_BoxAlgorithm_ConfusionMatrix OpenViBE::CIdentifier(0x1AB625DA, 0x3B2502CE)
|
||||
#define OVP_ClassId_BoxAlgorithm_ConfusionMatrixDesc OpenViBE::CIdentifier(0x52237A64, 0x63555613)
|
||||
#define OVP_ClassId_BoxAlgorithm_KappaCoef OpenViBE::CIdentifier(0x160D8F1B, 0xD864C5BB)
|
||||
#define OVP_ClassId_BoxAlgorithm_KappaCoefDesc OpenViBE::CIdentifier(0xD8BA2199, 0xD252BECB)
|
||||
#define OVP_ClassId_BoxAlgorithm_ROCCurve OpenViBE::CIdentifier(0x06FE5B1B, 0xDE066FEC)
|
||||
#define OVP_ClassId_BoxAlgorithm_ROCCurveDesc OpenViBE::CIdentifier(0xCB5DFCEA, 0xAF41EAB2)
|
||||
#define OVP_ClassId_BoxAlgorithm_StatisticGenerator OpenViBE::CIdentifier(0x83EDA40B, 0x425FBFFE)
|
||||
#define OVP_ClassId_BoxAlgorithm_StatisticGeneratorDesc OpenViBE::CIdentifier(0x35A0CB63, 0x78882C28)
|
||||
|
||||
// Global defines
|
||||
//---------------------------------------------------------------------------------------------------
|
||||
#ifdef TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
#include "ovp_global_defines.h"
|
||||
#endif // TARGET_HAS_ThirdPartyOpenViBEPluginsGlobalDefines
|
||||
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Sums OpenViBE::CIdentifier(0x75502E8E, 0x05D838EE)
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_Percentage OpenViBE::CIdentifier(0x7E504E8E, 0x058858EE)
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_TargetStimulationSet OpenViBE::CIdentifier(0x7E504E8F, 0x058858EF)
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassifierStimulationSet OpenViBE::CIdentifier(0x45220B61, 0x13FD7491)
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_InputParameterId_ClassCodes OpenViBE::CIdentifier(0x67780C91, 0x2A556C51)
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_OutputParameterId_ConfusionMatrix OpenViBE::CIdentifier(0x67780C91, 0x2A556C51)
|
||||
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetTarget OpenViBE::CIdentifier(0x4D390BDA, 0x6A180667)
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_ResetClassifier OpenViBE::CIdentifier(0x3C132C38, 0x557D2503)
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedTarget OpenViBE::CIdentifier(0x6B1E76B3, 0x06741B21)
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_InputTriggerId_FeedClassifier OpenViBE::CIdentifier(0x3EFC64B8, 0x5ACC3125)
|
||||
#define OVP_Algorithm_ConfusionMatrixAlgorithm_OutputTriggerId_ConfusionPerformed OpenViBE::CIdentifier(0x790C2277, 0x3D041A63)
|
||||
|
||||
|
||||
#define FIRST_CLASS_SETTING_INDEX 2
|
||||
|
||||
#define OV_AttributeId_Box_FlagIsUnstable OpenViBE::CIdentifier(0x666FFFFF, 0x666FFFFF)
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
#include "ovp_defines.h"
|
||||
|
||||
#include "box-algorithms/ovpCBoxAlgorithmStatisticGenerator.h"
|
||||
#include "box-algorithms/ovpCBoxAlgorithmKappaCoefficient.h"
|
||||
#include "box-algorithms/ovpCBoxAlgorithmConfusionMatrix.h"
|
||||
#include "box-algorithms/ovpCBoxAlgorithmROCCurve.h"
|
||||
#include "box-algorithms/ovpCBoxAlgorithmClassifierAccuracyMeasure.h"
|
||||
|
||||
#include "algorithms/ovpCAlgorithmConfusionMatrix.h"
|
||||
|
||||
namespace OpenViBE {
|
||||
namespace Plugins {
|
||||
namespace Evaluation {
|
||||
|
||||
OVP_Declare_Begin()
|
||||
context.getTypeManager().registerEnumerationEntry(OV_TypeId_BoxAlgorithmFlag, OV_AttributeId_Box_FlagIsUnstable.toString(),
|
||||
OV_AttributeId_Box_FlagIsUnstable.id());
|
||||
|
||||
OVP_Declare_New(CBoxAlgorithmStatisticGeneratorDesc);
|
||||
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
OVP_Declare_New(CBoxAlgorithmKappaCoefDesc);
|
||||
OVP_Declare_New(CBoxAlgorithmROCCurveDesc);
|
||||
#endif
|
||||
|
||||
OVP_Declare_New(CAlgorithmConfusionMatrixDesc);
|
||||
OVP_Declare_New(CBoxAlgorithmConfusionMatrixDesc);
|
||||
#if defined(TARGET_HAS_ThirdPartyGTK)
|
||||
OVP_Declare_New(CBoxAlgorithmClassifierAccuracyMeasureDesc);
|
||||
#endif
|
||||
OVP_Declare_End()
|
||||
|
||||
} // namespace Evaluation
|
||||
} // namespace Plugins
|
||||
} // namespace OpenViBE
|
||||
@@ -0,0 +1,25 @@
|
||||
PROJECT(test_evaluation)
|
||||
|
||||
IF(WIN32)
|
||||
ADD_DEFINITIONS(-DTARGET_OS_Windows)
|
||||
ENDIF(WIN32)
|
||||
IF(UNIX)
|
||||
ADD_DEFINITIONS(-DTARGET_OS_Linux)
|
||||
ENDIF(UNIX)
|
||||
ADD_DEFINITIONS(-D_CRT_SECURE_NO_DEPRECATE)
|
||||
ADD_DEFINITIONS(-DTARGET_ARCHITECTURE_i386)
|
||||
|
||||
INCLUDE_DIRECTORIES(../src)
|
||||
ADD_EXECUTABLE(${PROJECT_NAME} test_kappa.cpp)
|
||||
SET_PROPERTY(TARGET ${PROJECT_NAME} PROPERTY FOLDER ${TESTS_FOLDER}) # Place project in folder unit-test (for some IDE)
|
||||
|
||||
#INCLUDE("FindOpenViBE")
|
||||
|
||||
# Unfortunately we need to install the tests as any application to find .dll/.so files
|
||||
# on both Windows and Linux.
|
||||
OV_INSTALL_LAUNCH_SCRIPT(SCRIPT_PREFIX "${PROJECT_NAME}" EXECUTABLE_NAME "${PROJECT_NAME}")
|
||||
INSTALL(TARGETS ${PROJECT_NAME}
|
||||
RUNTIME DESTINATION ${DIST_BINDIR}
|
||||
LIBRARY DESTINATION ${DIST_LIBDIR}
|
||||
ARCHIVE DESTINATION ${DIST_LIBDIR})
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
#blabla
|
||||
|
||||
# @FIXME there is a problem of using the global log, this will cause interference if any tests are run in parallel
|
||||
|
||||
IF(WIN32)
|
||||
SET(EXT cmd)
|
||||
SET(OS_FLAGS "--no-pause")
|
||||
ELSE(WIN32)
|
||||
SET(EXT sh)
|
||||
SET(OS_FLAGS "")
|
||||
ENDIF(WIN32)
|
||||
|
||||
ADD_TEST(clean_Evaluation_kappa "${CMAKE_COMMAND}" "-E" "remove" "-f" ${OV_LOGFILE})
|
||||
ADD_TEST(run_Evaluation_kappa "$ENV{OV_BINARY_PATH}/openvibe-designer.${EXT}" ${OS_FLAGS} "--invisible" "--no-session-management" --define Plugin_Classification_RandomizeKFoldTestData true "--play-fast" Test-kappa.xml)
|
||||
#ADD_TEST(compare_Evaluation_kappa "$ENV{OV_BINARY_PATH}/test_evaluation.${EXT}" "${OS_FLAGS}" "${OV_LOGFILE}")
|
||||
|
||||
# It would be better to clean last, but we can't do this as it will delete the
|
||||
# output we wish to include, and we can't prevent clean from running if a prev. test fails
|
||||
# We need the clean to be sure that the comparator stage is not getting data from a previous run.
|
||||
SET_TESTS_PROPERTIES(run_Evaluation_kappa PROPERTIES DEPENDS clean_Evaluation_kappa)
|
||||
SET_TESTS_PROPERTIES(run_Evaluation_kappa PROPERTIES ATTACHED_FILES_ON_FAIL ${OV_LOGFILE})
|
||||
|
||||
#SET_TESTS_PROPERTIES(compare_Evaluation_kappa PROPERTIES DEPENDS run_Evaluation_kappa)
|
||||
#SET_TESTS_PROPERTIES(compare_Evaluation_kappa PROPERTIES ATTACHED_FILES_ON_FAIL ${OV_LOGFILE})
|
||||
|
||||
|
||||
ADD_TEST(run_Evaluation_statistic_generator "$ENV{OV_BINARY_PATH}/openvibe-designer.${EXT}" ${OS_FLAGS} "--invisible" "--no-session-management" --define Plugin_Classification_RandomizeKFoldTestData true "--play-fast" Test-StatisticGenerator.xml)
|
||||
ADD_TEST(compare_Evaluation_statistic_generator "git" "diff" "--no-index" "--ignore-space-change" "stat.xml" "data/Statistic_comparison.xml")
|
||||
ADD_TEST(clean_Evaluation_statistic_generator "${CMAKE_COMMAND}" "-E" "remove" "-f" stat.xml)
|
||||
|
||||
|
||||
SET_TESTS_PROPERTIES(compare_Evaluation_statistic_generator PROPERTIES DEPENDS run_Evaluation_statistic_generator)
|
||||
SET_TESTS_PROPERTIES(compare_Evaluation_statistic_generator PROPERTIES ATTACHED_FILES_ON_FAIL ${OV_LOGFILE})
|
||||
|
||||
### Do not enable the commented out sikuli tests unless you
|
||||
### or your lab commits to keep them passing in the long term.
|
||||
#FIND_PROGRAM(SIKULI NAMES sikuli-ide)
|
||||
#IF(SIKULI)
|
||||
# IF(UNIX)
|
||||
# ADD_TEST(sikuli_clean_Evaluation_ROC "${CMAKE_COMMAND}" "-E" "remove" "-f" ${OV_LOGFILE} screenshot.png)
|
||||
# ADD_TEST(sikuli_run_Evaluation_ROC "${SIKULI}" -t testROCCurve.UNIX.sikuli)
|
||||
#
|
||||
# SET_TESTS_PROPERTIES(sikuli_run_Evaluation_ROC PROPERTIES DEPENDS sikuli_clean_Evaluation_ROC)
|
||||
# SET_TESTS_PROPERTIES(sikuli_run_Evaluation_ROC PROPERTIES ATTACHED_FILES_ON_FAIL ${OV_LOGFILE})
|
||||
# SET_TESTS_PROPERTIES(sikuli_run_Evaluation_ROC PROPERTIES ATTACHED_FILES_ON_FAIL ${CTEST_SOURCE_DIRECTORY}/plugins/processing/evaluation/test/screenshot.png)
|
||||
# ENDIF(UNIX)
|
||||
#ENDIF(SIKULI)
|
||||
|
||||
+451
@@ -0,0 +1,451 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>1</FormatVersion>
|
||||
<Creator>openvibe</Creator>
|
||||
<CreatorVersion>2.0</CreatorVersion>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x29c00b5a, 0x38e642d5)</Identifier>
|
||||
<Name>General statistics generator</Name>
|
||||
<AlgorithmClassIdentifier>(0x83eda40b, 0x425fbffe)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Signal</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename for saving</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>${__volatile_ScenarioDir}/stat.xml</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>240.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>43</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>512.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xf6674389, 0x42f4fe25)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>190</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002abac0)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc67a01dc, 0x28ce06c1)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf191c1c8, 0xa0123976)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x2b584b95, 0x7008d0de)</Identifier>
|
||||
<Name>Player Controller</Name>
|
||||
<AlgorithmClassIdentifier>(0x5f426dce, 0x08456e13)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation name</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xcc14d8d6, 0xf27ecb73)</TypeIdentifier>
|
||||
<Name>Action to perform</Name>
|
||||
<DefaultValue>Pause</DefaultValue>
|
||||
<Value>Stop</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>256.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>800.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x568d148e, 0x650792b3)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>118</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x0012be4a)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x2b907080, 0x224d7576)</Identifier>
|
||||
<Name>Sinus oscillator</Name>
|
||||
<AlgorithmClassIdentifier>(0x7e33bdb8, 0x68194a4a)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x5ba36127, 0x195feae1)</TypeIdentifier>
|
||||
<Name>Generated signal</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Channel count</Name>
|
||||
<DefaultValue>4</DefaultValue>
|
||||
<Value>4</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Sampling frequency</Name>
|
||||
<DefaultValue>512</DefaultValue>
|
||||
<Value>512</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Generated epoch sample count</Name>
|
||||
<DefaultValue>32</DefaultValue>
|
||||
<Value>32</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>128.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>432.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x0b214ed8, 0x1f9ad83a)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>109</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x002cf528)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x592038f7, 0x3646c9fe)</Identifier>
|
||||
<Name>Clock stimulator</Name>
|
||||
<AlgorithmClassIdentifier>(0x4f756d3f, 0x29ff0b96)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Generated stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x512a166f, 0x5c3ef83f)</TypeIdentifier>
|
||||
<Name>Interstimulation interval (in sec)</Name>
|
||||
<DefaultValue>1.0</DefaultValue>
|
||||
<Value>0.2</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>126.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>23</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>608.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x27b3ee3c, 0xc50527e6)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>114</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x0020b3d0)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x625d022b, 0x4c72dfaa)</Identifier>
|
||||
<Name>Timeout</Name>
|
||||
<AlgorithmClassIdentifier>(0x24fcd292, 0x5c8f6aa8)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Input Stream</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output Stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Timeout delay</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>100</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Output Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>160.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa963f5, 0x1a638cd4)</Identifier>
|
||||
<Value>33</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>800.000000</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x1eaee00e, 0xdb05d34e)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xad100179, 0xa3c984ab)</Identifier>
|
||||
<Value>62</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x0011d368)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x0ff86487, 0x6c18ccc2)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x592038f7, 0x3646c9fe)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x29c00b5a, 0x38e642d5)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>144</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>608</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>214</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>519</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x6299b60b, 0x63373c3e)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x625d022b, 0x4c72dfaa)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x2b584b95, 0x7008d0de)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>183</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>800</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>240</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>800</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x7ed28c93, 0x1209a735)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x2b907080, 0x224d7576)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x29c00b5a, 0x38e642d5)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1b32c44c, 0x1905e0e9)</Identifier>
|
||||
<Value>146</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x358ae8b5, 0x0f8bacd1)</Identifier>
|
||||
<Value>432</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x3f0a3b27, 0x570913d2)</Identifier>
|
||||
<Value>214</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x6267b5c5, 0x676e3e42)</Identifier>
|
||||
<Value>504</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments></Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x1586c3d8, 0x35a029ef)","index":0,"name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":480},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x4cfffb67, 0x1d6c7d8c)","index":0,"name":"Default tab","parentIdentifier":"(0x1586c3d8, 0x35a029ef)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x3e00f59d, 0x6e47aad3)","index":0,"name":"Empty","parentIdentifier":"(0x4cfffb67, 0x1d6c7d8c)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+434
@@ -0,0 +1,434 @@
|
||||
<OpenViBE-Scenario>
|
||||
<FormatVersion>2</FormatVersion>
|
||||
<Creator>OpenViBE Designer</Creator>
|
||||
<CreatorVersion>2.2.0</CreatorVersion>
|
||||
<Settings></Settings>
|
||||
<Inputs></Inputs>
|
||||
<Outputs></Outputs>
|
||||
<Boxes>
|
||||
<Box>
|
||||
<Identifier>(0x00001d5f, 0x00007a11)</Identifier>
|
||||
<Name>Expected</Name>
|
||||
<AlgorithmClassIdentifier>(0x336a3d9a, 0x753f1ba4)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Output stream</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output stimulation</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>${Player_ScenarioDirectory}/data/Expected_stimulation.csv</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>192</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>432</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xa9cdc629, 0xb153eb33)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x00001d5f, 0x00007a12)</Identifier>
|
||||
<Name>Found</Name>
|
||||
<AlgorithmClassIdentifier>(0x336a3d9a, 0x753f1ba4)</AlgorithmClassIdentifier>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Output stream</Name>
|
||||
</Output>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output stimulation</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x330306dd, 0x74a95f98)</TypeIdentifier>
|
||||
<Name>Filename</Name>
|
||||
<DefaultValue></DefaultValue>
|
||||
<Value>${Player_ScenarioDirectory}/data/Found_stimulation.csv</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>160</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>560</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x30a4e5c9, 0x83502953)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xa9cdc629, 0xb153eb33)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x0000555d, 0x00004472)</Identifier>
|
||||
<Name>Stimulation listener</Name>
|
||||
<AlgorithmClassIdentifier>(0x65731e1d, 0x47de5276)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulation stream 1</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xa88b3667, 0x0871638c)</TypeIdentifier>
|
||||
<Name>Log level to use</Name>
|
||||
<DefaultValue>Information</DefaultValue>
|
||||
<Value>Information</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>272</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>640</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0xf451ad91, 0x14c75f86)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xfba64161, 0x65304e21)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x107f1920, 0x151fda5f)</Identifier>
|
||||
<Name>Player Controller</Name>
|
||||
<AlgorithmClassIdentifier>(0x5f426dce, 0x08456e13)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation name</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0xcc14d8d6, 0xf27ecb73)</TypeIdentifier>
|
||||
<Name>Action to perform</Name>
|
||||
<DefaultValue>Pause</DefaultValue>
|
||||
<Value>Stop</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>336</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>368</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x568d148e, 0x650792b3)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x006cdafc)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x2cc3b99b, 0x2d88ee53)</Identifier>
|
||||
<Name>Kappa coefficient</Name>
|
||||
<AlgorithmClassIdentifier>(0x160d8f1b, 0xd864c5bb)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Expected stimulations</Name>
|
||||
</Input>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Found stimulations</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Confusion Matrix</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Amount of class</Name>
|
||||
<DefaultValue>2</DefaultValue>
|
||||
<Value>3</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation of class 1</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Number_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation of class 2</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Number_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_01</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Stimulation of class 3</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Number_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_02</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>272</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>480</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x08859f27, 0x4f7b5879)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x017d49da)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>3</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xf191c1c8, 0xa0123976)</Identifier>
|
||||
<Value></Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
<Box>
|
||||
<Identifier>(0x5bdbea30, 0x7c64f6a8)</Identifier>
|
||||
<Name>Timeout</Name>
|
||||
<AlgorithmClassIdentifier>(0x24fcd292, 0x5c8f6aa8)</AlgorithmClassIdentifier>
|
||||
<Inputs>
|
||||
<Input>
|
||||
<TypeIdentifier>(0x544a003e, 0x6dcba5f6)</TypeIdentifier>
|
||||
<Name>Input Stream</Name>
|
||||
</Input>
|
||||
</Inputs>
|
||||
<Outputs>
|
||||
<Output>
|
||||
<TypeIdentifier>(0x6f752dd0, 0x082a321e)</TypeIdentifier>
|
||||
<Name>Output Stimulations</Name>
|
||||
</Output>
|
||||
</Outputs>
|
||||
<Settings>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x007deef9, 0x2f3e95c6)</TypeIdentifier>
|
||||
<Name>Timeout delay</Name>
|
||||
<DefaultValue>5</DefaultValue>
|
||||
<Value>1</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
<Setting>
|
||||
<TypeIdentifier>(0x2c132d6e, 0x44ab0d97)</TypeIdentifier>
|
||||
<Name>Output Stimulation</Name>
|
||||
<DefaultValue>OVTK_StimulationId_Label_00</DefaultValue>
|
||||
<Value>OVTK_StimulationId_Label_00</Value>
|
||||
<Modifiability>false</Modifiability>
|
||||
</Setting>
|
||||
</Settings>
|
||||
<Attributes>
|
||||
<Attribute>
|
||||
<Identifier>(0x1fa7a38f, 0x54edbe0b)</Identifier>
|
||||
<Value>272</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x207c9054, 0x3c841b63)</Identifier>
|
||||
<Value>368</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0x4e7b798a, 0x183beafb)</Identifier>
|
||||
<Value>(0x1eaee00e, 0xdb05d34e)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc46b3d00, 0x3e0454e1)</Identifier>
|
||||
<Value>(0x00000000, 0x02337a82)</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc73e83ec, 0xf855c5bc)</Identifier>
|
||||
<Value>false</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xc80ce8af, 0xf699f813)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xce18836a, 0x9c0eb403)</Identifier>
|
||||
<Value>2</Value>
|
||||
</Attribute>
|
||||
<Attribute>
|
||||
<Identifier>(0xcfad85b0, 0x7c6d841c)</Identifier>
|
||||
<Value>1</Value>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Box>
|
||||
</Boxes>
|
||||
<Links>
|
||||
<Link>
|
||||
<Identifier>(0x00001201, 0x00006cc6)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001d5f, 0x00007a12)</BoxIdentifier>
|
||||
<BoxOutputIndex>1</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x0000555d, 0x00004472)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00004a37, 0x00005687)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001d5f, 0x00007a12)</BoxIdentifier>
|
||||
<BoxOutputIndex>1</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x2cc3b99b, 0x2d88ee53)</BoxIdentifier>
|
||||
<BoxInputIndex>1</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00004cd4, 0x00001a75)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001d5f, 0x00007a11)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x5bdbea30, 0x7c64f6a8)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x00005a6a, 0x000006b5)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x00001d5f, 0x00007a11)</BoxIdentifier>
|
||||
<BoxOutputIndex>1</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x2cc3b99b, 0x2d88ee53)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
<Link>
|
||||
<Identifier>(0x49781978, 0x10193d32)</Identifier>
|
||||
<Source>
|
||||
<BoxIdentifier>(0x5bdbea30, 0x7c64f6a8)</BoxIdentifier>
|
||||
<BoxOutputIndex>0</BoxOutputIndex>
|
||||
</Source>
|
||||
<Target>
|
||||
<BoxIdentifier>(0x107f1920, 0x151fda5f)</BoxIdentifier>
|
||||
<BoxInputIndex>0</BoxInputIndex>
|
||||
</Target>
|
||||
</Link>
|
||||
</Links>
|
||||
<Comments></Comments>
|
||||
<Metadata>
|
||||
<Entry>
|
||||
<Identifier>(0x0000775c, 0x000078ff)</Identifier>
|
||||
<Type>(0x3bcce5d2, 0x43f2d968)</Type>
|
||||
<Data>[{"boxIdentifier":"(0x2cc3b99b, 0x2d88ee53)","childCount":0,"identifier":"(0x086c5aaa, 0x55baf27b)","parentIdentifier":"(0xffffffff, 0xffffffff)","type":3},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"height":320,"identifier":"(0x2f9f0580, 0x412699f4)","name":"Default window","parentIdentifier":"(0xffffffff, 0xffffffff)","type":1,"width":480},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":1,"identifier":"(0x010246fe, 0x0eacec10)","index":0,"name":"Default tab","parentIdentifier":"(0x2f9f0580, 0x412699f4)","type":2},{"boxIdentifier":"(0xffffffff, 0xffffffff)","childCount":0,"identifier":"(0x1fbe5a88, 0x65840069)","index":0,"name":"Empty","parentIdentifier":"(0x010246fe, 0x0eacec10)","type":0}]</Data>
|
||||
</Entry>
|
||||
</Metadata>
|
||||
</OpenViBE-Scenario>
|
||||
+1510
File diff suppressed because it is too large
Load Diff
+5
@@ -0,0 +1,5 @@
|
||||
<OpenViBE-SettingsOverride>
|
||||
<SettingValue>2.693394e-001 -2.082757e-001 2.391615e-001 2.344401e-001 3.927157e-001 2.381559e-001 1.105450e-001 5.748063e-001 3.098411e-001 2.888676e-001 1.972432e-001 -2.803966e-001 8.610541e-002 -2.669093e-001 -2.873429e-001 -3.080204e-001 -2.313958e-001 -3.049153e-001 -3.205304e-001 -4.424281e-001 -2.981316e-001 -3.624890e-001 -2.713850e-002 -7.049823e-001 -1.550608e-002 -1.321822e-001 1.119925e-001 1.023369e-002 5.826165e-002 -2.615791e-001 -2.637424e-001 -3.941850e-001 4.185020e-001 1.442614e-001 3.069018e-001 3.027673e-001 3.956899e-001 2.814762e-001 2.776705e-001 3.540791e-001 2.828738e-001 3.027926e-001 3.106658e-001 2.946954e-001 8.165735e-001 3.035239e-001 1.979707e-001 2.325919e-001 1.767888e-001 -1.389007e-001 -2.142701e-001 6.029197e-002 1.522051e-001 1.241781e-001 9.543869e-002 2.155692e-001 2.680507e-001 3.076862e-001 3.604533e-001 3.075757e-001 2.513993e-001 2.252315e-001 3.295531e-001 2.891706e-001 4.002560e-001 3.100291e-001 </SettingValue>
|
||||
<SettingValue>6</SettingValue>
|
||||
<SettingValue>11</SettingValue>
|
||||
</OpenViBE-SettingsOverride>
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
Time:1x1,End Time,Noise 1:,Event Id,Event Date,Event Duration
|
||||
0.2705078125,0.3398437500,0.0,33026,0.2705078125,0.0
|
||||
0.3398437500,0.5419921875,0.0,33024,0.3398437500,0.0
|
||||
0.5419921875,0.6796875000,0.0,33026,0.5419921875,0.0
|
||||
0.6796875000,0.7099609375,0.0,33024,0.6796875000,0.0
|
||||
0.7099609375,0.8125000000,0.0,33025,0.7099609375,0.0
|
||||
0.8125000000,1.0195312500,0.0,33026,0.8125000000,0.0
|
||||
1.0195312500,1.0839843750,0.0,33024,1.0195312500,0.0
|
||||
1.0839843750,1.3544921875,0.0,33026,1.0839843750,0.0
|
||||
1.3544921875,1.3593750000,0.0,33026,1.3544921875,0.0
|
||||
1.3593750000,1.4199218750,0.0,33024,1.3593750000,0.0
|
||||
1.4199218750,1.6259765625,0.0,33025,1.4199218750,0.0
|
||||
1.6259765625,1.6992187500,0.0,33026,1.6259765625,0.0
|
||||
1.6992187500,1.8964843750,0.0,33024,1.6992187500,0.0
|
||||
1.8964843750,2.0390625000,0.0,33026,1.8964843750,0.0
|
||||
2.0390625000,2.1298828125,0.0,33024,2.0390625000,0.0
|
||||
2.1298828125,2.1679687500,0.0,33025,2.1298828125,0.0
|
||||
2.1679687500,2.3798828125,0.0,33026,2.1679687500,0.0
|
||||
2.3798828125,2.4384765625,0.0,33024,2.3798828125,0.0
|
||||
2.4384765625,2.7099609375,0.0,33026,2.4384765625,0.0
|
||||
2.7099609375,2.7197265625,0.0,33026,2.7099609375,0.0
|
||||
2.7197265625,2.8398437500,0.0,33024,2.7197265625,0.0
|
||||
2.8398437500,2.9804687500,0.0,33025,2.8398437500,0.0
|
||||
2.9804687500,3.0595703125,0.0,33026,2.9804687500,0.0
|
||||
3.0595703125,3.2519531250,0.0,33024,3.0595703125,0.0
|
||||
3.2519531250,3.3994140625,0.0,33026,3.2519531250,0.0
|
||||
3.3994140625,3.5224609375,0.0,33024,3.3994140625,0.0
|
||||
3.5224609375,3.5498046875,0.0,33026,3.5224609375,0.0
|
||||
3.5498046875,3.7392578125,0.0,33025,3.5498046875,0.0
|
||||
3.7392578125,3.7939453125,0.0,33024,3.7392578125,0.0
|
||||
3.7939453125,4.0644531250,0.0,33026,3.7939453125,0.0
|
||||
4.0644531250,4.0791015625,0.0,33026,4.0644531250,0.0
|
||||
4.0791015625,4.2597656250,0.0,33024,4.0791015625,0.0
|
||||
4.2597656250,4.3359375000,0.0,33025,4.2597656250,0.0
|
||||
4.3359375000,4.4199218750,0.0,33026,4.3359375000,0.0
|
||||
4.4199218750,4.6064453125,0.0,33024,4.4199218750,0.0
|
||||
4.6064453125,4.7597656250,0.0,33026,4.6064453125,0.0
|
||||
4.7597656250,4.8779296875,0.0,33024,4.7597656250,0.0
|
||||
4.8779296875,4.9697265625,0.0,33026,4.8779296875,0.0
|
||||
4.9697265625,5.0996093750,0.0,33025,4.9697265625,0.0
|
||||
5.0996093750,5.1484375000,0.0,33024,5.0996093750,0.0
|
||||
5.1484375000,5.4199218750,0.0,33026,5.1484375000,0.0
|
||||
5.4199218750,5.4394531250,0.0,33026,5.4199218750,0.0
|
||||
5.4394531250,5.6796875000,0.0,33024,5.4394531250,0.0
|
||||
5.6796875000,5.6904296875,0.0,33025,5.6796875000,0.0
|
||||
5.6904296875,5.7792968750,0.0,33026,5.6904296875,0.0
|
||||
5.7792968750,5.9619140625,0.0,33024,5.7792968750,0.0
|
||||
5.9619140625,6.1191406250,0.0,33026,5.9619140625,0.0
|
||||
6.1191406250,6.2324218750,0.0,33024,6.1191406250,0.0
|
||||
6.2324218750,6.3896484375,0.0,33026,6.2324218750,0.0
|
||||
6.3896484375,6.4599609375,0.0,33025,6.3896484375,0.0
|
||||
6.4599609375,6.5039062500,0.0,33024,6.4599609375,0.0
|
||||
6.5039062500,6.7744140625,0.0,33026,6.5039062500,0.0
|
||||
6.7744140625,6.7998046875,0.0,33026,6.7744140625,0.0
|
||||
6.7998046875,7.0458984375,0.0,33024,6.7998046875,0.0
|
||||
7.0458984375,7.0996093750,0.0,33026,7.0458984375,0.0
|
||||
7.0996093750,7.1396484375,0.0,33025,7.0996093750,0.0
|
||||
7.1396484375,7.3164062500,0.0,33024,7.1396484375,0.0
|
||||
7.3164062500,7.4794921875,0.0,33026,7.3164062500,0.0
|
||||
7.4794921875,7.5878906250,0.0,33024,7.4794921875,0.0
|
||||
7.5878906250,7.8095703125,0.0,33026,7.5878906250,0.0
|
||||
7.8095703125,7.8193359375,0.0,33025,7.8095703125,0.0
|
||||
7.8193359375,7.8583984375,0.0,33024,7.8193359375,0.0
|
||||
7.8583984375,8.1298828125,0.0,33026,7.8583984375,0.0
|
||||
8.1298828125,8.1591796875,0.0,33026,8.1298828125,0.0
|
||||
8.1591796875,8.4003906250,0.0,33024,8.1591796875,0.0
|
||||
8.4003906250,8.4990234375,0.0,33026,8.4003906250,0.0
|
||||
8.4990234375,8.5195312500,0.0,33024,8.4990234375,0.0
|
||||
8.5195312500,8.6718750000,0.0,33025,8.5195312500,0.0
|
||||
8.6718750000,8.8398437500,0.0,33026,8.6718750000,0.0
|
||||
8.8398437500,8.9423828125,0.0,33024,8.8398437500,0.0
|
||||
8.9423828125,9.1796875000,0.0,33026,8.9423828125,0.0
|
||||
9.1796875000,9.2138671875,0.0,33024,9.1796875000,0.0
|
||||
9.2138671875,9.2294921875,0.0,33026,9.2138671875,0.0
|
||||
9.2294921875,9.4843750000,0.0,33025,9.2294921875,0.0
|
||||
9.4843750000,9.5195312500,0.0,33026,9.4843750000,0.0
|
||||
9.5195312500,9.7558593750,0.0,33024,9.5195312500,0.0
|
||||
9.7558593750,9.8593750000,0.0,33026,9.7558593750,0.0
|
||||
9.8593750000,9.9394531250,0.0,33024,9.8593750000,0.0
|
||||
9.9394531250,10.026367188,0.0,33025,9.9394531250,0.0
|
||||
10.026367188,10.106445313,0.0,33026,10.026367188,0.0
|
||||
|
+81
@@ -0,0 +1,81 @@
|
||||
Time:1x1,End Time,Noise 1:,Event Id,Event Date,Event Duration
|
||||
0.2715078125,0.3408437500,0.0,33026,0.2715078125,0.0
|
||||
0.3408437500,0.5429921875,0.0,33025,0.3408437500,0.0
|
||||
0.5429921875,0.6806875000,0.0,33026,0.5429921875,0.0
|
||||
0.6806875000,0.7109609375,0.0,33025,0.6806875000,0.0
|
||||
0.7109609375,0.8135000000,0.0,33025,0.7109609375,0.0
|
||||
0.8135000000,1.0295312500,0.0,33026,0.8135000000,0.0
|
||||
1.0295312500,1.0939843750,0.0,33024,1.0295312500,0.0
|
||||
1.0939843750,1.3569921875,0.0,33026,1.0939843750,0.0
|
||||
1.3569921875,1.3693750000,0.0,33026,1.3569921875,0.0
|
||||
1.3693750000,1.4299218750,0.0,33026,1.3693750000,0.0
|
||||
1.4299218750,1.6359765625,0.0,33025,1.4299218750,0.0
|
||||
1.6359765625,1.7092187500,0.0,33026,1.6359765625,0.0
|
||||
1.7092187500,1.9064843750,0.0,33024,1.7092187500,0.0
|
||||
1.9064843750,2.0490625000,0.0,33026,1.9064843750,0.0
|
||||
2.0490625000,2.1398828125,0.0,33024,2.0490625000,0.0
|
||||
2.1398828125,2.1779687500,0.0,33024,2.1398828125,0.0
|
||||
2.1779687500,2.3898828125,0.0,33026,2.1779687500,0.0
|
||||
2.3898828125,2.4484765625,0.0,33024,2.3898828125,0.0
|
||||
2.4484765625,2.7159609375,0.0,33026,2.4484765625,0.0
|
||||
2.7159609375,2.7297265625,0.0,33026,2.7159609375,0.0
|
||||
2.7297265625,2.8498437500,0.0,33024,2.7297265625,0.0
|
||||
2.8498437500,2.9904687500,0.0,33026,2.8498437500,0.0
|
||||
2.9904687500,3.0695703125,0.0,33026,2.9904687500,0.0
|
||||
3.0695703125,3.2619531250,0.0,33024,3.0695703125,0.0
|
||||
3.2619531250,3.4094140625,0.0,33024,3.2619531250,0.0
|
||||
3.4094140625,3.5324609375,0.0,33024,3.4094140625,0.0
|
||||
3.5324609375,3.5598046875,0.0,33024,3.5324609375,0.0
|
||||
3.5598046875,3.7492578125,0.0,33025,3.5598046875,0.0
|
||||
3.7492578125,3.8039453125,0.0,33024,3.7492578125,0.0
|
||||
3.8039453125,4.0744531250,0.0,33025,3.8039453125,0.0
|
||||
4.0744531250,4.0891015625,0.0,33026,4.0744531250,0.0
|
||||
4.0891015625,4.2697656250,0.0,33024,4.0891015625,0.0
|
||||
4.2697656250,4.3459375000,0.0,33025,4.2697656250,0.0
|
||||
4.3459375000,4.4299218750,0.0,33026,4.3459375000,0.0
|
||||
4.4299218750,4.6164453125,0.0,33024,4.4299218750,0.0
|
||||
4.6164453125,4.7697656250,0.0,33026,4.6164453125,0.0
|
||||
4.7697656250,4.8879296875,0.0,33024,4.7697656250,0.0
|
||||
4.8879296875,4.9797265625,0.0,33026,4.8879296875,0.0
|
||||
4.9797265625,5.1096093750,0.0,33025,4.9797265625,0.0
|
||||
5.1096093750,5.1584375000,0.0,33024,5.1096093750,0.0
|
||||
5.1584375000,5.4299218750,0.0,33026,5.1584375000,0.0
|
||||
5.4299218750,5.4494531250,0.0,33026,5.4299218750,0.0
|
||||
5.4494531250,5.6896875000,0.0,33024,5.4494531250,0.0
|
||||
5.6896875000,5.7004296875,0.0,33025,5.6896875000,0.0
|
||||
5.7004296875,5.7892968750,0.0,33026,5.7004296875,0.0
|
||||
5.7892968750,5.9719140625,0.0,33024,5.7892968750,0.0
|
||||
5.9719140625,6.1291406250,0.0,33026,5.9719140625,0.0
|
||||
6.1291406250,6.2424218750,0.0,33024,6.1291406250,0.0
|
||||
6.2424218750,6.3996484375,0.0,33026,6.2424218750,0.0
|
||||
6.3996484375,6.4699609375,0.0,33025,6.3996484375,0.0
|
||||
6.4699609375,6.5139062500,0.0,33024,6.4699609375,0.0
|
||||
6.5139062500,6.7844140625,0.0,33026,6.5139062500,0.0
|
||||
6.7844140625,6.8098046875,0.0,33026,6.7844140625,0.0
|
||||
6.8098046875,7.0558984375,0.0,33024,6.8098046875,0.0
|
||||
7.0558984375,7.1096093750,0.0,33026,7.0558984375,0.0
|
||||
7.1096093750,7.1496484375,0.0,33025,7.1096093750,0.0
|
||||
7.1496484375,7.3264062500,0.0,33024,7.1496484375,0.0
|
||||
7.3264062500,7.4894921875,0.0,33026,7.3264062500,0.0
|
||||
7.4894921875,7.5978906250,0.0,33024,7.4894921875,0.0
|
||||
7.5978906250,7.8155703125,0.0,33026,7.5978906250,0.0
|
||||
7.8155703125,7.8293359375,0.0,33025,7.8155703125,0.0
|
||||
7.8293359375,7.8683984375,0.0,33024,7.8293359375,0.0
|
||||
7.8683984375,8.1398828125,0.0,33026,7.8683984375,0.0
|
||||
8.1398828125,8.1691796875,0.0,33026,8.1398828125,0.0
|
||||
8.1691796875,8.4103906250,0.0,33024,8.1691796875,0.0
|
||||
8.4103906250,8.5090234375,0.0,33026,8.4103906250,0.0
|
||||
8.5090234375,8.5295312500,0.0,33024,8.5090234375,0.0
|
||||
8.5295312500,8.6818750000,0.0,33025,8.5295312500,0.0
|
||||
8.6818750000,8.8498437500,0.0,33026,8.6818750000,0.0
|
||||
8.8498437500,8.9523828125,0.0,33024,8.8498437500,0.0
|
||||
8.9523828125,9.1896875000,0.0,33026,8.9523828125,0.0
|
||||
9.1896875000,9.2238671875,0.0,33024,9.1896875000,0.0
|
||||
9.2238671875,9.2394921875,0.0,33026,9.2238671875,0.0
|
||||
9.2394921875,9.4943750000,0.0,33025,9.2394921875,0.0
|
||||
9.4943750000,9.5295312500,0.0,33026,9.4943750000,0.0
|
||||
9.5295312500,9.7658593750,0.0,33024,9.5295312500,0.0
|
||||
9.7658593750,9.8693750000,0.0,33026,9.7658593750,0.0
|
||||
9.8693750000,9.9494531250,0.0,33024,9.8693750000,0.0
|
||||
9.9494531250,10.126367188,0.0,33025,9.9494531250,0.0
|
||||
10.126367188,10.206445313,0.0,33026,100126367188,0.0
|
||||
|
+35
@@ -0,0 +1,35 @@
|
||||
<Statistic>
|
||||
<Stimulations-list>
|
||||
<Stimulation>
|
||||
<Identifier>(0x00000000, 0x00008100)</Identifier>
|
||||
<Label>OVTK_StimulationId_Label_00</Label>
|
||||
<Count>500</Count>
|
||||
</Stimulation>
|
||||
</Stimulations-list>
|
||||
<Channel-list>
|
||||
<Channel>
|
||||
<Name>sinusOsc 1</Name>
|
||||
<Maximum>2.9959498935</Maximum>
|
||||
<Minimum>-2.9958162250</Minimum>
|
||||
<Mean>0.0037440891</Mean>
|
||||
</Channel>
|
||||
<Channel>
|
||||
<Name>sinusOsc 2</Name>
|
||||
<Maximum>2.9955453841</Maximum>
|
||||
<Minimum>-2.9959417073</Minimum>
|
||||
<Mean>0.0021516936</Mean>
|
||||
</Channel>
|
||||
<Channel>
|
||||
<Name>sinusOsc 3</Name>
|
||||
<Maximum>2.9959425273</Maximum>
|
||||
<Minimum>-2.9959158246</Minimum>
|
||||
<Mean>0.0004745227</Mean>
|
||||
</Channel>
|
||||
<Channel>
|
||||
<Name>sinusOsc 4</Name>
|
||||
<Maximum>2.9959140852</Maximum>
|
||||
<Minimum>-2.9959417073</Minimum>
|
||||
<Mean>0.0012721927</Mean>
|
||||
</Channel>
|
||||
</Channel-list>
|
||||
</Statistic>
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
<OpenViBE-Classifier-Box XMLVersion="3">
|
||||
<Strategy-Identifier class-id="(0xffffffff, 0xffffffff)">Native</Strategy-Identifier>
|
||||
<Algorithm-Identifier class-id="(0x2ba17a3c, 0x1bd46d84)">Linear Discrimimant Analysis (LDA)</Algorithm-Identifier>
|
||||
<Stimulations>
|
||||
<Class-Stimulation class-id="1">OVTK_GDF_Left</Class-Stimulation>
|
||||
<Class-Stimulation class-id="2">OVTK_GDF_Right</Class-Stimulation>
|
||||
</Stimulations>
|
||||
<OpenViBE-Classifier>
|
||||
<LDA>
|
||||
<Classes>1 2</Classes>
|
||||
<Weights> -1.390939e+01 -3.837006e+01 -3.951661e+00 1.267055e+02 8.129262e+00 1.130540e+02</Weights>
|
||||
<Bias-distance>1.04657</Bias-distance>
|
||||
<Coefficient-probability>1.15779</Coefficient-probability>
|
||||
</LDA>
|
||||
</OpenViBE-Classifier>
|
||||
</OpenViBE-Classifier-Box>
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
|
||||
g_offset = nil
|
||||
g_duration = nil
|
||||
|
||||
-- this function is called when the box is initialized
|
||||
function initialize(box)
|
||||
|
||||
dofile(box:get_config("${Path_Data}") .. "/plugins/stimulation/lua-stimulator-stim-codes.lua")
|
||||
|
||||
g_offset = box:get_setting(2)
|
||||
g_duration = box:get_setting(3)
|
||||
end
|
||||
|
||||
-- this function is called when the box is uninitialized
|
||||
function uninitialize(box)
|
||||
|
||||
end
|
||||
|
||||
function wait_until(box, time)
|
||||
while box:get_current_time() < time do
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function wait_for(box, duration)
|
||||
wait_until(box, box:get_current_time() + duration)
|
||||
end
|
||||
|
||||
|
||||
|
||||
function process(box)
|
||||
-- loops on every received stimulation for a given input
|
||||
while box:keep_processing() do
|
||||
for stimulation = 1, box:get_stimulation_count(1) do
|
||||
|
||||
-- gets the received stimulation
|
||||
identifier, date, duration = box:get_stimulation(1, 1)
|
||||
-- discards it
|
||||
box:remove_stimulation(1, 1)
|
||||
|
||||
-- delay the OVTK_GDF_Left and Right
|
||||
if identifier == OVTK_GDF_Left or identifier == OVTK_GDF_Right then
|
||||
box:send_stimulation(1, OVTK_GDF_Correct, date+g_offset, 0)
|
||||
box:send_stimulation(1, OVTK_GDF_Incorrect, date+g_offset+g_duration, 0)
|
||||
end
|
||||
end
|
||||
box:sleep()
|
||||
end
|
||||
end
|
||||
BIN
Binary file not shown.
|
After Width: | Height: | Size: 7.1 KiB |
+29
@@ -0,0 +1,29 @@
|
||||
def setUp(self):
|
||||
import os
|
||||
import shutil
|
||||
ov_binany_path=os.environ['OV_BINARY_PATH']
|
||||
self.terminal = App.open("xterm -e " + ov_binany_path +"/openvibe-designer.sh --no-session-management --play-fast Test_ROCCurve.xml")
|
||||
while not self.terminal.window():
|
||||
wait(1)
|
||||
|
||||
#def takepicture:
|
||||
|
||||
#dir = os.path.dirname(getBundlePath()) # the folder, where your script is stored
|
||||
#img = capture(SCREEN) # snapshots the screen
|
||||
#shutil.move(img, os.path.join(dir, "shot.png"))
|
||||
|
||||
def testROCCurve(self):
|
||||
import os
|
||||
import shutil
|
||||
try:
|
||||
wait("ROCCurveResult.png",60)
|
||||
assert(exists("ROCCurveResult.png"))
|
||||
except (FindFailed, AssertionError):
|
||||
print "Unable to find the required png"
|
||||
dir = os.path.dirname(getBundlePath()) # the folder, where your script is stored
|
||||
img = capture(SCREEN) # snapshots the screen
|
||||
shutil.move(img, os.path.join(dir, "screenshot.png"))
|
||||
raise
|
||||
|
||||
def tearDown(self):
|
||||
self.terminal.close()
|
||||
@@ -0,0 +1,46 @@
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
if (argc != 2)
|
||||
{
|
||||
std::cout << "Usage: test_evaluation <filename>\n";
|
||||
return 3;
|
||||
}
|
||||
|
||||
std::ifstream file(argv[1], std::ios::in);
|
||||
|
||||
if (file.good() && !file.bad() && file.is_open()) // ...
|
||||
{
|
||||
std::string line;
|
||||
while (getline(file, line))
|
||||
{
|
||||
if (line.find("Final value of Kappa") != std::string::npos)
|
||||
{
|
||||
std::cout << "Found kappa line " << line << std::endl;
|
||||
|
||||
const size_t pos = line.rfind(' ');
|
||||
const std::string cutline = line.substr(pos);
|
||||
|
||||
std::stringstream kappa(cutline);
|
||||
|
||||
double coefficient;
|
||||
kappa >> coefficient;
|
||||
|
||||
if (coefficient != 0.840677)
|
||||
{
|
||||
std::cout << "Wrong Kappa coefficient. Found " << coefficient << " instead of 0.840677" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::cout << "Test ok" << std::endl;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout << "Error: Problem opening [" << argv[1] << "]\n";
|
||||
|
||||
return 2;
|
||||
}
|
||||
Reference in New Issue
Block a user