37 #include <visp3/core/vpConfig.h>
38 #include <visp3/core/vpGaussRand.h>
39 #include <visp3/core/vpStatisticalTestEWMA.h>
40 #include <visp3/core/vpStatisticalTestHinkley.h>
41 #include <visp3/core/vpStatisticalTestMeanAdjustedCUSUM.h>
42 #include <visp3/core/vpStatisticalTestShewhart.h>
43 #include <visp3/core/vpStatisticalTestSigma.h>
44 #include <visp3/gui/vpPlot.h>
46 #if defined(VISP_HAVE_DISPLAY)
93 result =
"unknown-type-test";
111 bool hasNotFound =
true;
112 while ((
id < count) && hasNotFound) {
132 const std::string &suffix =
">")
134 std::string msg(prefix);
136 unsigned int lastId = count - 1;
137 for (
unsigned int i = 0; i < lastId; i++) {
151 template <
typename T>
154 std::stringstream ss;
186 std::string rulesAsString = prefix;
189 rulesAsString +=
"ON";
192 rulesAsString +=
"OFF";
194 rulesAsString += sep;
197 rulesAsString +=
"ON";
200 rulesAsString +=
"OFF";
202 rulesAsString += suffix;
203 return rulesAsString;
226 size_t nbNames = names.size();
227 for (
size_t i = 0; i < nbNames; ++i) {
229 std::cout <<
"alarm[" << names[i] <<
"] (i.e. " <<
static_cast<unsigned int>(alarmToActivate) <<
") set to true" << std::endl;
230 array[
static_cast<unsigned int>(alarmToActivate)] =
true;
250 std::vector<std::string> listActivatedAlarms;
252 for (
unsigned int id = 0;
id < nbTypeTests; ++id) {
256 listActivatedAlarms.push_back(testName);
259 return listActivatedAlarms;
273 const std::string &prefix =
"[",
const std::string &sep =
" , ",
274 const std::string &suffix =
"]")
277 std::string result = prefix;
278 size_t nbTestActivated = listActivatedAlarms.size();
279 if (nbTestActivated == 0) {
280 return prefix +
" " + suffix;
282 for (
size_t i = 0; i < nbTestActivated - 1; ++i) {
283 result += listActivatedAlarms[i] + sep;
285 result += listActivatedAlarms[nbTestActivated - 1] + suffix;
297 unsigned int nbActivated = 0;
299 for (
unsigned int id = 0;
id < nbTypeAlarms; ++id) {
351 const float &mean,
const float &mean_drift,
const float &stdev)
353 const float dt = 10.f;
358 plotter.
setTitle(0,
"Evolution of the signal");
364 unsigned int idFrame = 0;
399 vpGaussRand rndGen(stdev, mean,
static_cast<long>(idFrame * dt));
400 signal =
static_cast<float>(rndGen());
406 std::cout <<
"Estimated mean of the input signal: " << p_test->
getMean() << std::endl;
407 std::cout <<
"Estimated stdev of the input signal: " << p_test->
getStdev() << std::endl;
410 float mean_eff = mean;
411 bool hasToRun =
true;
414 vpGaussRand rndGen(stdev, mean_eff,
static_cast<long>(idFrame * dt));
415 signal =
static_cast<float>(rndGen());
422 mean_eff += mean_drift;
429 std::cout <<
"Test failed at frame: " << idFrame - parameters.
m_test_nbsamples << std::endl;
431 std::cout <<
"Last signal value: " << signal << std::endl;
434 std::cout <<
"\tw(t) = " << p_testEwma->
getWt() << std::endl;
439 std::cout <<
"\tUpper cusum = " << p_testCusum->
getTestSignalPlus() << std::endl;
443 std::vector<float> signal = p_testShewhart->
getSignals();
444 size_t nbSignal = signal.size();
445 std::cout <<
"Signal history = [ ";
446 for (
size_t i = 0; i < nbSignal; ++i) {
447 std::cout << signal[i] <<
" ";
449 std::cout <<
"]" << std::endl;
454 float Mk = p_hinkley->
getMk();
455 float Nk = p_hinkley->
getNk();
456 float Sk = p_hinkley->
getSk();
457 float Tk = p_hinkley->
getTk();
458 std::cout <<
"S+(t) = " << Tk - Nk <<std::endl;
459 std::cout <<
"S-(t) = " << Mk - Sk <<std::endl;
461 float limitDown = 0.f, limitUp = 0.f;
463 std::cout <<
"\tLimit down = " << limitDown << std::endl;
464 std::cout <<
"\tLimit up = " << limitUp << std::endl;
466 std::cout <<
"End of test on synthetic data. Press enter to leave." << std::endl;
472 int main(
int argc,
char *argv[])
476 float opt_mean = 6.f;
477 float opt_meandrift = 0.f;
478 float opt_stdev = 2.f;
482 if ((std::string(argv[i]) ==
"--test") && ((i + 1) < argc)) {
486 else if ((std::string(argv[i]) ==
"--nb-samples") && ((i + 1) < argc)) {
490 else if ((std::string(argv[i]) ==
"--mean") && ((i + 1) < argc)) {
491 opt_mean =
static_cast<float>(std::atof(argv[i + 1]));
494 else if ((std::string(argv[i]) ==
"--mean-drift") && ((i + 1) < argc)) {
495 opt_meandrift =
static_cast<float>(std::atof(argv[i + 1]));
498 else if ((std::string(argv[i]) ==
"--stdev") && ((i + 1) < argc)) {
499 opt_stdev =
static_cast<float>(std::atof(argv[i + 1]));
502 else if ((std::string(argv[i]) ==
"--alarms")) {
503 unsigned int nbArguments = 0;
504 std::vector<std::string> alarmNames;
505 bool hasNotFoundNextParams =
true;
506 for (
int j = 1; ((i + j) < argc) && hasNotFoundNextParams; ++j) {
507 std::string candidate(argv[i+j]);
508 if (candidate.find(
"--") != std::string::npos) {
510 hasNotFoundNextParams =
false;
514 alarmNames.push_back(candidate);
522 else if ((std::string(argv[i]) ==
"--cusum-h") && ((i + 1) < argc)) {
523 parameters.
m_cusum_h =
static_cast<float>(std::atof(argv[i + 1]));
526 else if ((std::string(argv[i]) ==
"--cusum-k") && ((i + 1) < argc)) {
527 parameters.
m_cusum_k =
static_cast<float>(std::atof(argv[i + 1]));
530 else if ((std::string(argv[i]) ==
"--ewma-alpha") && ((i + 1) < argc)) {
531 parameters.
m_ewma_alpha =
static_cast<float>(std::atof(argv[i + 1]));
534 else if ((std::string(argv[i]) ==
"--hinkley-alpha") && ((i + 1) < argc)) {
535 parameters.
m_hinkley_alpha =
static_cast<float>(std::atof(argv[i + 1]));
538 else if ((std::string(argv[i]) ==
"--hinkley-delta") && ((i + 1) < argc)) {
539 parameters.
m_hinkley_delta =
static_cast<float>(std::atof(argv[i + 1]));
542 else if (std::string(argv[i]) ==
"--hinkley-compute") {
545 else if ((std::string(argv[i]) ==
"--hinkley-h") && ((i + 1) < argc)) {
546 parameters.
m_hinkley_h =
static_cast<float>(std::atof(argv[i + 1]));
549 else if ((std::string(argv[i]) ==
"--hinkley-k") && ((i + 1) < argc)) {
550 parameters.
m_hinkley_k =
static_cast<float>(std::atof(argv[i + 1]));
555 std::string argument = std::string(argv[i + 1 + j]);
556 if ((argument.find(
"on") != std::string::npos) || (argument.find(
"ON") != std::string::npos)) {
565 else if (std::string(argv[i]) ==
"--shewhart-weco") {
568 else if ((std::string(argv[i]) ==
"--sigma-h") && ((i + 1) < argc)) {
569 parameters.
m_sigma_h =
static_cast<float>(std::atof(argv[i + 1]));
572 else if ((std::string(argv[i]) ==
"--help") || (std::string(argv[i]) ==
"-h")) {
573 std::cout <<
"\nSYNOPSIS " << std::endl
575 <<
" [--test <type>]"
576 <<
" [--nb-samples <value>]"
577 <<
" [--alarms <name_1 ... name_n>]"
578 <<
" [--mean <value>]"
579 <<
" [--mean-drift <value>]"
580 <<
" [--stdev <value>]"
581 <<
" [--cusum-h <value>]"
582 <<
" [--cusum-k <value>]"
583 <<
" [--ewma-alpha <value ]0; 1[>]"
584 <<
" [--hinkley-alpha <]0; inf[>]"
585 <<
" [--hinkley-delta <]0; inf[>]"
586 <<
" [--hinkley-compute]"
587 <<
" [--hinkley-h <]0; inf[>]"
588 <<
" [--hinkley-k <]0; inf[>]"
589 <<
" [--shewhart-rules <3-sigma:{on|off} 2-sigma:{on|off} 1-sigma:{on|off} same-side:{on|off}>"
590 <<
" [--shewhart-weco]"
591 <<
" [--sigma-h <value>]"
592 <<
" [--help,-h]" << std::endl;
593 std::cout <<
"\nOPTIONS " << std::endl
594 <<
" --test <type-name>" << std::endl
595 <<
" Type of test to perform on the data." << std::endl
598 <<
" --nb-samples <value>" << std::endl
599 <<
" Number of samples to compute the mean and standard deviation of the monitored signal." << std::endl
602 <<
" --alarms <name_1 .. name_n>" << std::endl
603 <<
" Set the mean drift alarms to monitor." << std::endl
607 <<
" --mean <value>" << std::endl
608 <<
" Mean of the signal." << std::endl
609 <<
" Default: " << opt_mean<< std::endl
611 <<
" --mean-drift <value>" << std::endl
612 <<
" Mean drift for the synthetic data." << std::endl
613 <<
" Default: " << opt_meandrift << std::endl
615 <<
" --stdev <value>" << std::endl
616 <<
" Standard deviation of the signal." << std::endl
617 <<
" Default: " << opt_stdev << std::endl
619 <<
" --cusum-h <value>" << std::endl
620 <<
" The alarm factor that permits to the CUSUM test to determine when the process is out of control" << std::endl
621 <<
" from the standard deviation of the signal." << std::endl
622 <<
" Default: " << parameters.
m_cusum_h << std::endl
624 <<
" --cusum-k <value>" << std::endl
625 <<
" The factor that permits to determine the slack of the CUSUM test, " << std::endl
626 <<
" i.e. the minimum value of the jumps we want to detect, from the standard deviation of the signal." << std::endl
627 <<
" Default: " << parameters.
m_cusum_k << std::endl
629 <<
" --ewma-alpha <value ]0; 1[>" << std::endl
630 <<
" Forgetting factor for the Exponential Weighted Moving Average (EWMA)." << std::endl
633 <<
" --hinkley-alpha <value ]0; inf[>" << std::endl
634 <<
" The alarm threshold indicating that a mean drift occurs for the Hinkley's test." << std::endl
637 <<
" --hinkley-delta <value>" << std::endl
638 <<
" Detection threshold indicating minimal magnitude we want to detect for the Hinkley's test." << std::endl
641 <<
" --hinkley-compute" << std::endl
642 <<
" If set, the Hinkley's test will compute the alarm and detection thresholds" << std::endl
643 <<
" from the standard deviation of the input signal." << std::endl
644 <<
" Default: disabled" << std::endl
646 <<
" --hinkley-h <value>" << std::endl
647 <<
" Alarm factor permitting to compute the alarm threshold for the Hinkley's test." << std::endl
648 <<
" Default: " << parameters.
m_hinkley_h << std::endl
650 <<
" --hinkley-k <value>" << std::endl
651 <<
" Detection factor permitting to compute the Detection threshold for the Hinkley's test." << std::endl
652 <<
" Default: " << parameters.
m_hinkley_k << std::endl
654 <<
" --shewhart-rules <3-sigma:{on|off} 2-sigma:{on|off} 1-sigma:{on|off} same-side:{on|off}>" << std::endl
655 <<
" Choose the WECO additionnal tests for the Shewhart's test to use. To activate them, --shewart-weco must be used." << std::endl
656 <<
" Default: ON ON ON ON" << std::endl
658 <<
" --shewhart-weco" << std::endl
659 <<
" Activate the WECO additionnal tests for the Shewhart's test." << std::endl
660 <<
" Default: deactivated" << std::endl
662 <<
" --sigma-h <value>" << std::endl
663 <<
" The alarm factor of the sigma test." << std::endl
664 <<
" Default: " << parameters.
m_sigma_h << std::endl
666 <<
" --help, -h" << std::endl
667 <<
" Display this helper message." << std::endl
672 std::cout <<
"\nERROR " << std::endl <<
" Unknown option " << argv[i] << std::endl;
685 std::cout <<
" Nb samples for statistics computation: " << parameters.
m_test_nbsamples << std::endl;
696 std::cout <<
" Actual mean of the input signal: " << opt_mean << std::endl;
697 std::cout <<
" Actual stdev of the input signal: " << opt_stdev << std::endl;
698 std::cout <<
" Mean drift of the input signal: " << opt_meandrift << std::endl;
700 return testOnSynthetic(opt_typeTest, parameters, opt_mean, opt_meandrift, opt_stdev);
705 std::cerr <<
"Recompile ViSP with display capabilities in order to use this tutorial." << std::endl;
error that can be emitted by ViSP classes.
@ badValue
Used to indicate that a value is not in the allowed range.
Class for generating random number with normal probability density.
This class enables real time drawing of 2D or 3D graphics. An instance of the class open a window whi...
void initGraph(unsigned int graphNum, unsigned int curveNbr)
void setUnitY(unsigned int graphNum, const std::string &unity)
void plot(unsigned int graphNum, unsigned int curveNum, double x, double y)
void setUnitX(unsigned int graphNum, const std::string &unitx)
void setTitle(unsigned int graphNum, const std::string &title)
Base class for methods detecting the drift of the mean of a process.
vpMeanDriftType
Enum that indicates if a drift of the mean occurred.
static vpMeanDriftType vpMeanDriftTypeFromString(const std::string &name)
Cast a string into a vpMeanDriftType.
void getLimits(float &limitDown, float &limitUp) const
Get the upper and lower limits of the test signal.
static std::string vpMeanDriftTypeToString(const vpMeanDriftType &type)
Cast a vpMeanDriftType into a string.
vpMeanDriftType testDownUpwardMeanDrift(const float &signal)
Test if a downward or an upward mean drift occurred according to the new value of the signal.
float getMean() const
Get the mean used as reference.
float getStdev() const
Get the standard deviation used as reference.
static std::string getAvailableMeanDriftType(const std::string &prefix="<", const std::string &sep=" , ", const std::string &suffix=">")
Get the list of available vpMeanDriftType objects that are handled.
Class that permits to perform Exponentially Weighted Moving Average mean drft tests.
float getWt() const
Get the current value of the test signal.
This class implements the Hinkley's cumulative sum test.
float getNk() const
Get the minimum of the test signal for upward mean drift .
float getTk() const
Get the test signal for upward mean drift..
float getSk() const
Get the test signal for downward mean drift.
float getMk() const
Get the maximum of the test signal for downward mean drift .
Class that permits to perform a mean adjusted Cumulative Sum test.
float getTestSignalMinus() const
Get the latest value of the test signal for downward jumps of the mean.
float getTestSignalPlus() const
Get the latest value of the test signal for upward jumps of the mean.
Class that permits a Shewhart's test.
vpWecoRulesAlarm getAlarm() const
Get the alarm raised by the last test due to the WECO's rules.
std::vector< float > getSignals() const
Get the NB_DATA_SIGNAL last signal values, sorted from the latest [0] to the newest [NB_DATA_SIGNAL -...
static const bool CONST_ALL_WECO_ACTIVATED[COUNT_WECO - 1]
static std::string vpWecoRulesAlarmToString(const vpWecoRulesAlarm &alarm)
Class that permits a simple test comparing the current value to the standard deviation of the signal.
TypeTest typeTestFromString(const std::string &name)
Permit to cast a string into a TypeTest, to cast a command line argument.
void vectorOfStringToMeanDriftTypeArray(const std::vector< std::string > &names, bool array[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT])
Cast a vector of string into an array of boolean activating / deactivating the mean drift alarms.
std::string meanDriftArrayToString(const bool array[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT], const std::string &prefix="[", const std::string &sep=" , ", const std::string &suffix="]")
Cast an array of boolean (de)activating the mean drift alarms into a single string listing all the al...
std::vector< std::string > meanDriftArrayToVectorOfString(const bool array[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT])
Cast an array of boolean (de)activating the mean drift alarms into the corresponding vector of string...
std::string getAvailableTypeTest(const std::string &prefix="<", const std::string &sep=" , ", const std::string &suffix=">")
Get the list of available TypeTest objects that are handled.
std::string typeTestToString(const TypeTest &type)
[Enum_For_Test_Choice]
std::string numberToString(const T &number)
Cast a number type into a string.
const bool CONST_ALL_ALARM_OFF[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT]
Array that sets all the types of mean drift to deactivated.
struct TutorialMeanDrift::ParametersForAlgo ParametersForAlgo
[Structure_Parameters]
std::string boolToString(const bool &boolean)
Cast a boolean into a string.
const bool CONST_ALL_ALARM_ON[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT]
Array that sets all the types of mean drift to activated.
std::string wecoRulesToString(const bool rules[vpStatisticalTestShewhart::COUNT_WECO - 1], const std::string &prefix="[", const std::string &suffix="]", const std::string &sep=" , ")
Write the WECO's rules used in the Shewhart's test in human readable format.
TypeTest
[Enum_For_Test_Choice]
@ MEAN_ADJUSTED_CUSUM_TYPE_TEST
unsigned int meanDriftArrayToNbActivated(const bool array[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT])
Indicate how many alarms are set.
bool m_shewhart_rules[vpStatisticalTestShewhart::COUNT_WECO - 1]
bool m_hinkley_computealphadelta
unsigned int m_test_nbactivatedalarms
unsigned int m_test_nbsamples
bool m_test_activatedalarms[vpStatisticalTestAbstract::MEAN_DRIFT_COUNT]