Empirical
visualizations.h
Go to the documentation of this file.
1 
10 #ifndef EMP_VISUALIZATION_UTILS_H
11 #define EMP_VISUALIZATION_UTILS_H
12 
13 #include <functional>
14 #include <algorithm>
15 #include <deque>
16 
17 #include "../../config/config.h"
18 #include "../../tools/BitSet.h"
19 #include "../../tools/Random.h"
20 #include "../../tools/stats.h"
21 #include "../../tools/string_utils.h"
22 #include "../../tools/FunctionSet.h"
23 #include "../../tools/const.h"
24 
25 #include "../init.h"
26 #include "../Animate.h"
27 #include "../JSWrap.h"
28 
29 #include "selection.h"
30 #include "scales.h"
31 #include "axis.h"
32 #include "svg_shapes.h"
33 #include "layout.h"
34 #include "visual_elements.h"
35 #include "histogram.h"
36 
37 //Pretty sure D3VisualizationInfo can't be shared among multiple D3Visualizations
38 
39 namespace emp{
40 namespace web{
41 class D3Visualization : public internal::WidgetFacet<D3Visualization> {
42  friend class D3VisualizationInfo;
43 protected:
45  friend D3Visualization;
46 
47  protected:
48  int width;
49  int height;
52 
53  D3VisualizationInfo(D3Visualization * parent, const std::string & in_id="") : internal::WidgetInfo(in_id) {
54  this->parent = parent;
55  }
56 
57  D3VisualizationInfo(const D3VisualizationInfo &) = delete;
59  virtual ~D3VisualizationInfo(){;}
60 
61  virtual bool IsD3VisualiationInfo() const override {return true;}
62 
63  virtual void GetHTML(std::stringstream & HTML) override {
64  HTML.str("");
65  HTML << "<svg id=\"" << id
66  << "\" width=\"" << width
67  << "\" height=\"" << height << "\">";
68 
69  HTML << "</svg>";
70  }
71 
72  // Trigger any JS code needed on re-draw.
73  void TriggerJS() override {
74  if (state == Widget::ACTIVE) { // Only draw on active canvases
75  svg = D3::Selection("#"+id);
76  parent->Setup();
77  }
78  }
79 
80  public:
81  virtual std::string GetType() override {return "web::D3VisualizationInfo";}
82 
83  };
84 
85  // Get a properly cast version of indo.
87  const D3VisualizationInfo * Info() const { return (D3VisualizationInfo *) info; }
88 
89  D3Visualization(D3VisualizationInfo * in_info) : WidgetFacet(in_info) { ; }
90 
91  double axis_width = 60;
92  double y_margin = 10;
93  double x_margin = 30;
94 
95 public:
96 
97  D3Visualization(int w, int h, const std::string & in_id="")
98  : WidgetFacet(in_id) {
99  #ifdef EMSCRIPTEN
100  n_objects();
101  #endif
102 
103  info = new D3VisualizationInfo(this, in_id);
104  Info()->width = w;
105  Info()->height = h;
106  EM_ASM({window["emp"]["__default_draw_data_callback"] =
107  function(){;};});
108  }
109 
112  virtual ~D3Visualization() { ; }
113 
115 
116  int GetWidth() const { return Info()->width; }
117  int GetHeight() const { return Info()->height; }
118  D3::Selection * GetSVG() {return &(Info()->svg);}
119  std::string GetID() {return Info()->id;}
120 
123  bool init = false;
124 
126  std::string draw_data_callback = "__default_draw_data_callback";
127 
128  virtual void Setup(){}
129 
131  template <typename T>
133  SetDrawCallback(T func) {
134  emp::JSWrap(func, GetID()+"draw_data_callback");
135  draw_data_callback = GetID()+"draw_data_callback";
136  }
138 
142  void SetDrawCallback(std::string func) {
143  draw_data_callback = func;
144  }
145 
147  EM_ASM_ARGS({window["emp"][Pointer_stringify($0)]()}, draw_data_callback.c_str());
148  }
149 
150  /*
151  virtual void AnimateStep(...){;}
152  virtual void AnimateStep(emp::vector<double>){;}
153  virtual void AnimateStep(int update, emp::vector<double>){;}
154  virtual void AnimateStep(int parent, int offspring){;}
155  */
156 };
157 
158 
159 class DotPlot : public D3Visualization {
160 private:
161  double margin = 10;
162  double axis_width = 40;
163  double value_growth_margin = 1.5;
164  double value_loss_margin = .8;
165 public:
171 
172  std::function<double(double, int, int)> scaled_d = [&](double d, int i, int k){
173  return y_scale->ApplyScale(d);
174  };
175 
176  std::function<double(double, int, int)> scaled_i = [&](double d, int i, int k){
177  return x_scale->ApplyScale(i);
178  };
179 
180  DotPlot(int w=500, int h=500) : D3Visualization(w, h){;}
181 
182  void Setup(){
183 
184  D3::Selection * svg = GetSVG();
185 
186  double lowest = 10;//*(std::min_element(values.begin(), values.end()));
187  double highest = 20;//*(std::max_element(values.begin(), values.end()));
188  double x_max = 100;
189 
190  //Set up scales
191  y_scale = new D3::LinearScale();
192  x_scale = new D3::LinearScale();
193  y_scale->SetDomain(emp::array<double, 2>{{highest*value_growth_margin, lowest*value_loss_margin}});
194  y_scale->SetRange(emp::array<double, 2>{{margin, GetHeight() - margin}});
195  x_scale->SetDomain(emp::array<double, 2>{{0, x_max}});
196  x_scale->SetRange(emp::array<double, 2>{{axis_width, GetHeight()-margin}});
197 
198  //Set up axis
199  ax = new D3::Axis<D3::LinearScale>("right");
200  ax->SetScale(*y_scale);
201  ax->Draw(*svg);
202 
203  //Make callback functions
204  JSWrap(scaled_d, GetID()+"scaled_d");
205  JSWrap(scaled_i, GetID()+"scaled_i");
206  this->pending_funcs.Run();
207  }
208 
209  virtual void AddDataPoint(int update, emp::vector<double> & values){
210  //Draw circles that represent values
211  circles = D3::Selection(GetSVG()->SelectAll("circle").Data(values));
212  circles.ExitRemove();
213  circles = circles.EnterAppend("circle").Merge(circles);
214  circles.SetAttr("r", 5);
215  circles.SetAttr("cx", GetID()+"scaled_i");
216  circles.SetAttr("cy", GetID()+"scaled_d");
217 
218  // circles->AddToolTip(tip);
219 
220  circles = D3::Selection(circles.Data(values));
221  circles.MakeTransition().SetAttr("cy", GetID()+"scaled_d");
222  }
223 
224 };
225 
226 class HeatMap : public D3Visualization {
227 public:
228 
229  int grid_width = 10;
230  int grid_height = 10;
231  int cell_size = 15;
233 
234  virtual void Setup() {
235  grid = D3::TileGrid<>(grid_width, grid_height, cell_size, *GetSVG());
236  }
237 };
238 
239 template <typename DATA_TYPE = int, typename X_SCALE_TYPE = D3::LinearScale, typename Y_SCALE_TYPE = D3::LinearScale>
241 protected:
242 
245 
247 
248  DATA_TYPE x_min = 100;
249  DATA_TYPE x_max = 0;
250  DATA_TYPE y_max = 10;
251 
252 
253 public:
254  HistogramChart(std::string x_var, int w=800, int h=400) :
255  D3Visualization(w, h),
256  x_ax("bottom", x_var),
257  y_ax("left", "Frequency"){;}
258 
259  virtual void Setup() {
260  x_ax.GetScale().SetRangeRound(axis_width, GetWidth()-x_margin);
261  x_ax.GetScale().SetDomain(x_min, x_max);
262  h.SetDomain(x_min, x_max);
263  y_ax.GetScale().SetRange(GetHeight() - axis_width, y_margin);
264  y_ax.GetScale().SetDomain(0, y_max);
265  D3::DrawAxes(x_ax, y_ax, *GetSVG());
266  }
267 
268 
270  X_SCALE_TYPE& x = x_ax.GetScale();
271  Y_SCALE_TYPE& y = y_ax.GetScale();
272  double new_x_min = *std::min_element(data.begin(), data.end());
273  double new_x_max = *std::max_element(data.begin(), data.end());
274  bool rescale = false;
275 
276  if (new_x_min < x_min || (new_x_min - x_min) > .5*(new_x_max - new_x_min)) {
277  x_min = new_x_min - (new_x_max-new_x_min)*.05;
278  rescale = true;
279  }
280  if (new_x_max > x_max || (x_max - new_x_max) > .5*(new_x_max - new_x_min)) {
281  x_max = new_x_max + (new_x_max-new_x_min)*.05;
282  rescale = true;
283  }
284 
286  t.SetDuration(500);
287  if (rescale) {
288  x.SetDomain(x_min, x_max);
289  h.Domain(x_min, x_max);
290  x_ax.Rescale(x_min, x_max, t);
291  }
292 
293  D3::Dataset bin_data = h.Call(data);
294 
295  double new_y_max = bin_data.Max([](D3::HistogramBin d){return d.length();});
296 
297  if (new_y_max > y_max) {
298  y_max = new_y_max * 1.2;
299  y_ax.Rescale(0, y_max, t);
300  }
301 
302  D3::Selection bins = GetSVG()->SelectAll(".bar").Data(bin_data);
303  D3::Selection enter = bins.Enter().Append("rect")
304  .SetAttr("class", "bar")
305  .SetAttr("x", (GetWidth() - axis_width)/2)
306  .SetAttr("y", GetHeight() - axis_width);
307  bins.ExitRemove();
308  bins.Merge(enter).MakeTransition(t).SetAttr("x", [this, &x](D3::HistogramBin d){
309  return x.ApplyScale(d.x0());
310  })
311  .SetAttr("y", [this, &y](D3::HistogramBin d){
312  return y.ApplyScale(d.length());
313  })
314  .SetAttr("width", [this, &x](D3::HistogramBin d){
315  return x.ApplyScale(d.x1()) - x.ApplyScale(d.x0()) - 1;
316  })
317  .SetAttr("height", [this, &y](D3::HistogramBin d){
318  return GetHeight() - y.ApplyScale(d.length()) - axis_width;
319  });
320 
321  }
322 
323  // void Clear() {
324  // GetSVG()->SelectAll(".bar").Remove();
325  // }
326 };
327 
328 template <typename DATA_TYPE = emp::array<double, 2>,
329  typename X_SCALE_TYPE = D3::LinearScale,
330  typename Y_SCALE_TYPE = D3::LinearScale >
331 class LineGraph : public D3Visualization {
332 protected:
333  // Formatting constants
334  double y_min = 1000;
335  double y_max = 0;
336  double x_min = 1000;
337  double x_max = 0;
338 
339  // Components of the graph
340  X_SCALE_TYPE * x_scale;
341  Y_SCALE_TYPE * y_scale;
346  // In case we need to store a dataset
348 
349  // Containers to keep track of data state
350  std::deque<DATA_TYPE> data;
351  DATA_TYPE prev_data = {{-1,-1}};
352 
353  // Callback functions for accessing and scaling data
354 
355  //Callback function for getting unscaled x value of data point (used as key function for data binding)
356  std::function<double(DATA_TYPE)> return_x = [](DATA_TYPE d){ return d[0]; };
357 
358  //Callback function for getting unscaled x value of data point (used as key function for data binding)
359  std::function<double(DATA_TYPE)> return_y = [](DATA_TYPE d){ return d[1]; };
360 
361  //Callback function for taking a datapoint and getting appropriately scaled y val
362  std::function<double(DATA_TYPE)> y = [this](DATA_TYPE d){
363  return y_scale->ApplyScale(this->return_y(d));
364  };
365 
366  //Callback function for taking a datapoint and getting appropriately scaled x val
367  std::function<double(DATA_TYPE)> x = [this](DATA_TYPE d){
368  return x_scale->ApplyScale(this->return_x(d));
369  };
370 
371 public:
372 
373  LineGraph(std::string x_var="", std::string y_var="", int w=800, int h=400) : D3Visualization(w, h){
374  this->variables.push_back(x_var);
375  this->variables.push_back(y_var);
376  }
377 
379  delete x_scale;
380  delete y_scale;
381  delete x_axis;
382  delete y_axis;
383  delete line_gen;
384  delete tip;
385  delete dataset;
386  }
387 
390  virtual void Setup(){
391  D3::Selection * svg = GetSVG();
392 
393  //Wrap ncessary callback functions
394  JSWrap([this](){exit.Remove(); this->DrawData(true);}, GetID()+"draw_data");
395 
396  //Create tool tip
397  tip = new D3::ToolTip([this](DATA_TYPE d) {return D3::FormatFunction(".2f")(return_y(d));});
398  GetSVG()->SetupToolTip(*tip);
399 
400  //Set up scales
401  y_scale = new Y_SCALE_TYPE();
402  x_scale = new X_SCALE_TYPE();
403  y_scale->SetDomain(emp::array<double, 2>{{y_max, y_min}});
404  y_scale->SetRange(emp::array<double, 2>{{y_margin, (double)GetHeight() - axis_width}});
405  x_scale->SetDomain(emp::array<double, 2>{{x_min,x_max}});
406  x_scale->SetRange(emp::array<double, 2>{{axis_width, GetWidth()-x_margin}});
407 
408  //Set up axes
409  x_axis = new D3::Axis<X_SCALE_TYPE>("bottom", variables[0]);
410  x_axis->SetScale(*x_scale);
411  y_axis = new D3::Axis<Y_SCALE_TYPE>("left", variables[1]);
412  y_axis->SetScale(*y_scale);
413  D3::DrawAxes(*x_axis, *y_axis, *svg);
414 
415  line_gen = new D3::LineGenerator();
416 
417  // Set up accessors (for retriving coords from data points)
418  SetXAccessor(return_x);
419  SetYAccessor(return_y);
420 
421  dataset = new D3::CSVDataset();
422 
423  // In case functions were called before initilization
424  init = true;
425  this->pending_funcs.Run();
426  }
427 
429  X_SCALE_TYPE * GetXScale() {return x_scale;}
430  Y_SCALE_TYPE * GetYScale() {return y_scale;}
431  D3::Axis<X_SCALE_TYPE> * GetXAxis() {return x_axis;}
432  D3::Axis<Y_SCALE_TYPE> * GetYAxis() {return y_axis;}
433  D3::LineGenerator * GetLineGenerator() {return line_gen;}
434  D3::CSVDataset * GetDataset() {return dataset;}
435  D3::ToolTip * GetToolTip() {return tip;}
436  std::function<double(DATA_TYPE)> GetXAccessor() {return return_x;}
437  std::function<double(DATA_TYPE)> GetYAccessor() {return return_y;}
438  std::function<double(DATA_TYPE)> GetScaledX() {return x;}
439  std::function<double(DATA_TYPE)> GetScaledY() {return y;}
440 
441 
442  void SetXScale(X_SCALE_TYPE * scale) {x_scale = scale;}
443  void SetYScale(Y_SCALE_TYPE * scale) {y_scale = scale;}
444  void SetXAxis(D3::Axis<X_SCALE_TYPE> * ax) {x_axis = ax;}
445  void SetYAxis(D3::Axis<Y_SCALE_TYPE> * ax) {y_axis = ax;}
446  void SetLineGenerator(D3::LineGenerator * line) {line_gen = line;}
447  void SetDataset(D3::CSVDataset * d) {dataset = d;}
448 
449  void SetTooltipFunction(std::string func) {
450  tip->SetHtml(func);
451  }
452 
454  template <typename T>
456  SetTooltipFunction(T func) {
457  tip->SetHtml(func);
458  }
460 
461 
463  template <typename T>
465  SetXAccessor(T func) {
466  return_x = func;
467  JSWrap(return_x, GetID()+"return_x");
468  JSWrap(x, GetID()+"x");
469  line_gen->SetX(GetID()+"x");
470  }
472 
479 
480  void SetXAccessor(std::string func) {
481  return_x = [func](DATA_TYPE d){
482  emp::StoreReturn(d);
483  return EM_ASM_DOUBLE({
484  var func_string = Pointer_stringify($0);
485  if (typeof window[func_string] === function) {
486  func_string = window[func_string];
487  } else if (typeof window["emp"][func_string] === function) {
488  func_string = window["emp"][func_string];
489  } else if (typeof window["d3"][func_string] === function) {
490  func_string = window["d3"][func_string];
491  }
492  return func_string(emp_i.cb_return);
493  }, func.c_str());
494  };
495 
496  JSWrap(return_x, GetID()+"return_x");
497  JSWrap(x, GetID()+"x");
498  line_gen->SetX(GetID()+"x");
499  }
500 
502  template <typename T>
504  SetYAccessor(T func) {
505  return_y = func;
506  JSWrap(return_y, GetID()+"return_y");
507  JSWrap(y, GetID()+"y");
508  line_gen->SetY(GetID()+"y");
509  }
511 
518  void SetYAccessor(std::string func) {
519  return_y = [func](DATA_TYPE d){
520  emp::StoreReturn(d);
521  return EM_ASM_DOUBLE({
522  var func_string = Pointer_stringify($0);
523  if (typeof window[func_string] === function) {
524  func_string = window[func_string];
525  } else if (typeof window["emp"][func_string] === function) {
526  func_string = window["emp"][func_string];
527  } else if (typeof window["d3"][func_string] === function) {
528  func_string = window["d3"][func_string];
529  }
530 
531  return func_string(emp_i.cb_return);
532  }, func.c_str());
533  };
534  JSWrap(return_y, GetID()+"return_y");
535  JSWrap(y, GetID()+"y");
536  line_gen->SetY(GetID()+"y");
537  }
538 
540  // Needs to be a std::function object or else JSWrap complains
542 
543  // Adjust axes
544  x_min = std::min(EM_ASM_DOUBLE({
545  return d3.min(js.objects[$0], window["emp"][Pointer_stringify($1)+"return_x"]);
546  }, dataset->GetID(), this->GetID().c_str()), x_min);
547 
548  x_max = std::max(EM_ASM_DOUBLE({
549  return d3.max(js.objects[$0], window["emp"][Pointer_stringify($1)+"return_x"]);
550  }, dataset->GetID(), this->GetID().c_str()), x_max);
551 
552  y_min = std::min(EM_ASM_DOUBLE({
553  return d3.min(js.objects[$0], window["emp"][Pointer_stringify($1)+"return_y"]);
554  }, dataset->GetID(), this->GetID().c_str()), y_min);
555 
556  y_max = std::max(EM_ASM_DOUBLE({
557  return d3.max(js.objects[$0], window["emp"][Pointer_stringify($1)+"return_y"]);
558  }, dataset->GetID(), this->GetID().c_str()), y_max);
559 
560  y_scale->SetDomain(y_max, y_min);
561  x_scale->SetDomain(x_min, x_max);
562 
563  y_axis->Rescale(y_max, y_min, *GetSVG());
564  x_axis->Rescale(x_min, x_max, *GetSVG());
565 
566  // Bind data and update graphics
567  D3::Selection update = GetSVG()->SelectAll(".data-point")
568  .Data(*dataset, GetID()+"return_x");
569  update = update.EnterAppend("circle").Merge(update);
570  update.SetAttr("cy", GetID()+"y")
571  .SetAttr("cx", GetID()+"x")
572  .SetAttr("r", 2)
573  .SetAttr("class", "data-point")
574  .BindToolTipMouseover(*tip);
575 
576  D3::Selection line = line_gen->DrawShape(*dataset, *GetSVG());
577  line.SetAttr("fill", "none")
578  .SetAttr("stroke-width", 1)
579  .SetAttr("stroke", "black")
580  .SetAttr("class", "line-seg");
581 
582  // Set prev_data appropriately
583  dataset->GetLastRow(prev_data);
585  }
586 
588  void LoadDataFromFile(std::string filename) {
589  emp::JSWrap([this](){DrawPointsFromDataset();}, "draw");
590 
591  if (this->init) {
592  dataset->LoadDataFromFile(filename, "draw", false);
593 
594  } else {
595  this->pending_funcs.Add([this, filename](){
596  dataset->LoadDataFromFile(filename, "draw", false);
597  });
598  }
599  }
600 
602  void AddDataPoint(DATA_TYPE data_point) {
603  data.push_back(data_point);
604 
605  if (data_point[1] > y_max || data_point[1] < y_min
606  || data_point[0] > x_max || data_point[0] < x_min) {
607  y_max = std::max(data_point[1]*1.2, y_max);
608  y_min = std::min(data_point[1]*.8, y_min);
609  x_max = std::max(data_point[0]*1.2, x_max);
610  x_min = std::min(data_point[0]*.8, x_min);
611 
612  if (y_min == y_max) {
613  y_min -= .2;
614  y_max += .2;
615  }
616 
617  if (x_min == x_max) {
618  x_min -= .2;
619  x_max += .2;
620  }
621 
623  EM_ASM_ARGS({js.objects[$0].ease(d3.easeLinear).delay(10).duration(300);}, t.GetID());
624  y_axis->Rescale(y_max, y_min, t);
625  x_axis->Rescale(x_min, x_max, t);
626  t.On("end", GetID()+"draw_data");
627  Redraw(t);
628 
629  } else {
630  DrawData(false);
631  }
632  }
633 
636  // template <typename T>
637  // void Redraw(D3::SelectionOrTransition<T> & s) {
638  // s.SelectAll(".data-point").Log();
639  // s.SelectAll(".data-point").SetAttr("cy", GetID()+"y");
640  // s.SelectAll(".data-point").SetAttr("cx", GetID()+"x");
641  //
642  // D3::Dataset circle_data = GetSVG()->SelectAll(".data-point").Data();
643  // circle_data.Log();
644  // D3::Selection new_segs = GetSVG()->SelectAll(".line-seg").Data(circle_data);
645  // new_segs.ExitRemove();
646  // new_segs.EnterAppend("path").SetAttr("class", "line-seg");
647  // new_segs.SetAttr("d", GetID()+"genpath");
648  //
649  // // EM_ASM_ARGS({
650  // //
651  // // js.objects[$0].selectAll(".line-seg").attr("d", function(d){console.log("in d", d, $1, js.objects[$1]); return js.objects[$1](d);});
652  // // }, GetSVG()->GetID(), line_gen->GetID(), s.GetID());
653  // std::cout << "Done redrawing" << std::endl;
654  // }
655  template <typename T>
657  // s.SelectAll(".data-point").SetAttr("cy", GetID()+"y");
658  // s.SelectAll(".data-point").SetAttr("cx", GetID()+"x");
659 
660  EM_ASM_ARGS({
661  function pathTween(d1, precision) {
662  return function() {
663  var path0 = this;
664  path1 = path0.cloneNode();
665  n0 = path0.getTotalLength();
666  n1 = (path1.setAttribute("d", d1), path1).getTotalLength();
667 
668  // Uniform sampling of distance based on specified precision.
669  var distances = [0];
670  i = 0;
671  dt = precision / Math.max(n0, n1);
672  while ((i += dt) < 1) distances.push(i);
673  distances.push(1);
674 
675  // Compute point-interpolators at each distance.
676  var points = distances.map(function(t) {
677  var p0 = path0.getPointAtLength(t * n0);
678  p1 = path1.getPointAtLength(t * n1);
679  return d3.interpolate([p0.x, p0.y], [p1.x, p1.y]);
680  });
681 
682  return function(t) {
683  return t < 1 ? "M" + points.map(function(p) { return p(t); }).join("L") : d1;
684  };
685  };
686  };
687 
688  circle_data = js.objects[$0].selectAll(".data-point").data();
689  ls = js.objects[$2].selectAll(".line-seg");
690  var s = js.objects[$0].selectAll(".line-seg").data([circle_data]);
691  js.objects[$3] = s.exit();
692  js.objects[$2].ease(d3.easeLinear).duration(300).selectAll(".data-point")
693  .attr("cy", emp[Pointer_stringify($4)+"y"])
694  .attr("cx", emp[Pointer_stringify($4)+"x"]);
695  t = s.transition(js.objects[$2]).duration(300).attrTween("d", pathTween).ease(d3.easeLinear);
696  t.attr("d", js.objects[$1]);
697  js.objects[$3]
698  .transition(js.objects[$2])
699  .duration(300)
700  .attrTween("d", pathTween)
701  .ease(d3.easeLinear)
702  .attr("d",js.objects[$1](circle_data.slice(circle_data.length-2, circle_data.length-1)));
703  }, GetSVG()->GetID(), line_gen->GetID(), s.GetID(), exit.GetID(), GetID().c_str());
704  }
705 
706  void DrawData(bool backlog = false) {
707 
708  //If there's a backlog, then we're only allowed to clear it if this
709  //was called recursively or from javascript (since javascript handles)
710  //using this as a callback to asynchronous stuff)
711  if ((!backlog && data.size() > 1) || data.size() == 0){
712  return;
713  }
714 
715  // //We can't draw a line on the first update
716  if (prev_data[0] >= 0 ){
717  emp::array<DATA_TYPE, 2> line_data;
718  line_data[0] = prev_data;
719  line_data[1] = data[0];
720 
721  line_gen->DrawShape(line_data, *GetSVG())
722  .SetAttr("fill", "none")
723  .SetAttr("stroke-width", 1)
724  .SetAttr("stroke", "black")
725  .SetAttr("class", "line-seg");
726  }
727 
728  // If it isn't nested, D3 will think it's 2 separate points
729  emp::array<DATA_TYPE, 1> new_point = {{data[0]}};
730  // GetSVG()->SelectAll(".data-point").Log();
731  GetSVG()->SelectAll(".data-point")
732  .Data(new_point, GetID()+"return_x")
733  .EnterAppend("circle")
734  .SetAttr("cy", GetID()+"y")
735  .SetAttr("cx", GetID()+"x")
736  .SetAttr("r", 2)
737  .SetAttr("class", "data-point")
738  .BindToolTipMouseover(*tip);
739  prev_data = data[0];
740  data.pop_front();
741  // GetSVG()->SelectAll("circle").Log();
742  if (data.size() > 0) {
743  DrawData(true);
744  } else if (data.size() == 0) {
745  // std::cout << "About to draw callback" << std::endl;
747  }
748  }
749 
750  void Clear() {
751  data.clear();
752  GetSVG()->SelectAll(".data-point").Remove();
753  GetSVG()->SelectAll(".line-seg").Remove();
754  y_axis->Rescale(0, 1000, *(GetSVG()));
755  x_axis->Rescale(0, 0, *(GetSVG()));
756  y_min = 1000;
757  y_max = 0;
758  x_min = 0;
759  x_max = 0;
760  prev_data = {{-1,-1}};
761  }
762 };
763 
764 struct TreeDataNode {
765  EMP_BUILD_INTROSPECTIVE_TUPLE( int, name)
766 };
767 
768 struct TreeNode {
769  EMP_BUILD_INTROSPECTIVE_TUPLE( double, x,
770  double, y,
772  int, parent,
773  int, depth
774  )
775 };
776 
777 template <typename NODE = TreeNode>
779 protected:
780  double y_margin = 10;
781  double x_margin = 30;
782 
783  // struct TreeEdge {
784  // EMP_BUILD_INTROSPECTIVE_TUPLE( NODE, source,
785  // NODE, target)
786  // };
787 
789 
791  JSWrap(color_fun_node, GetID()+"color_fun_node");
792  JSWrap(color_fun_link, GetID()+"color_fun_link");
793  data = new D3::JSONDataset();
794  tip = new D3::ToolTip([](NODE d, int i){return "Name: " + to_string(d.data().name());});
795  GetSVG()->Move(0,0);
796  data->Append(std::string("{\"name\": 0, \"parent\": \"null\", \"children\" : []}"));
797  tree.SetDataset(data);
798  tree.SetSize(GetHeight(), GetWidth());
799  }
800 
801  std::function<std::string(NODE, int)> color_fun_node = [](NODE d, int i){
802  return "black";
803  };
804 
805  std::function<std::string(NODE, int)> color_fun_link = [this](NODE d, int i){
806  return "black";
807  };
808 
809 public:
812 
814 
815  virtual void Setup() {
816  InitializeVariables();
817  this->init = true;
818  this->pending_funcs.Run();
819  }
820 
821  void SetTooltipFunction(std::string func) {
822  tip->SetHtml(func);
823  }
824 
826  template <typename T>
828  SetTooltipFunction(T func) {
829  tip->SetHtml(func);
830  }
832 
835  D3::ToolTip * GetToolTip() {return tip;}
836 
837  void SetDataset(D3::JSONDataset * d) {data = d;}
838 
839  void LoadDataFromFile(std::string filename) {
840  if (this->init) {
841  data->LoadDataFromFile(filename, [this](){DrawTree();});
842  } else {
843  this->pending_funcs.Add([this, filename](){
844  data->LoadDataFromFile(filename, [this](){
845  DrawTree();
846  });
847  });
848  }
849  }
850 
851  void AddDataPoint(int parent, int child){
852  std::string child_json = std::string("{\"name\":" + to_string(child) + ", \"parent\":" + to_string(parent) + ", \"children\":[]}");
853  data->AppendNested(child_json);
854  DrawTree();
855  }
856 
857  void DrawTree() {
858  // std::cout << "Vis data id: " << data->GetID() << std::endl;
860  // std::cout << "Links generated" << std::endl;
861  nodes_links[0].Append("circle").SetAttr("r", 2).AddToolTip(*tip);
862  nodes_links[1].Remove();
863  nodes_links[3].Remove();
864  // std::cout << "Circles appended" << std::endl;
865  GetSVG()->SelectAll("g.node").SelectAll("circle").SetStyle("fill", GetID()+"color_fun_node");
866  // std::cout << "Circles sstyled" << std::endl;
867  GetSVG()->SelectAll(".link").SetStyle("stroke", GetID()+"color_fun_link");
868  // std::cout << "links styled" << std::endl;
870  }
871 
872  void Clear() {
873  GetSVG()->SelectAll(".node").Remove();
874  GetSVG()->SelectAll(".link").Remove();
875  }
876 
877 };
878 
879 template <typename NODE = TreeNode>
881 protected:
889 
890 public:
891 
892  int next_pos;
893  int next_parent = 0;
896 
897  TreeVisualizationReplacement(int width, int height) : TreeVisualization<NODE>(width, height){variables.push_back("Persist");}
898 
899  virtual void Setup() {
900  InitializeVariables();
901 
902  EM_ASM_ARGS({
903  js.objects[$0] = [js.objects[$1][0]];
904  }, possible_parents.GetID(), data->GetID());
905 
906  this->init = true;
907  this->pending_funcs.Run();
908  }
909 
910  void AddDataPoint(int parent, int child){
911  std::string child_json = std::string("{\"name\":" + to_string(child) + ", \"parent\":" + to_string(parent) + ", \"children\":[]}");
912  int pos = data->AppendNestedFromList(child_json, possible_parents);
913  (void) pos;
914 
915  EM_ASM_ARGS({
916  while (js.objects[$0].length < $1 + 1) {
917  js.objects[$0].push(-1);
918  }
919  js.objects[$0][$1] = js.objects[$0][$2].children[js.objects[$0][$2].children.length-1];
920  }, possible_parents.GetID(), next_pos, pos);
921  DrawTree();
922  }
923 
924  void RecordPlacement(int pos) {
925  next_pos = pos + 1;
926  AddDataPoint(next_parent, next_child);
927  }
928 
929  void RecordParent(int parent, int child) {
930  next_parent = parent;
931  next_child = child;
932  }
933 };
934 
936  EMP_BUILD_INTROSPECTIVE_TUPLE( double, x,
937  double, y,
938  int, name,
939  int, parent,
940  int, depth,
941  int, loc
942  )
943 };
944 
945 template <typename NODE = SpatialGridTreeNode, template <typename> class TREE_TYPE = TreeVisualization>
946 class SpatialGridTreeVisualization : public TREE_TYPE<NODE> {
947 protected:
948  using TREE_TYPE<NODE>::GetID;
949  using TREE_TYPE<NODE>::GetSVG;
950  using TREE_TYPE<NODE>::InitializeVariables;
951  using TREE_TYPE<NODE>::DrawTree;
952  using TREE_TYPE<NODE>::tip;
953  using TREE_TYPE<NODE>::data;
954 
955 public:
956 
957  int grid_width = 10;
958  int grid_height = 10;
959  int legend_cell_size = 15;
960 
962 
963  struct TreeEdge {
964  EMP_BUILD_INTROSPECTIVE_TUPLE( NODE, source,
965  NODE, target)
966  };
967 
968  struct LegendNode {
969  EMP_BUILD_INTROSPECTIVE_TUPLE( int, loc)
970  };
971 
972  std::function<void(NODE, int)> node_mouseover = [this](NODE d, int i){
973  EM_ASM_ARGS({
974 
975  var trace_lineage = function(root, id) {
976  if (root.name == id){
977  return [root.loc];
978  }
979  if (root.children) {
980  for (var k in root.children) {
981  if (root.children[k].name == id) {
982  return [root.children[k].loc];
983  }
984  else if (root.children[k].children) {
985  result = trace_lineage(root.children[k], id);
986  if (result) {
987  result.push(root.children[k].loc);
988  return result;
989  }
990  }
991  }
992  }
993  };
994  // console.log("about to trace");
995  var result = trace_lineage(js.objects[$0][0], $1);
996  var paths = ([[result[0]%$2, Math.floor(result[0]/$2)]]);
997  for (i=1; i <result.length; i++) {
998  var old_point = paths[paths.length-1];
999  var new_point = ([result[i]%$2, Math.floor(result[i]/$2)]);
1000  paths.push(new_point);
1001  }
1002  var scale = d3.scale.linear().domain([0,$2]).range([0,500]);
1003  var l = d3.svg.line().x(function(d){return scale(d[0]);}).y(function(d){return scale(d[1]);});
1004  var svg = d3.select("body").append("svg");
1005  svg.attr("width", 500).attr("height",500);
1006  // console.log(paths);
1007  svg.selectAll("path").data([paths]).enter().append("path").attr("d", function(d){console.log(d, l(d)); return l(d);}).attr("stroke", "white").attr("stroke-width", 1).attr("fill","none");
1008  // console.log(path.length);
1009  // console.log(l(path));
1010 
1011 
1012 }, data->GetID(), d.name(), grid_width);
1013  };
1014 
1015  std::function<std::string(NODE, int)> color_fun_node = [this](NODE d, int i){
1016  if (d.loc() < 0) {
1017  return std::string("black");
1018  }
1019 
1020  double x = (d.loc() % grid_width) - grid_width/2;
1021  double y = (d.loc() / grid_width) - grid_height/2;
1022 
1023  double r = sqrt(emp::Pow((int)x,2)+emp::Pow((int)y,2)) / sqrt(emp::Pow(grid_width,2)+emp::Pow(grid_height,2));
1024  (void) r;
1025 
1026  //atan2 takes sign into account
1027  double theta = atan2(y, x)*(180/emp::PI);
1028  (void) theta;
1029 
1030  char * color = (char *) EM_ASM_INT({
1031  var text = d3.hcl($1, 150, $0*175).toString();
1032  var buffer = Module._malloc(text.length+1);
1033  Module.writeStringToMemory(text, buffer);
1034  return buffer;
1035  }, r, theta);
1036 
1037  std::string result = std::string(color);
1038  free(color);
1039  return result;
1040  };
1041 
1042  std::function<std::string(NODE, int)> dark_color_fun = [this](NODE d, int i){
1043  if (d.loc() < 0) {
1044  return std::string("black");
1045  }
1046 
1047  double x = (d.loc() % grid_width) - grid_width/2;
1048  double y = (d.loc() / grid_width) - grid_height/2;
1049 
1050  double r = sqrt(emp::Pow((int)x,2)+emp::Pow((int)y,2)) / sqrt(emp::Pow(grid_width,2)+emp::Pow(grid_height,2));
1051  (void) r;
1052 
1053  //atan2 takes sign into account
1054  double theta = atan2(y, x)*(180/emp::PI);
1055  (void) theta;
1056 
1057  char * color = (char *) EM_ASM_INT({
1058  var text = d3.hcl($1, 150, $0*175).darker().toString();
1059  var buffer = Module._malloc(text.length+1);
1060  Module.writeStringToMemory(text, buffer);
1061  return buffer;
1062  }, r, theta);
1063 
1064  std::string result = std::string(color);
1065  free(color);
1066  return result;
1067  };
1068 
1069  std::function<std::string(TreeEdge, int)> color_fun_link = [this](TreeEdge d, int i){
1070  return this->color_fun_node(d.source(), i);
1071  };
1072 
1073 
1074  std::function<void(LegendNode, int)> legend_mouseover = [this](LegendNode d, int il) {
1075  legend.SelectAll("rect").Filter([d](LegendNode in_data){return d.loc() != in_data.loc();}).SetClassed("faded", true);
1076  GetSVG()->SelectAll(".node").Filter([d](LegendNode in_data){return d.loc() != in_data.loc();}).SetClassed("faded", true);
1077  EM_ASM_ARGS({emp.filter_fun = function(d){return d.source.loc != $0;}}, d.loc());
1078  GetSVG()->SelectAll(".link").Filter("filter_fun").SetClassed("faded", true);
1079  };
1080 
1081  std::function<void(LegendNode, int)> legend_mouseout = [this](LegendNode d, int i) {
1082  legend.SelectAll("rect")
1083  .Filter([d](LegendNode in_data){return d.loc() != in_data.loc();})
1084  .SetClassed("faded", false);
1085  GetSVG()->SelectAll(".node")
1086  .Filter([d](LegendNode in_data){return d.loc() != in_data.loc();})
1087  .SetClassed("faded", false);
1088 
1089  EM_ASM_ARGS({emp.filter_fun = function(d){return d.source.loc != $0;}}, d.loc());
1090  GetSVG()->SelectAll(".link").Filter("filter_fun").SetClassed("faded", false);
1091  };
1092 
1094  EM_ASM_ARGS({
1095  var org = js.objects[$1](js.objects[$0][0], $2);
1096  var loc_history = [];
1097  loc_history.push(org.loc);
1098  console.log(org);
1099  while (+org.name > 0) {
1100  org = js.objects[$1](js.objects[$0][0], org.parent);
1101  loc_history.push(org.loc);
1102  }
1103  emp_i.__outgoing_array = loc_history;
1104 
1105  }, data->GetID(), data->FindInHierarchy.GetID(), id);
1106 
1107  emp::vector<int> loc_history;
1108  emp::pass_vector_to_cpp(loc_history);
1109  return loc_history;
1110  }
1111 
1112  SpatialGridTreeVisualization(int width, int height) : TreeVisualization<NODE>(width, height){;}
1113 
1114  virtual void Setup() {
1115  TREE_TYPE<NODE>::Setup();
1116  JSWrap(color_fun_node, GetID()+"color_fun_node");
1117  JSWrap(dark_color_fun, GetID()+"dark_color_fun");
1118  JSWrap(color_fun_link, GetID()+"color_fun_link");
1119  JSWrap(legend_mouseover, GetID()+"legend_mouseover");
1120  JSWrap(legend_mouseout, GetID()+"legend_mouseout");
1121  JSWrap(node_mouseover, GetID()+"node_mouseover");
1122 
1123  tip->SetHtml([this](NODE d){
1124  return "ID: " + to_string(d.name()) + ", Pos: ("
1125  + to_string(d.loc()% grid_width) + ", "
1126  + to_string(d.loc()/grid_width) + ")";
1127  });
1128 
1129  legend = D3::Select("body").Append("svg");
1130 
1131  legend.SetAttr("x", 1000).SetAttr("y", 0);//.SetAttr("width", legend_cell_size*grid_width).SetAttr("height", legend_cell_size*grid_height);
1132  legend.SetStyle("position", "fixed").SetStyle("right", "10px").SetStyle("top", "10px");//.SetStyle("width", "10%");//.SetStyle("height", "10%");
1133 
1134  D3::TileGrid<LegendNode> legend_grid(grid_width, grid_height, legend_cell_size, legend);
1135 
1136  legend.SelectAll("rect").SetStyle("fill", GetID()+"color_fun_node")
1137  .SetStyle("stroke", GetID()+"color_fun_node")
1138  .On("mouseover", GetID()+"legend_mouseover")
1139  .On("mouseout", GetID()+"legend_mouseout");
1140 
1141  GetSVG()->SelectAll(".node").On("click", [this](NODE d){std::cout << emp::to_string(GetLocHistory(d.name())) << std::endl;});
1142 
1143  }
1144 
1145 
1146 
1147 };
1148 
1149 }
1150 }
1151 #endif
DERIVED Merge(DERIVED &other)
Definition: selection.h:171
void Setup()
Definition: visualizations.h:182
FunctionSet< void()> pending_funcs
Definition: visualizations.h:122
double x_margin
Definition: visualizations.h:93
virtual void Setup()
Definition: visualizations.h:815
Definition: Widget.h:206
Definition: array.h:42
DERIVED SelectAll(std::string selector) const
Definition: selection.h:60
emp::array< Selection, 4 > GenerateNodesAndLinks(Selection svg)
Definition: layout.h:135
D3::Axis< Y_SCALE_TYPE > * GetYAxis()
Definition: visualizations.h:432
Selection Enter()
Definition: selection.h:1188
D3Visualization(const Widget &in)
Definition: visualizations.h:111
Definition: visualizations.h:159
Definition: visualizations.h:768
D3::TileGrid grid
Definition: visualizations.h:232
Y_SCALE_TYPE * y_scale
Definition: visualizations.h:341
std::string id
ID used for associated DOM element.
Definition: Widget.h:212
D3::ToolTip * GetToolTip()
Definition: visualizations.h:435
void DrawPointsFromDataset()
Draw points and lines for data in this object&#39;s dataset object.
Definition: visualizations.h:541
std::deque< DATA_TYPE > data
Definition: visualizations.h:350
D3::LinearScale * x_scale
Definition: visualizations.h:166
std::string to_string(ALL_TYPES &&...all_values)
Definition: string_utils.h:511
REAL_TYPE sfinae_decoy
Definition: meta.h:93
Definition: dataset.h:23
iterator end() noexcept
Definition: vector.h:155
void AddDataPoint(int parent, int child)
Definition: visualizations.h:910
std::function< double(DATA_TYPE)> GetXAccessor()
Definition: visualizations.h:436
std::function< double(DATA_TYPE)> GetScaledX()
Definition: visualizations.h:438
A callable string d3.format() string formatting function.
Definition: d3_init.h:191
Definition: visualizations.h:41
void SetX(std::string x)
Definition: svg_shapes.h:254
D3::JSONDataset * GetDataset()
Definition: visualizations.h:834
WidgetInfo * info
Information associated with this widget.
Definition: Widget.h:82
D3::Axis< Y_SCALE_TYPE > y_ax
Definition: visualizations.h:244
WidgetFacet is a template that provides accessors into Widget with a derived return type...
Definition: Widget.h:543
int GetHeight() const
Definition: visualizations.h:117
virtual bool IsD3VisualiationInfo() const
Definition: Widget.h:248
D3::LineGenerator * line_gen
Definition: visualizations.h:344
void SetXAccessor(std::string func)
Definition: visualizations.h:480
D3::LinearScale * y_scale
Definition: visualizations.h:167
virtual void Setup()
Definition: visualizations.h:128
Definition: visualizations.h:764
virtual std::string GetType() override
Definition: visualizations.h:81
D3::CSVDataset * GetDataset()
Definition: visualizations.h:434
void SetDataset(D3::JSONDataset *d)
Definition: visualizations.h:837
void AddDataPoint(int parent, int child)
Definition: visualizations.h:851
DERIVED & SetStyle(std::string name, std::string value, bool priority=false)
Definition: selection.h:284
void Redraw()
Clear and redraw the current widget on the screen.
Definition: Widget.h:517
double ApplyScale(double input)
Calculate the ouput for [input], based on the scale&#39;s scaling function.
Definition: scales.h:73
void Redraw(D3::SelectionOrTransition< T > &s)
Definition: visualizations.h:656
D3::Selection exit
Definition: visualizations.h:428
void InitializeVariables()
Definition: visualizations.h:790
virtual ~D3Visualization()
Definition: visualizations.h:112
virtual void Setup()
Definition: visualizations.h:1114
D3::Histogram h
Definition: visualizations.h:246
void LoadDataFromFile(std::string location, std::string callback, bool header=true)
Definition: dataset.h:195
DotPlot(int w=500, int h=500)
Definition: visualizations.h:180
int height
Definition: visualizations.h:49
void Remove()
Definition: selection.h:166
virtual void AddDataPoint(int update, emp::vector< double > &values)
Definition: visualizations.h:209
D3::Axis< X_SCALE_TYPE > x_ax
Definition: visualizations.h:243
Scale & SetRange(emp::array< T, SIZE > values)
Definition: scales.h:38
D3::Selection * GetSVG()
Definition: visualizations.h:118
void SetYAccessor(std::string func)
Definition: visualizations.h:518
void Clear()
Definition: visualizations.h:872
Definition: visualizations.h:240
DERIVED & SetAttr(std::string name, std::string value)
Definition: selection.h:208
void push_back(PB_Ts &&...args)
Definition: vector.h:189
void LoadDataFromFile(std::string filename)
Definition: dataset.h:99
void DrawData(emp::vector< DATA_TYPE > &data)
Definition: visualizations.h:269
D3::Axis< Y_SCALE_TYPE > * y_axis
Definition: visualizations.h:343
Create a tooltup using the d3.tip Javascript library.
Definition: d3_init.h:106
constexpr const double PI
pi
Definition: const.h:20
virtual bool IsD3VisualiationInfo() const override
Definition: visualizations.h:61
void SetXScale(X_SCALE_TYPE *scale)
Definition: visualizations.h:442
D3VisualizationInfo & operator=(const D3VisualizationInfo &)=delete
Definition: Widget.h:102
D3::TreeLayout< NODE > tree
Definition: visualizations.h:810
bool init
Definition: visualizations.h:123
void SetDrawCallback(std::string func)
Definition: visualizations.h:142
Catch-all object for storing references to things created in JS.
Definition: d3_init.h:213
virtual void Setup()
Definition: visualizations.h:899
D3VisualizationInfo(D3Visualization *parent, const std::string &in_id="")
Definition: visualizations.h:53
HistogramChart(std::string x_var, int w=800, int h=400)
Definition: visualizations.h:254
void SetTooltipFunction(std::string func)
Definition: visualizations.h:449
data
A set of modifiers are available do describe DataNode.
Definition: DataNode.h:38
Definition: visualizations.h:226
void SetHtml(std::string func)
Definition: d3_init.h:164
Definition: selection.h:547
D3::JSObject possible_parents
Definition: visualizations.h:895
Definition: dataset.h:189
Selection Select(std::string selector)
Definition: selection.h:1670
Widget::ActivityState state
Is this element active in DOM?
Definition: Widget.h:218
void SetXAxis(D3::Axis< X_SCALE_TYPE > *ax)
Definition: visualizations.h:444
Selection & On(std::string type, std::string listener="null", bool capture=false)
Definition: selection.h:1533
void CallDrawCallback()
Definition: visualizations.h:146
Axis & SetScale(SCALE_TYPE &scale)
Definition: axis.h:150
emp::sfinae_decoy< double, decltype(&T::operator())> Max(T comp)
Definition: dataset.h:48
std::function< double(DATA_TYPE)> GetScaledY()
Definition: visualizations.h:439
Definition: visualizations.h:880
~LineGraph()
Definition: visualizations.h:378
Definition: visualizations.h:963
Definition: visualizations.h:946
Definition: histogram.h:17
Y_SCALE_TYPE * GetYScale()
Definition: visualizations.h:430
static const PrintStr endl("<br>")
Pre-define emp::endl to insert a "<br>" and thus acting like a newline.
void pass_vector_to_cpp(emp::vector< T > &arr, bool recurse=false)
Same as pass_array_to_cpp, but lets you store values in a vector instead.
Definition: js_utils.h:334
Tools for scaling graph axes in D3.
int next_child
Definition: visualizations.h:894
void TriggerJS() override
Definition: visualizations.h:73
Selection EnterAppend(std::string type)
Definition: selection.h:1147
D3::JSONDataset * data
Definition: visualizations.h:811
DERIVED Filter(std::string selector) const
Definition: selection.h:122
X_SCALE_TYPE * GetXScale()
Definition: visualizations.h:429
D3::TreeLayout< NODE > * GetTreeLayout()
Definition: visualizations.h:833
D3::ToolTip * tip
Definition: visualizations.h:345
D3::CSVDataset * dataset
Definition: visualizations.h:347
void SetY(std::string y)
Definition: svg_shapes.h:301
D3::ToolTip * GetToolTip()
Definition: visualizations.h:835
Definition: selection.h:39
const D3VisualizationInfo * Info() const
Definition: visualizations.h:87
Generator for regular old (cartesian) lines.
Definition: svg_shapes.h:187
Transition MakeTransition(std::string name="")
Definition: selection.h:1452
D3::ToolTip * tip
Definition: visualizations.h:170
D3Visualization(int w, int h, const std::string &in_id="")
Definition: visualizations.h:97
Definition: visualizations.h:44
static constexpr type_if< T, std::is_integral > Pow(T base, T p)
A fast (O(log p)) integral-power command.
Definition: math.h:150
void DrawAxes(Axis< SCALE_X_TYPE > &x_axis, Axis< SCALE_Y_TYPE > &y_axis, Selection &selection)
Definition: axis.h:255
Definition: selection.h:936
Tools to build common SVG shapes.
D3::Axis< X_SCALE_TYPE > * GetXAxis()
Definition: visualizations.h:431
D3::LineGenerator * GetLineGenerator()
Definition: visualizations.h:433
void GetLastRow(emp::array< T, N > &arr)
Put the last row of the array into arr.
Definition: dataset.h:237
virtual void GetHTML(std::stringstream &HTML) override
Definition: visualizations.h:63
Selection SelectAll(std::string selector)
Definition: selection.h:1676
Definition: histogram.h:9
void RecordPlacement(int pos)
Definition: visualizations.h:924
iterator begin() noexcept
Definition: vector.h:153
emp::vector< std::string > variables
Definition: visualizations.h:121
D3Visualization(const D3Visualization &in)
Definition: visualizations.h:110
DERIVED & SetClassed(std::string classname, bool value)
Definition: selection.h:400
Scale & SetDomain(emp::array< T, SIZE > values)
Definition: scales.h:52
D3::Axis< D3::LinearScale > * ax
Definition: visualizations.h:168
void AppendNested(std::string json)
Definition: dataset.h:137
Axis & Draw(Selection &selection)
Definition: axis.h:79
If we are in emscripten, make sure to include the header.
Definition: array.h:37
D3::Selection svg
Definition: visualizations.h:51
emp::vector< int > GetLocHistory(int id)
Definition: visualizations.h:1093
void DrawTree()
Definition: visualizations.h:857
virtual ~D3VisualizationInfo()
Definition: visualizations.h:59
double y_margin
Definition: visualizations.h:92
LineGraph(std::string x_var="", std::string y_var="", int w=800, int h=400)
Definition: visualizations.h:373
D3::ToolTip * tip
Definition: visualizations.h:788
void AddDataPoint(DATA_TYPE data_point)
Smoothly (i.e. with animation) add data_point to the graph.
Definition: visualizations.h:602
D3VisualizationInfo * Info()
Definition: visualizations.h:86
BitSet< NUM_BITS1+NUM_BITS2 > join(const BitSet< NUM_BITS1 > &in1, const BitSet< NUM_BITS2 > &in2)
Definition: BitSet.h:586
Widget is effectively a smart pointer to a WidgetInfo object, plus some basic accessors.
Definition: Widget.h:78
int width
Definition: visualizations.h:48
void LoadDataFromFile(std::string filename)
Load data from the file at [filename]. Expected to be a CSV dataset.
Definition: visualizations.h:588
void SetLineGenerator(D3::LineGenerator *line)
Definition: visualizations.h:446
#define emp_assert(...)
Definition: assert.h:199
D3::Selection legend
Definition: visualizations.h:961
void DrawData(bool backlog=false)
Definition: visualizations.h:706
void LoadDataFromFile(std::string filename)
Definition: visualizations.h:839
Axis & Rescale(double new_min, double new_max, const D3::SelectionOrTransition< T > &svg)
Definition: axis.h:242
SpatialGridTreeVisualization(int width, int height)
Definition: visualizations.h:1112
double axis_width
Definition: visualizations.h:91
Handle drawing of axes on D3 graphts.
Selection & Move(int x, int y)
Definition: selection.h:1486
int GetWidth() const
Definition: visualizations.h:116
Tools for laying out nodes in D3.
X_SCALE_TYPE * x_scale
Definition: visualizations.h:340
D3Visualization(D3VisualizationInfo *in_info)
Definition: visualizations.h:89
void ExitRemove()
Selection must have an exit selection (i.e. have just had data bound to it).
Definition: selection.h:1204
Histogram & SetDomain(double x, double y)
Definition: histogram.h:29
virtual void Setup()
Definition: visualizations.h:390
void SetYAxis(D3::Axis< Y_SCALE_TYPE > *ax)
Definition: visualizations.h:445
void Clear()
Definition: visualizations.h:750
std::function< double(DATA_TYPE)> GetYAccessor()
Definition: visualizations.h:437
void SetTooltipFunction(std::string func)
Definition: visualizations.h:821
void SetDataset(D3::CSVDataset *d)
Definition: visualizations.h:447
Selection Data(Dataset &values, std::string key="")
Definition: selection.h:1008
TreeVisualization(int width=800, int height=400)
Definition: visualizations.h:813
Selection Append(std::string name)
Append DOM element(s) of the type specified by [name] to this selection.
Definition: selection.h:1417
void SetYScale(Y_SCALE_TYPE *scale)
Definition: visualizations.h:443
Selection DrawShape(emp::array< emp::array< T, 2 >, SIZE > &data, Selection &s)
Definition: svg_shapes.h:58
Definition: scales.h:142
virtual void Setup()
Definition: visualizations.h:234
Definition: visualizations.h:935
D3Visualization * parent
Definition: visualizations.h:50
Definition: visualizations.h:778
std::string GetID()
Definition: visualizations.h:119
Dataset Call(emp::vector< DATA_TYPE > data)
Definition: histogram.h:69
Definition: dataset.h:64
int GetID() const
Definition: d3_init.h:96
Histogram & Domain(double x, double y)
Definition: histogram.h:34
D3::Selection circles
Definition: visualizations.h:169
return_t & SetAttr(const std::string &setting, SETTING_TYPE &&value)
Set a specific Attribute value for this widget.
Definition: Widget.h:589
std::string draw_data_callback
Callback function for drawing data after rescale animation.
Definition: visualizations.h:126
TreeVisualizationReplacement(int width, int height)
Definition: visualizations.h:897
int next_pos
Definition: visualizations.h:892
virtual void Setup()
Definition: visualizations.h:259
WidgetFacet(const std::string &in_id="")
WidgetFacet cannot be built unless within derived class, so constructors are protected.
Definition: Widget.h:546
Definition: visual_elements.h:16
SCALE_TYPE & GetScale()
Get a reference to this object&#39;s scale.
Definition: axis.h:160
D3::Axis< X_SCALE_TYPE > * x_axis
Definition: visualizations.h:342
void RecordParent(int parent, int child)
Definition: visualizations.h:929
Definition: visualizations.h:331