CEBL  2.1
TabTraining.cpp
Go to the documentation of this file.
1 
7 #include "TabTraining.hpp"
8 #include "InterfaceCombo.hpp"
11 #include "interfaces/RobotPie.hpp"
12 #include "DataSourceCombo.hpp"
13 
14 //----------------------------------------------------------------------
15 // Constructors / Destructor
16 
18 {
19  delete this->interface_config;
20 }
21 
22 
23 //----------------------------------------------------------------------
24 // Create the GUI
25 
26 
28 {
29  //add title
30  GtkWidget *title = gtk_label_new("");
31  gtk_label_set_markup(GTK_LABEL(title),view->getString("TrainingTitle"));
32  TabAdd(title);
33  TabAdd(gtk_hseparator_new());
34 
35  //-------------------------------------------------
36 
37  this->interface_box = gtk_vbox_new(false, 0);
38  this->updating_view = false;
39  this->training_stopped_manually = false;
40  this->interface_config = new InterfaceConfigurationWindow(this->view);
41 
42  //----------------------------------------
43  //create buttons
44 
45 
46  btn_start = gtk_button_new_with_label(view->getString("TrainingStr1"));
47  g_signal_connect(G_OBJECT(btn_start),
48  "clicked",
49  G_CALLBACK(CB_startTraining),
50  (gpointer) this);
51 
52  btn_stop = gtk_button_new_with_label(view->getString("TrainingStr2"));
53  gtk_widget_set_sensitive(btn_stop,false);
54  g_signal_connect(G_OBJECT(btn_stop),
55  "clicked",
56  G_CALLBACK(CB_stopTraining),
57  (gpointer) this);
58 
59  spin_classes = gtk_spin_button_new_with_range(2,50,1);
60  gtk_widget_set_size_request(spin_classes,40,25);
61 
62  g_signal_connect(G_OBJECT(spin_classes),
63  "value-changed",
64  G_CALLBACK(CB_changeNumClasses),
65  (gpointer) this);
66 
67  spin_sequences = gtk_spin_button_new_with_range(1,50,1);
68  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_sequences),3);
69  gtk_widget_set_size_request(spin_sequences,40,25);
70  g_signal_connect(G_OBJECT(spin_sequences),
71  "value-changed",
72  G_CALLBACK(CB_changeNumSequences),
73  (gpointer) this);
74 
75  spin_sequence_length = gtk_spin_button_new_with_range(1,50,1);
76  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_sequence_length),3);
77  gtk_widget_set_size_request(spin_sequence_length,40,25);
78  g_signal_connect(G_OBJECT(spin_sequence_length),
79  "value-changed",
80  G_CALLBACK(CB_changeSequenceLength),
81  (gpointer) this);
82 
83  spin_pause_length = gtk_spin_button_new_with_range(1,50,1);
84  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_pause_length),3);
85  gtk_widget_set_size_request(spin_pause_length,40,25);
86  g_signal_connect(G_OBJECT(spin_pause_length),
87  "value-changed",
88  G_CALLBACK(CB_changePauseLength),
89  (gpointer) this);
90 
91  btn_load = gtk_button_new_with_label(view->getString("TrainingStr3"));
92  g_signal_connect(G_OBJECT(btn_load),
93  "clicked",
94  G_CALLBACK(CB_loadData),
95  (gpointer) this);
96 
97  btn_save = gtk_button_new_with_label(view->getString("TrainingStr4"));
98  g_signal_connect(G_OBJECT(btn_save),
99  "clicked",
100  G_CALLBACK(CB_saveData),
101  (gpointer) this);
102 
103 
104  info_frame1 = gtk_viewport_new(NULL,NULL);
105  // gtk_container_border_width(GTK_CONTAINER(info_frame),1);
106  label_info = gtk_label_new("");
107 
108  info_frame2 = gtk_viewport_new(NULL,NULL);
109  // gtk_container_border_width(GTK_CONTAINER(info_frame),1);
110  label_data = gtk_label_new("");
111 
112  //----------------------------------------
113  //create boxes
114  controls_hbox1 = gtk_hbox_new(false,0);
115  controls_hbox2 = gtk_hbox_new(false,0);
116  controls_hbox3 = gtk_hbox_new(false,0);
117  controls_hbox4 = gtk_hbox_new(false,0);
118  GtkWidget * btn_box1 = gtk_hbutton_box_new();
119  GtkWidget * btn_box2 = gtk_hbutton_box_new();
120  GtkWidget * btn_box3 = gtk_hbutton_box_new();
121  GtkWidget * btn_box4 = gtk_hbutton_box_new();
122  gtk_button_box_set_layout(GTK_BUTTON_BOX(btn_box1),GTK_BUTTONBOX_START);
123  gtk_button_box_set_layout(GTK_BUTTON_BOX(btn_box2),GTK_BUTTONBOX_START);
124  gtk_button_box_set_layout(GTK_BUTTON_BOX(btn_box3),GTK_BUTTONBOX_START);
125  gtk_button_box_set_layout(GTK_BUTTON_BOX(btn_box4),GTK_BUTTONBOX_START);
126 
127 
128 
129  //----------------------------------------
130  //pack everything into boxes
131  gtk_box_pack_start(GTK_BOX(btn_box1),btn_start,false,false,2);
132  gtk_box_pack_start(GTK_BOX(btn_box1),btn_stop,false,false,2);
133  gtk_box_pack_start(GTK_BOX(controls_hbox1),btn_box1,false,false,2);
134  source_combo = getView()->getDataSource()->getCombo();
135  gtk_box_pack_end(GTK_BOX(controls_hbox1),source_combo,false,true,2);
136  gtk_box_pack_end(GTK_BOX(controls_hbox1),
137  gtk_label_new(view->getString("TrainingStr5")),
138  false,false,2);
139 
140  gtk_box_pack_start(GTK_BOX(controls_hbox2),spin_classes,false,false,2);
141  gtk_box_pack_start(GTK_BOX(controls_hbox2),
142  gtk_label_new(view->getString("TrainingStr6")),
143  false,false,2);
144  gtk_box_pack_start(GTK_BOX(controls_hbox2),spin_sequences,false,false,2);
145  gtk_box_pack_start(GTK_BOX(controls_hbox2),
146  gtk_label_new(view->getString("TrainingStr7")),
147  false,false,2);
148  gtk_box_pack_start(GTK_BOX(controls_hbox2),
149  spin_sequence_length,false,false,2);
150  gtk_box_pack_start(GTK_BOX(controls_hbox2),
151  gtk_label_new(view->getString("TrainingStr8")),
152  false,false,2);
153  gtk_box_pack_start(GTK_BOX(controls_hbox2),
154  spin_pause_length,false,false,2);
155  gtk_box_pack_start(GTK_BOX(controls_hbox2),
156  gtk_label_new(view->getString("TrainingStr9")),
157  false,false,2);
158  gtk_container_add(GTK_CONTAINER(info_frame1),label_info);
159 
160  gtk_box_pack_start(GTK_BOX(btn_box3),btn_load,false,false,2);
161  gtk_box_pack_start(GTK_BOX(btn_box3),btn_save,false,false,2);
162  gtk_box_pack_start(GTK_BOX(controls_hbox3),btn_box3,false,false,2);
163  gtk_container_add(GTK_CONTAINER(info_frame2),label_data);
164 
165 
166  //----------------------------------------
167  // classification feedback controls
168  check_classification_feedback =
169  gtk_check_button_new_with_label("Classification Feedback");
170  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_classification_feedback),
171  false);
172  gtk_box_pack_start(GTK_BOX(btn_box4),check_classification_feedback,
173  false,false,2);
174  g_signal_connect(G_OBJECT(check_classification_feedback),
175  "toggled",
176  G_CALLBACK(CB_toggleClassificationFeedback),
177  (gpointer) this);
178 
179  gtk_box_pack_start(GTK_BOX(controls_hbox4),btn_box4,false,false,2);
180 
181  //----------------------------------------
182  //add everything to tab
183  controls_box = gtk_vbox_new(false,0);
184  gtk_box_pack_start(GTK_BOX(controls_box), controls_hbox1, true, true, 2);
185  gtk_box_pack_start(GTK_BOX(controls_box), controls_hbox2, true, true, 2);
186  gtk_box_pack_start(GTK_BOX(controls_box), info_frame1, true, true, 4);
187  gtk_box_pack_start(GTK_BOX(controls_box), controls_hbox3, true, true, 2);
188  gtk_box_pack_start(GTK_BOX(controls_box), info_frame2, true, true, 4);
189  gtk_box_pack_start(GTK_BOX(controls_box), controls_hbox4, true, true, 2);
190 
191 
192  //--------------------------------------------------
193  // Training/Using Interfaces
194  // because training interfaces are totally view-side,
195  // the selection of the training interface will be handled
196  // independently from the model
197 
198  //interface combo box
199  this->interface_combo = this->view->getInterfaceCombo()->getCombo();
200  gtk_box_pack_end(GTK_BOX(controls_hbox3),this->interface_combo,false,false,0);
201  this->btn_interface_cfg = this->interface_config->getButton();
202  gtk_box_pack_end(GTK_BOX(controls_hbox3),btn_interface_cfg,false,false,0);
203  gtk_widget_show_all(controls_hbox3);
204 
205  this->interface = NULL;
206 
207 
208  gtk_widget_set_size_request(controls_box,700,-1);
209  TabFrameAdd(controls_box, view->getString("TrainingStr10"));
210  TabAdd(interface_box,true,true,0);
211 
212 }
213 
214 
215 
216 //update view from model
218 {
219  this->updating_view = true;
220  CEBLModel * model = this->getView()->getModel();
221  //----------------------------------------
222  //update training options
223  int num_classes = model->trainingGetNumClasses();
224  int num_sequences = model->trainingGetNumSequences();
225  int sequence_length = model->trainingGetSequenceLength();
226  int pause_length = model->trainingGetPauseLength();
227  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_classes),num_classes);
228  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_sequences),num_sequences);
229  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_sequence_length),
230  sequence_length);
231  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_pause_length),pause_length);
232  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_classification_feedback),
233  model->trainingFeedbackEnabled());
234 
235  //----------------------------------------
236  // update data label
237  bool data_loaded = model->trainingDataIsLoaded();
238  string text = "";
239  if(data_loaded)
240  {
241  EEGTrainingData data = model->trainingGetData();
242  int num_classes = data.numClasses();
243  int num_sequences = data.numSequences();
244  int num_samples = data.numSamples();
245  if(model->trainingIsDataFileLoaded())
246  {
247  //indicate filename of saved data
248  text = view->getString("TrainingStr29") + model->trainingGetDataFilename() + ", ";
249  }
250  else
251  {
252  //indicate unsaved data
253  text = view->getString("TrainingStr30");
254  }
255  text += view->getString("TrainingStr31")
256  + TextUtils::IntToString(num_classes)
257  + view->getString("TrainingStr32")
258  + TextUtils::IntToString(num_sequences)
259  + view->getString("TrainingStr33")
260  + TextUtils::IntToString(num_samples);
261 
262  }
263  else
264  {
265  text = view->getString("TrainingStr34");
266  }
267 
268  text = "<small>" + text + "</small>";
269  gtk_label_set_markup(GTK_LABEL(this->label_data),
270  text.c_str());
271 
272 
273  //----------------------------------------
274  //update interface
275  //get a pointer to the selected interface
276  EEGInterface* new_interface = this->view->getInterfaceCombo()->getInterface();
277 
278 
279  //if the interface has changed, remove old interface and pack in new one
280  if(new_interface != this->interface)
281  {
282  if(this->interface != NULL)
283  {
284  this->interface->hide();
285  gtk_container_remove(GTK_CONTAINER(this->interface_box),
286  this->interface->getContainer());
287  }
288 
289  this->interface = new_interface;
290  if(this->interface != NULL)
291  {
292  gtk_box_pack_start(GTK_BOX(this->interface_box),
293  this->interface->getContainer(),true,true,0);
294  interface->setBGColor(this->getView()->getBGRED(),
295  this->getView()->getBGGREEN(),
296  this->getView()->getBGBLUE());
297  this->interface->show();
298  }
299  }
300 
301  this->updating_view = false;
302  updateInterface();
303  updateTextInfo();
304 
305 }
306 
307 //----------------------------------------
308 
309 void TabTraining::updateInterface()
310 {
311  if(!updating_view)
312  {
313  int n = int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(spin_classes)));
314  interface->setNumClasses(n);
315  }
316 }
317 
318 
319 //----------------------------------------
320 
321 void TabTraining::updateTextInfo()
322 {
323  int num_classes = this->getView()->getModel()->trainingGetNumClasses();
324  int num_sequences = this->getView()->getModel()->trainingGetNumSequences();
325  int sequence_length = this->getView()->getModel()->trainingGetSequenceLength();
326  int pause_length = this->getView()->getModel()->trainingGetPauseLength();
327 
328  int total_data_time = num_classes * num_sequences * sequence_length;
329  int total_time = total_data_time + pause_length * num_sequences * num_classes;
330  stringstream ss;
331  int minutes = total_data_time/60;
332  int seconds = total_data_time % 60;
333  int minutes2 = total_time/60;
334  int seconds2 = total_time % 60;
335 
336  if(total_time > 60)
337  {
338  ss << view->getString("TrainingStr11") << minutes2 << view->getString("TrainingStr12") << seconds2 << view->getString("TrainingStr13")
339  << minutes << view->getString("TrainingStr14") << seconds << view->getString("TrainingStr15");
340  }
341  else
342  {
343  ss << view->getString("TrainingStr16") << total_time << view->getString("TrainingStr17")
344  << total_data_time << view->getString("TrainingStr18");
345  }
346  gtk_label_set_markup(GTK_LABEL(label_info),ss.str().c_str());
347  gtk_widget_set_size_request(label_info,300,-1);
348 }
349 
350 
351 //----------------------------------------
352 
353 gint TabTraining::timedUpdateInterface(gpointer parent)
354 {
355  TabTraining * tab = (TabTraining*)parent;
356  CEBLModel * model = tab->getView()->getModel();
357  CEBLViewGTK * view = tab->getView();
358 
359  //ERROR CHECKING
360  bool failed = model->trainingFailed();
361  if(failed)
362  {
363  if(!tab->training_stopped_manually)
364  WidgetUtils::AlertError(view->getString("TrainingStr19"),model->trainingGetFailureMessage());
365  if(tab->interface!=NULL)
366  tab->interface->selectTrainingClass(-1);
367  tab->enableControls();
368  tab->updateView();
369  tab->interface->setTrainMode();
370  return false;
371  }
372 
373  //update interface
374  bool paused = model->trainingIsPaused();
375  bool training_classifier = model->trainingIsTrainingClassifier();
376  bool classification_feedback = model->trainingFeedbackEnabled();
377  if(!training_classifier)
378  {
380  }
381 
382  if(training_classifier)
383  {
384  WidgetUtils::waitBoxShow("Training classifier");
386  {
388  }
389  else
390  {
391  WidgetUtils::waitBoxSetText("Attempting to stop training.\n(This may take awhile.)");
394  }
395  }
396  else if(paused)
397  {
398  tab->interface->setTrainMode();
399  int cls = model->trainingGetTrainingClass();
400  int seq = model->trainingGetTrainingSequence();
401 
402  tab->interface->selectTrainingClass(cls);
403 
404  tab->view->getStatusBar()->remove(tab->status_id);
405  tab->status_id = tab->view->getStatusBar()->push(string(view->getString("TrainingStr20"))
406  + TextUtils::IntToString(cls) +
407  view->getString("TrainingStr21")
408  + TextUtils::IntToString(seq) + ".");
409  }
410  else
411  {
412  tab->interface->selectTrainingClass(-1);
413 
414  //if we are providing feedback, draw the bars
415  if(classification_feedback)
416  {
417  tab->interface->setUseMode();
418  std::vector<double> std_props =
420  ublas::vector<double> proportions =
421  cppR::asUblasVector(std_props);
422  if(proportions.size() > 0)
423  {
424  tab->interface->setClassProportions(std_props);
425  }
426  }
427  }
428 
429  if(tab->interface==NULL)
430  {
431  tab->enableControls();
432  return false;
433  }
434 
435  //end training successfully
436  if(!model->trainingIsActive())
437  {
438  WidgetUtils::Alert(view->getString("TrainingStr22"),view->getString("TrainingStr23"), GTK_MESSAGE_INFO);
439  if(tab->interface!=NULL)
440  tab->interface->selectTrainingClass(-1);
441  tab->enableControls();
442  model->trainingStop();
443  tab->updateView();
444  tab->getView()->updateInfoBar();
445  return false;
446  }
447  else
448  {
449  return true;
450  }
451 }
452 
453 //----------------------------------------
454 // Enable and disable controls
455 void TabTraining::disableControls()
456 {
457  gtk_widget_set_sensitive(btn_stop,true);
458  gtk_widget_set_sensitive(btn_start,false);
459  gtk_widget_set_sensitive(source_combo,false);
460  gtk_widget_hide(controls_hbox2);
461  gtk_widget_hide(controls_hbox3);
462  gtk_widget_hide(controls_hbox4);
463  gtk_widget_hide(info_frame2);
464 }
465 
466 void TabTraining::enableControls()
467 {
468  gtk_widget_set_sensitive(btn_stop,false);
469  gtk_widget_set_sensitive(btn_start,true);
470  gtk_widget_set_sensitive(source_combo,true);
471  gtk_widget_show(controls_hbox2);
472  gtk_widget_show(controls_hbox3);
473  gtk_widget_show(controls_hbox4);
474  gtk_widget_show(info_frame2);
475  view->getStatusBar()->remove(status_id);
476 }
477 
478 //----------------------------------------
479 
480 //update the model from the widgets
482 {
483 
484 }
485 
486 // when the tab becomes hidden, this function is run
488 {
489  this->CB_stopTraining(NULL,this);
490  if(this->interface != NULL)
491  {
492  this->interface->hide();
493  gtk_container_remove(GTK_CONTAINER(this->interface_box),this->interface->getContainer());
494  }
495  this->interface = NULL;
496  this->enableControls();
497  view->updateInfoBar();
498  CEBL::Param param = CEBL::Param("classes","classes", view->getModel()->trainingGetNumClasses());
499  view->getModel()->classifierReset(param);
500 }
501 
502 
503 //----------------------------------------------------------------------
504 // CALLBACKS
505 
506 void TabTraining::CB_startTraining(GtkWidget *w, gpointer data)
507 {
508  TabTraining * tab = (TabTraining*)data;
509  CEBLViewGTK * view = tab->getView();
510  try
511  {
512  tab->getView()->getModel()->trainingStart();
513  }
514  catch(exception & e)
515  {
516  string msg = view->getString("TrainingStr24") + string(e.what()) + ")";
517  WidgetUtils::AlertError(view->getString("TrainingStr25"), msg);
518  return;
519  }
520  tab->training_stopped_manually = false;
521  tab->disableControls();
522  g_timeout_add(50, timedUpdateInterface, tab);
523 }
524 
525 void TabTraining::CB_stopTraining(GtkWidget *w, gpointer data)
526 {
527  TabTraining * tab = (TabTraining*)data;
528  tab->getView()->getModel()->trainingStop();
529  if(tab->interface != NULL)
530  tab->interface->selectTrainingClass(-1);
531  tab->training_stopped_manually = true;
532 }
533 
534 void TabTraining::CB_changeNumClasses(GtkWidget *w, gpointer data)
535 {
536  TabTraining * tab = (TabTraining*)data;
537  if(!tab->updating_view)
538  {
539  int n = int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(tab->spin_classes)));
540  tab->getView()->getModel()->trainingSetNumClasses(n);
541  tab->updateInterface();
542  tab->updateTextInfo();
543  tab->getView()->updateInfoBar();
544  }
545 }
546 void TabTraining::CB_changeNumSequences(GtkWidget *w, gpointer data)
547 {
548  TabTraining * tab = (TabTraining*)data;
549  if(!tab->updating_view)
550  {
551  int n = int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(tab->spin_sequences)));
553  tab->updateTextInfo();
554  }
555 }
556 void TabTraining::CB_changeSequenceLength(GtkWidget *w, gpointer data)
557 {
558  TabTraining * tab = (TabTraining*)data;
559  if(!tab->updating_view)
560  {
561  int n = int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(tab->spin_sequence_length)));
563  tab->updateTextInfo();
564  }
565 }
566 
567 
568 void TabTraining::CB_changePauseLength(GtkWidget *w, gpointer data)
569 {
570  TabTraining * tab = (TabTraining*)data;
571  if(!tab->updating_view)
572  {
573  int n = int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(tab->spin_pause_length)));
575  tab->updateTextInfo();
576  }
577 }
578 
579 
580 
581 void TabTraining::CB_loadData(GtkWidget *w, gpointer data)
582 {
583  TabTraining * tab = (TabTraining*)data;
584  CEBLViewGTK * view = tab->getView();
585 
586  if(tab->getView()->getModel()->trainingDataIsLoaded())
587  {
588 
589  if(!WidgetUtils::Confirm("Replace Data?", "You already have training data loaded. If you load training data, any unsaved training data will be lost."))
590  return;
591  }
592  string filename = WidgetUtils::selectLoadFile();
593  if(filename != "")
594  {
595  view->getModel()->trainingLoadData(filename);
596  }
597  tab->updateView();
598 }
599 
600 void TabTraining::CB_saveData(GtkWidget *w, gpointer data)
601 {
602  TabTraining * tab = (TabTraining*)data;
603  CEBLViewGTK * view = tab->getView();
604  if(tab->getView()->getModel()->trainingDataIsLoaded())
605  {
606  string filename = WidgetUtils::selectSaveFile("tar.bz2");
607  if(filename != "")
608  {
609  try
610  {
611  tab->getView()->getModel()->trainingSaveData(filename);
612  }
613  catch(exception &e)
614  {
615  string msg = "Failed to save training data: " + string(e.what());
616  WidgetUtils::AlertError("Failed to save data.",msg);
617  }
618  }
619  }
620  else
621  {
622  WidgetUtils::AlertError(view->getString("TrainingStr26"),view->getString("TrainingStr27"));
623  }
624 
625 }
626 
627 
628 
629 
630 //update all the channel values in the model from gui
631 void TabTraining::CB_toggleClassificationFeedback(GtkWidget *w, gpointer data)
632 {
633  TabTraining *tab = (TabTraining*)(data);
634  //return if callback is suppressed
635  if(!tab->updating_view)
636  {
637  bool checked =
638  gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(tab->check_classification_feedback));
639  tab->getView()->getModel()->trainingSetFeedbackEnabled(checked);
640  }
641 }