CEBL  2.1
TabFilter.cpp
Go to the documentation of this file.
1 
7 #include "TabFilter.hpp"
8 #include "WidgetUtils.hpp"
9 #include "EEGMonitor.hpp"
10 
11 //----------------------------------------------------------------------
12 // Constructors / Destructor
13 
14 
16 {
17 
18 }
19 
20 
21 //----------------------------------------------------------------------
22 // Create the GUI
23 
24 
26 {
27  //add title
28  GtkWidget *title = gtk_label_new("");
29  gtk_label_set_markup(GTK_LABEL(title),"<big>Filter</big>");
30  TabAdd(title);
31  TabAdd(gtk_hseparator_new());
32 
33 
34 
35  this->updating_view = true;
36  this->num_filters = 0;
37  this->selected_filter = "";
38  this->is_collecting = false;
39  this->training_collected = false;
40  this->num_seconds = 7;
41  //-------------------------------------------------
42  //Filter Selection
43  GtkWidget *hbox_filters = gtk_hbox_new(false, 0);
44 
45  combo_filters = gtk_combo_box_new_text();
46 
47  //configure the combo box and add callback
48  gtk_combo_box_set_active(GTK_COMBO_BOX(combo_filters),0);
49  g_signal_connect(G_OBJECT(combo_filters),
50  "changed",
51  G_CALLBACK(CB_changeFilter),
52  (gpointer) this);
53 
54  gtk_box_pack_start(GTK_BOX(hbox_filters), combo_filters, false, false, 0);
55 
56  //is_made check box
57  check_filter_made = gtk_check_button_new_with_label("Filter Made");
58  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_filter_made),false);
59  gtk_widget_set_sensitive(check_filter_made,false);
60 
61  gtk_box_pack_end(GTK_BOX(hbox_filters),check_filter_made,false, false, 0);
62 
63 
64  TabAdd(hbox_filters);
65 
66  //boxes
67  btn_box1 = gtk_hbutton_box_new();
68  gtk_button_box_set_layout(GTK_BUTTON_BOX(btn_box1),GTK_BUTTONBOX_START);
69  GtkWidget *hbox1 = gtk_hbox_new(false,0);
70  GtkWidget *hbox2 = gtk_hbox_new(false,0);
71 
72  btn_box2 = gtk_hbutton_box_new();
73  gtk_button_box_set_layout(GTK_BUTTON_BOX(btn_box2),GTK_BUTTONBOX_START);
74 
75  btn_box3 = gtk_hbutton_box_new();
76  gtk_button_box_set_layout(GTK_BUTTON_BOX(btn_box3),GTK_BUTTONBOX_START);
77 
78 
79 
80 
81  //buttons and other widgets
82 
83  btn_collect = gtk_button_new_with_label("Collect Training Data");
84  g_signal_connect(G_OBJECT(btn_collect),
85  "clicked",
86  G_CALLBACK(CB_collectData),
87  (gpointer) this);
88  spin_seconds = gtk_spin_button_new_with_range(1,30,1);
89  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_seconds),num_seconds);
90  g_signal_connect(G_OBJECT(spin_seconds),
91  "value-changed",
92  G_CALLBACK(CB_changeNumSeconds),
93  (gpointer) this);
94  gtk_widget_set_size_request(spin_seconds, 40,25);
95 
96 
97  btn_show = gtk_button_new_with_label("Show Components");
98  spin_lags = gtk_spin_button_new_with_range(0,50,1);
99  gtk_widget_set_size_request(spin_lags,40,25);
100 
101  g_signal_connect(G_OBJECT(spin_lags),
102  "value-changed",
103  G_CALLBACK(CB_changeNumLags),
104  (gpointer) this);
105 
106  g_signal_connect(G_OBJECT(btn_show),
107  "clicked",
108  G_CALLBACK(CB_showComponents),
109  (gpointer) this);
110 
111 
112  entry_components = gtk_entry_new();
113  g_signal_connect(G_OBJECT(entry_components),
114  "changed",
115  G_CALLBACK(CB_selectComponents),
116  (gpointer) this);
117 
118 
119  label_selected = gtk_label_new("(not set)");
120  gtk_label_set_max_width_chars(GTK_LABEL(label_selected),35);
121 
122 
123  //create filter
124  btn_create_filter = gtk_button_new_with_label("Create Filter");
125  g_signal_connect(G_OBJECT(btn_create_filter),
126  "clicked",
127  G_CALLBACK(CB_createFilter),
128  (gpointer) this);
129 
130  //pack widgets
131  gtk_box_pack_start(GTK_BOX(btn_box3),gtk_label_new("Seconds to collect: "), false, false, 0);
132  gtk_box_pack_start(GTK_BOX(btn_box3),spin_seconds, false, false, 0);
133  gtk_box_pack_start(GTK_BOX(btn_box3),btn_collect, false, false, 0);
134  gtk_box_pack_start(GTK_BOX(hbox1),gtk_label_new("Lags: "), false, false, 0);
135  gtk_box_pack_start(GTK_BOX(hbox1),spin_lags, false, false, 0);
136  gtk_box_pack_start(GTK_BOX(hbox1),gtk_label_new(" "), false, false, 0);
137  gtk_box_pack_start(GTK_BOX(hbox1),btn_show, false, false, 0);
138  gtk_box_pack_start(GTK_BOX(hbox2),gtk_label_new("Select Components (e.g. 1,3,6:9): "), false, false, 0);
139  gtk_box_pack_start(GTK_BOX(hbox2),entry_components, false, false, 0);
140  gtk_box_pack_start(GTK_BOX(hbox2),gtk_label_new(" = "), false, false, 0);
141  gtk_box_pack_start(GTK_BOX(hbox2),label_selected, false, false, 0);
142  gtk_box_pack_start(GTK_BOX(btn_box2),btn_create_filter, false, false, 0);
143 
144  //put all boxes into one and add it to the tab
145  GtkWidget * btn_boxes = gtk_vbox_new(false,0);
146  gtk_box_pack_start(GTK_BOX(btn_boxes), btn_box3, false, false, 0);
147  gtk_box_pack_start(GTK_BOX(btn_boxes), hbox1, false, false, 1);
148  gtk_box_pack_start(GTK_BOX(btn_boxes), btn_box1, false, false, 0);
149  gtk_box_pack_start(GTK_BOX(btn_boxes), hbox2, false, false, 0);
150  gtk_box_pack_start(GTK_BOX(btn_boxes), btn_box2, false, false, 0);
151  TabFrameAdd(btn_boxes,"Filter Configuration");
152 
153  //plot
154  plot = NULL;
155 
156  gtk_widget_set_sensitive(btn_create_filter,false);
157 
158  this->updating_view = false;
159 
160  updateView();
161 
162  if(gtk_combo_box_get_active(GTK_COMBO_BOX(combo_filters))==-1)
163  gtk_combo_box_set_active(GTK_COMBO_BOX(combo_filters),0);
164 }
165 
166 
167 //update view from model
168 
170 {
171 
172  //set flag to indicate process of updating view
173  //in order to stop callbacks from triggering
174  this->updating_view = true;
175 
176 
177  //get information from model about filters
178  CEBLModel * model = getView()->getModel();
179  std::vector<string> names = model->filterGetNameList();
180  std::vector<string> paths = model->filterGetPathList();
181  string model_selected_filter = model->filterGetSelected();
182 
183  //if the model's filters have changed or the selected filter has changed
184  //update the filter list
185  if(names != this->filter_names
186  || this->selected_filter != model_selected_filter)
187  {
188  this->selected_filter = model_selected_filter;
189  this->filter_names = names;
190  for(int i = this->num_filters-1; i >= 0; i--)
191  {
192  gtk_combo_box_remove_text(GTK_COMBO_BOX(combo_filters),i);
193  }
194  this->num_filters = names.size();
195 
196  // add in all filters
197  for(unsigned int i=0;i<names.size();i++)
198  {
199  gtk_combo_box_append_text(GTK_COMBO_BOX(combo_filters),
200  names[i].c_str());
201  if(names[i]==model_selected_filter)
202  {
203  gtk_combo_box_set_active(GTK_COMBO_BOX(combo_filters),i);
204  }
205  }
206  }//end of conditional concerning whether update should occur
207 
208  //get number of lags
209  int n = model->filterGetNumLags();
210  gtk_spin_button_set_value(GTK_SPIN_BUTTON(spin_lags),n);
211 
212  //get components string
213  string comps = model->filterGetSelectedComponentsString();
214  gtk_label_set_text(GTK_LABEL(label_selected),comps.c_str());
215 
216  //set entry if it is different from the currently selected components
217  string input = string(gtk_entry_get_text(GTK_ENTRY(entry_components)));
218  model->filterSetSelectedComponentsString(input);
219  string comps2 = model->filterGetSelectedComponentsString();
220  if(comps != comps2)
221  {
222  comps = model->filterGetSelectedComponentsString();
224  {
225  gtk_entry_set_text(GTK_ENTRY(entry_components),comps.c_str());
226  }
227  }
228 
229  //update sensitivity on create filter button, and filter trained box
230  bool components_valid = model->filterGetSelectedComponentsValid();
231  gtk_widget_set_sensitive(btn_create_filter,components_valid);
232 
233  bool filter_made = model->filterIsTrained();
234  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(check_filter_made),
235  filter_made);
236 
237 
238  this->updating_view = false;
239 
240 }
241 
242 //update the model from the widgets
244 {
245 
246 }
247 
248 //----------------------------------------------------------------------
249 // PLOTTING
250 
252 void TabFilter::createPlot(int num_channels)
253 {
254  if(plot==NULL)
255  {
256  plot = new EEGMonitor(this, num_channels);
257  plot->setZoom(10);
258  TabAdd(*plot, true, true, 0);
259  }
260  else
261  {
262  plot->reInitPlot(num_channels);
263  plot->setZoom(10);
264  }
265 }
266 
267 //----------------------------------------------------------------------
268 // COLLECTING
269 
270 void TabFilter::startCollect()
271 {
272  if(!this->is_collecting)
273  {
274  this->training_data.clear();
275  this->training_collected = false;
276  CEBLModel * model = this->getView()->getModel();
277  try {
278  model->dataStart();
279  } catch(exception & e) {
280  string msg = "There was an error starting the data source. \n("+string(e.what())+")";
281  WidgetUtils::AlertError("Error Starting Data Source",msg);
282  return;
283  }
284  this->is_collecting = true;
285  //show wait box
286  WidgetUtils::waitBoxShow("Collecting Data");
289  int num_samples = 0;
290  int display_step = 64;
291  this->collect_timer.restart();
292  double percent;
293  while(this->is_collecting)
294  {
295  gtk_main_iteration();
297  {
298  gtk_main_iteration();
299  try {
300  model->dataStop();
301  } catch(exception & e){}
302 
303  this->is_collecting = false;
304  }
305  else
306  {
307  try {
308  this->training_data.append(model->dataReadAll());
309  } catch(exception & e) {}
310  int new_samples = training_data.size2();
311  double elapsed = collect_timer.elapsed() / 1000.0;
312  if(new_samples - num_samples > display_step)
313  {
314  num_samples = new_samples;
315  percent = elapsed/num_seconds;
316  if(elapsed >= num_seconds)
317  {
318  this->is_collecting = false;
319  this->training_collected = true;
320  model->dataStop();
321  this->CB_showComponents(NULL,this);
322  }
323  else
324  {
325  stringstream msg;
326 
327  msg << int(elapsed) << " of " << num_seconds << " seconds\n";
328  msg << num_samples << " samples";
329 
330  WidgetUtils::waitBoxSetText(msg.str().c_str());
332  }
333  }
334  }
335  }
337  }
338 }
339 
340 void TabFilter::stopCollect()
341 {
342  if(this->is_collecting)
343  {
344 
345  this->is_collecting = false;
346  }
347 }
348 
349 //----------------------------------------------------------------------
350 // CALLBACKS
351 
352 
353 void TabFilter::CB_selectComponents(GtkWidget *w, gpointer data)
354 {
355  TabFilter * filter = (TabFilter *) data;
356  if(!filter->updating_view)
357  {
358  string input = string(gtk_entry_get_text(GTK_ENTRY(w)));
360 
361  filter->updateView();
362  }
363 }
364 
365 
366 void TabFilter::CB_showComponents(GtkWidget *w, gpointer data)
367 {
368  TabFilter * tab = (TabFilter*) data;
369  CEBLModel * model = tab->getView()->getModel();
370  if(!tab->training_collected || tab->is_collecting)
371  {
372  string msg = "Failed to extract components. Collect data first!";
373  WidgetUtils::AlertError("Failed to extract components. ", msg);
374  return;
375  }
376 
377 
378  try
379  {
380  WidgetUtils::waitBoxShow("Extracting components...",false);
381  EEGData components = model->filterGetComponents(tab->training_data);
382  tab->createPlot(components.size1());
383  tab->plot->setNumDisplaySamples(components.numSamples());
384  tab->plot->Plot(components);
386  }
387  catch(PluginException e)
388  {
390  string msg = "Failed to extract components. \n(" + string(e.what()) + ")";
391  WidgetUtils::AlertError("Failed to extract components. ", msg);
392  }
393  catch(exception &e)
394  {
396  string msg = "Failed to extract components. \n(" + string(e.what()) + ")";
397  WidgetUtils::AlertError("Failed to extract components. ", msg);
398  }
399 }
400 
401 
402 void TabFilter::CB_createFilter(GtkWidget *w, gpointer data)
403 {
404  TabFilter * tab = (TabFilter*) data;
405  try
406  {
407  tab->getView()->getModel()->filterTrain(tab->training_data);
408  }
409  catch(exception &e)
410  {
411  string msg = "Failed to make filter. \n(" + string(e.what()) + ")";
412  WidgetUtils::AlertError("Failed to make filter. ", msg);
413  }
414  tab->updateView();
415 }
416 
417 void TabFilter::CB_changeFilter(GtkWidget *w, gpointer data)
418 {
419  TabFilter * tab = (TabFilter*) data;
420  //as long as the update view is not currently running,
421  //set the model's selected filter to the selected filter
422  //in combo box
423  if(tab->num_filters > 0 && !tab->updating_view)
424  {
425  string filter =
426  gtk_combo_box_get_active_text(GTK_COMBO_BOX(tab->combo_filters));
427  try
428  {
429  if(filter != tab->selected_filter)
430  {
431  // set the selected filter in the model
432  tab->getView()->getModel()->filterSetSelected(filter);
433  }
434  }
435  catch(...)
436  {
437  cerr << "Error selecting filter.\n";
438  }
439  tab->updateView();
440  }
441 }
442 
443 void TabFilter::CB_changeNumLags(GtkWidget *w, gpointer data)
444 {
445  TabFilter * tab = (TabFilter*) data;
446  if(!tab->updating_view)
447  {
448  int n = int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(tab->spin_lags)));
449  tab->getView()->getModel()->filterSetNumLags(n);
450  }
451 }
452 
453 void TabFilter::CB_changeNumSeconds(GtkWidget *w, gpointer data)
454 {
455  TabFilter * tab = (TabFilter*) data;
456  if(!tab->updating_view)
457  {
458  tab->num_seconds = int(gtk_spin_button_get_value(GTK_SPIN_BUTTON(tab->spin_seconds)));
459  }
460 }
461 
462 
463 void TabFilter::CB_collectData(GtkWidget *w, gpointer data)
464 {
465  TabFilter * tab = (TabFilter*) data;
466  if(!tab->is_collecting)
467  tab->startCollect();
468 }
469 
470