CEBL  2.1
EEGPlot.cpp
Go to the documentation of this file.
1 
8 #include "EEGPlot.hpp"
9 #include <iostream>
10 using namespace std;
11 
12 const char *PLOT_COLORS[] = {"black",
13  "red",
14  "darkorange",
15  "purple",
16  "darkgreen",
17  "brown",
18  "darkblue",
19  "violet",
20  "darkred",
21  "orange",
22  "darkbrown",
23  "blue",
24  "darkviolet"};
25 const int NUM_PLOT_COLORS = 13;
26 
27 
28 
29 
30 //Constructor
31 EEGPlot::EEGPlot(int num_channels)
32 {
33  this->num_channels = num_channels;
34  this->num_plotted_channels = 0;
35 
36  //create the buffers for data points
37  px = new double*[num_channels];
38  py = new double*[num_channels];
39  datasets = new GtkPlotData*[num_channels];
40  for(int channel=0;channel<num_channels;channel++)
41  {
42  datasets[channel] = GTK_PLOT_DATA(gtk_plot_data_new());
43  px[channel] = NULL;
44  py[channel] = NULL;
45  }
46 
47  current_plot = NULL;
48 
49  //default configuration
50  this->num_samples = 0;
51  this->window_width = 500;
52  this->window_height = 500;
53  this->num_display_samples = 400;
54  this->zoom = 1.0;
55  this->num_layers = 0;
56  this->ymax = 1000;
57  this->initialized = false;
58  this->redraw_timeout_id = -1;
59 }
60 //Destructor
62 {
63  if(this->redraw_timeout_id >= 0)
64  gtk_timeout_remove(this->redraw_timeout_id);
65 
66  for(int channel=0;channel<num_channels;channel++)
67  {
68  if(px != NULL && px[channel] != NULL)
69  delete[] px[channel];
70  if(py != NULL && py[channel] != NULL)
71  delete[] py[channel];
72  }
73  if(px!=NULL)
74  delete[] px;
75  if(py!=NULL)
76  delete[] py;
77  if(datasets!=NULL)
78  delete[] datasets;
79 }
80 
81 //creates a new plot layer
82 GtkWidget *EEGPlot::newLayer(GtkWidget *canvas)
83 {
84  num_layers++;
85  return gtk_plot_new_with_size(NULL, .65, .45);
86 }
87 
88 //get the vbox widget
89 EEGPlot::operator GtkWidget*()
90 {
91  return vbox_container;
92 }
93 
94 
95 //sets channel labels
96 void EEGPlot::setLabels(std::vector<std::string> labels)
97 {
98  this->labels = labels;
99 }
100 
101 //-----------------------------------------------
102 //initialize the plot
104 {
105  GdkColor color;
106  //gfloat scale = 1.0;
107  gint page_width = int(this->window_width);
108  gint page_height = int(this->window_height * 0.9);
109 
110  //create container
111  this->vbox_container = gtk_vbox_new(FALSE,0);
112  gtk_widget_show(this->vbox_container);
113 
114  //create canvas
115  this->canvas = gtk_plot_canvas_new(page_width,page_height, 1.);
116  GTK_PLOT_CANVAS_UNSET_FLAGS(GTK_PLOT_CANVAS(canvas), GTK_PLOT_CANVAS_DND_FLAGS);
117  gtk_box_pack_start(GTK_BOX(vbox_container),canvas, TRUE, TRUE, 0);
118  gtk_widget_show(canvas);
119 
120  //background color
121  gdk_color_parse("white", &color);
122  color.red = BG_RED;
123  color.green = BG_GREEN;
124  color.blue = BG_BLUE;
125 
126  gdk_color_alloc(gtk_widget_get_colormap(canvas), &color);
127  gtk_plot_canvas_set_background(GTK_PLOT_CANVAS(canvas), &color);
128 
129  //create plot
130  this->current_plot = newLayer(canvas);
131  gdk_color_alloc(gtk_widget_get_colormap(current_plot), &color);
132  gtk_plot_set_background(GTK_PLOT(current_plot), &color);
133 
134  //range and ticks
135  gtk_plot_set_ticks(GTK_PLOT(current_plot), GTK_PLOT_AXIS_X, 20, 1);
136  gtk_plot_set_ticks(GTK_PLOT(current_plot), GTK_PLOT_AXIS_Y, 40, 1);
137  gtk_plot_set_xrange(GTK_PLOT(current_plot), 0, getDisplaySamples());
138  gtk_plot_set_yrange(GTK_PLOT(current_plot), 0, this->ymax);
139 
140  gtk_plot_axis_show_ticks(gtk_plot_get_axis(GTK_PLOT(current_plot),GTK_PLOT_AXIS_RIGHT), false, false);
141  gtk_plot_axis_show_ticks(gtk_plot_get_axis(GTK_PLOT(current_plot),GTK_PLOT_AXIS_LEFT), false, false);
142  gtk_plot_axis_set_tick_labels(gtk_plot_get_axis(GTK_PLOT(current_plot),GTK_PLOT_AXIS_LEFT), NULL);
143 
144  //hide tick labels
145  gtk_plot_axis_show_labels(gtk_plot_get_axis(GTK_PLOT(current_plot),GTK_PLOT_AXIS_LEFT), 0);
146  gtk_plot_axis_show_labels(gtk_plot_get_axis(GTK_PLOT(current_plot),GTK_PLOT_AXIS_RIGHT), 0);
147 
148  //axis
149  gtk_plot_axis_set_visible(gtk_plot_get_axis(GTK_PLOT(current_plot), GTK_PLOT_AXIS_TOP), FALSE);
150  gtk_plot_axis_set_visible(gtk_plot_get_axis(GTK_PLOT(current_plot), GTK_PLOT_AXIS_RIGHT), FALSE);
151  gtk_plot_axis_set_visible(gtk_plot_get_axis(GTK_PLOT(current_plot), GTK_PLOT_AXIS_BOTTOM), FALSE);
152  gtk_plot_axis_set_visible(gtk_plot_get_axis(GTK_PLOT(current_plot), GTK_PLOT_AXIS_LEFT), FALSE);
153 
154  //axis name
155  gtk_plot_axis_set_title(gtk_plot_get_axis(GTK_PLOT(current_plot), GTK_PLOT_AXIS_LEFT), "");
156  gtk_plot_axis_move_title(gtk_plot_get_axis(GTK_PLOT(current_plot),GTK_PLOT_AXIS_LEFT),0,.145,.4);
157 
158  //hide grids
159  //vertical,vertical dotted,horizontal,horizontal dotted
160  gtk_plot_grids_set_visible(GTK_PLOT(current_plot), FALSE, TRUE, FALSE, FALSE);
161 
162  //show the plot
163  gtk_widget_show(current_plot);
164 
165  //legends
166  gtk_plot_hide_legends(GTK_PLOT(current_plot));
167 
168  //create lines
169  this->lines = gtk_plot_canvas_plot_new(GTK_PLOT(current_plot));
170 
171  //placement of lines
172  x1 = .05;
173  x2 = .95;
174  y1 = .05;
175  y2 = .99;
176  gtk_plot_canvas_put_child(GTK_PLOT_CANVAS(canvas), lines, x1, y1, x2, y2);
177  GtkPlotCanvasChild *child;
178 
179  for(int channel=0;channel<this->num_channels;channel++)
180  {
181  //labels
182  gtk_plot_data_show_labels(datasets[channel], FALSE);
183 
184 
185  gdk_color_parse(PLOT_COLORS[channel%NUM_PLOT_COLORS], &color);
186  gdk_color_alloc(gdk_colormap_get_system(), &color);
187  gtk_plot_data_set_line_attributes(datasets[channel],
188  GTK_PLOT_LINE_SOLID,
189  GDK_CAP_NOT_LAST, GDK_JOIN_MITER, 1, &color);
190 
191  //add label to plot
192  double text_size = window_width/90.0;
193  double x_pos = 0.02;
194  double y_pos = (double(channel)/num_channels) * .953 + 0.05;
195  string label;
196  if(unsigned(channel) < labels.size())
197  label = labels[channel];
198  else
199  label = "unnamed";
200  //don't allow empty labels
201  if(label == "")
202  label = "unnamed";
203 
204  child = gtk_plot_canvas_text_new("Times-Roman", (int)text_size, 0, NULL, NULL, TRUE,
205  GTK_JUSTIFY_CENTER,
206  label.c_str());
207 
208  gtk_plot_canvas_put_child(GTK_PLOT_CANVAS(canvas), child, x_pos, y_pos, 0, 0);
209 
210  //add data to plot and show
211  gtk_plot_add_data(GTK_PLOT(current_plot), datasets[channel]);
212  gtk_widget_show(GTK_WIDGET(datasets[channel]));
213  }
214  //paint canvas
215  gtk_plot_canvas_paint(GTK_PLOT_CANVAS(canvas));
216  gtk_plot_canvas_refresh(GTK_PLOT_CANVAS(canvas));
217  this->initialized = true;
218 }
219 
220 
221 
222 
223 //-----------------------------------------------------------
224 
226 {
227  this->num_display_samples = n;
228  if(this->initialized)
229  {
230  this->queueRedraw();
231  }
232 }
233 
234 //-----------------------------------------------------------
235 
236 void EEGPlot::setZoom(double zoom)
237 {
238  if(zoom == this->zoom)
239  {
240  return;
241  }
242 
243  //set the zoom
244  this->zoom = zoom;
245  if(zoom <= 0.01)
246  zoom = 0.01;
247 
248  //TODO set the data points and replot
249 
250 
251 
252  //queue a redraw
253  if(this->initialized)
254  {
255  this->queueRedraw();
256  }
257 }
258 
259 //-----------------------------------------------------------
260 
261 void EEGPlot::plot(ublas::matrix<double> data)
262 {
263 
264  if(data.size1() <= 0 || data.size2() <= 0)
265  return;
266 
267 
268  if(data.size1() > 72){
269  data.resize(72,data.size2());
270  // cerr << "ERROR trying to plot too many channels. Reducing to 72.\n";
271  }
272  //----------------------------------------
273  //select how many samples are going to be displayed
274 
275  int size;
276  int max_samples = getDisplaySamples();
277  int orig_size = num_samples;
278  int num_new_samples = data.size2();
279  int num_old_samples = num_samples;
280 
281  num_samples += num_new_samples;
282  if(num_samples > max_samples)
283  {
284  num_old_samples = max_samples-num_new_samples;
285  if(num_new_samples > max_samples)
286  {
287  num_new_samples = max_samples;
288  num_old_samples = 0;
289  }
290  size = max_samples;
291  }
292  else
293  {
294  size = num_samples;
295  }
296  num_samples = size;
297 
298  //----------------------------------------
299  //plot the data
300  //std::cout << "Recieved " << data.size2() << " samples. \n";
301 
302  //std::cout << "Using " << num_old_samples << " old samples. \n";
303  //std::cout << "Using " << num_new_samples << " new samples. \n";
304  //std::cout << "Size = " << size << ". \n";
305 
306  int nchannels = num_channels;
307  if(unsigned(num_channels) > data.size1())
308  nchannels = data.size1();
309  this->num_plotted_channels = nchannels;
310 
311  double ymax = this->ymax;
312  double yscale = zoom * 5.0 / (num_channels * .2);
313  double yoffset = ymax/nchannels;
314  double *px_new,*py_new;
315  int new_array_counter;
316  for(int channel=0;channel<nchannels;channel++)
317  {
318  px_new = new double[size];
319  py_new = new double[size];
320 
321  //copy over old data
322  new_array_counter = 0;
323  for(int i = orig_size-num_old_samples;
324  i < orig_size;
325  i++)
326  {
327  py_new[new_array_counter] = py[channel][i];
328  px_new[new_array_counter] = (new_array_counter+1);
329  new_array_counter++;
330  }
331 
332  //copy over new data
333  for(unsigned int i = data.size2() - num_new_samples;
334  i < data.size2();
335  i++)
336  {
337  py_new[new_array_counter] = data(channel,i)*yscale + ((nchannels-channel))*yoffset;
338  px_new[new_array_counter] = new_array_counter;
339  new_array_counter++;
340  }
341 
342  //delete old arrays over arrays
343  if(px != NULL && px[channel] != NULL)
344  delete[] px[channel];
345  if(py != NULL && py[channel] != NULL)
346  delete[] py[channel];
347 
348  //copy over new data
349  px[channel] = px_new;
350  py[channel] = py_new;
351  }
352  this->redraw();
353 }
354 
355 //--------------------------------------------------
356 
358 {
359  if(this == NULL || current_plot == NULL)
360  return;
361 
362  if(this->redraw_timeout_id >= 0)
363  gtk_timeout_remove(this->redraw_timeout_id);
364 
365  gtk_plot_set_xrange(GTK_PLOT(current_plot), 0, this->num_display_samples);
366  int dataset_index;
367  for(int channel=0;channel<this->num_plotted_channels;channel++)
368  {
369 
370  dataset_index = channel;//this->num_plotted_channels - 1 - channel;
371 
372  gtk_plot_data_set_numpoints(datasets[dataset_index], num_samples);
373  gtk_plot_data_set_x(datasets[dataset_index], px[channel]);
374  gtk_plot_data_set_y(datasets[dataset_index], py[channel]);
375  }
376  gtk_plot_canvas_paint(GTK_PLOT_CANVAS(canvas));
377  gtk_plot_canvas_refresh(GTK_PLOT_CANVAS(canvas));
378 }
379 
380 
381 //--------------------------------------------------
382 
384 {
385  if(this->redraw_timeout_id < 0)
386  {
387  this->redraw_timeout_id = gtk_timeout_add(200, timedRedraw, this);
388  }
389  else
390  {
391  gtk_timeout_remove(this->redraw_timeout_id);
392  this->redraw_timeout_id = gtk_timeout_add(200, timedRedraw, this);
393  }
394 }
395 //--------------------------------------------------
396 
398 void EEGPlot::setWindowWidth(double width)
399 {
400  if(width <= 1224)
401  this->window_width = width;
402  else
403  this->window_width = 1224;
404 }
405 
407 void EEGPlot::setWindowHeight(double height)
408 {
409  if(height <= 1024)
410  this->window_height = height;
411  else
412  this->window_height = 1024;
413 }
414 
415 //--------------------------------------------------
416 
417 gint EEGPlot::timedRedraw(gpointer data)
418 {
419  EEGPlot *plot = (EEGPlot*)data;
420  plot->redraw();
421  return 0;
422 }
423