artdaq_node_server  v1_01_01
MakeEventGraph.js
1 // Variables common to all graphs
2 var duration = 1000; // Transition animation duration
3 var colors = ["black","red","blue","green", "yellow","gray","fuchsia","navy","olive", "aqua", "lime", "maroon", "orange", "purple", "silver", "teal"];
4 var graphs = [];
5 var events = [];
6 var currentEvent = 0;
7 var eventsBehind = 0;
8 var partition = 0;
9 var moduleName = "artdaq-runcontrol";
10 var fetching = false;
11 var updateInterval = 500;
12 
13 function tick(graph, event) {
14  var transition = d3.select(graph.tag).transition()
15  .duration(duration)
16  .ease("linear").attrTween("transform", function () {
17 
18  var vals = $.map(event.fragments, function(v) {
19  return v.data[graph.dataElement];
20  });
21  $("#p" + partition + graph.dataElement + "value").text("Current Value(s): " + vals);
22 
23  for(var name in graph.data) {
24  var plotName = graph.data[name].name;
25  var value = vals[name];
26  graph.data[name].data.push({event:event.event,value:value});
27  }
28 
29  // update the domains
30  var xextent = [currentEvent, currentEvent];
31  for(var name in graph.data) {
32  var group = graph.data[name];
33  var thisExtent = d3.extent(group.data,function(d) { return d.event;});
34  if(thisExtent[0] < xextent[0]){xextent[0] = thisExtent[0];}
35  }
36  graph.x.domain(xextent);
37 
38  var extent = [0x1000000, 0];
39  for (var name in graph.data) {
40  var group = graph.data[name];
41  var thisExtent = d3.extent(group.data, function (d) { return d.value; });
42  if (thisExtent[0] < extent[0]) { extent[0] = thisExtent[0]; }
43  if (thisExtent[1] > extent[1]) { extent[1] = thisExtent[1]; }
44  }
45  graph.y.domain([extent[0] * 98 / 100, extent[1] * 102 / 100]);
46 
47 
48  // slide the x-axis left
49  graph.axes[0].call(graph.x.axis);
50  graph.axes[1].call(graph.y.axis);
51 
52  for(var name in graph.data) {
53  // redraw the line
54  graph.data[name].path
55  .attr("d", graph.line)
56  .attr("transform", null)
57  .transition()
58  .duration(duration)
59  .ease("linear")
60  .attr("transform", "translate(" + graph.x(xextent[0]) + ")");
61 
62  if(graph.caughtUp) {
63  graph.data[name].data = graph.data[name].data.sort(function(a,b) { return a.event - b.event; });
64  }
65  while (graph.data[name].data.length > 0 && graph.data[name].data[0].event < currentEvent - graph.n) {
66  graph.data[name].data.shift();
67  }
68  }
69 
70  if(graph.caughtUp) { graph.caughtUp = false;}
71  }).transition();
72  return graph;
73 }
74 
75 function DeleteGraph(dataElement) {
76  $("#p" + partition + dataElement + "plot").remove();
77 }
78 
79 function MakeEventGraph(tag, dataElement) {
80  data = [];
81  var margin = { top: 6, right: 20, bottom: 20, left: 60 },
82  width = $(tag).width() - margin.right - margin.left,
83  height = 120 - margin.top - margin.bottom;
84 
85  var x = d3.scale.linear()
86  .range([0, width]);
87 
88  var y = d3.scale.linear()
89  .range([height, 0]);
90 
91  var line = d3.svg.line()
92  .interpolate("linear")
93  .x(function (d) { return x(d.event); })
94  .y(function (d) { return y(d.value); });
95 
96  var svg = d3.select(tag).append("svg")
97  .attr("width", width + margin.left + margin.right)
98  .attr("height", height + margin.top + margin.bottom)
99  .style("margin-left", -margin.right + "px")
100  .append("g")
101  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
102 
103  svg.append("defs").append("clipPath")
104  .attr("id", "clip" + tag.replace('#', ""))
105  .append("rect")
106  .attr("width", width)
107  .attr("height", height);
108 
109  var xaxis = svg.append("g")
110  .attr("class", "x axis")
111  .attr("transform", "translate(0," + height + ")")
112  .call(x.axis = d3.svg.axis().scale(x).orient("bottom"));
113 
114  var formatTick = function (d) {
115  var prefix = d3.formatPrefix(d);
116  return prefix.scale(d) + " " + prefix.symbol + "";
117  }
118 
119  var yaxis = svg.append("g")
120  .attr("class", "y axis")
121  .attr("transform", "translate(0,0)")
122  .call(y.axis = d3.svg.axis().scale(y).tickFormat(formatTick).orient("left"));
123 
124  var paths = svg.append("g")
125  .attr("clip-path", "url(#clip" + tag.replace('#', "") + ")");
126 
127  var fragCount = events[0].fragments.length;
128 
129  for (var i = 0; i < fragCount; i++) {
130  if(events[0].fragments[i].data[dataElement]) {
131  var color = colors[i%colors.length];
132  var thisData = {};
133  thisData.name = i;
134  thisData.data = [];
135  for(var j = 0; j < events.length; j++) {
136  var value = events[j].fragments[i].data[dataElement];
137  thisData.data.push({event:events[j].event,value: value});
138  }
139  thisData.path = paths.append('path')
140  .data([thisData.data])
141  .attr('class', 'line')
142  .style('stroke', color);
143  data.push(thisData);
144  }
145  }
146 
147  this.paths = paths;
148  this.line = line;
149  this.axes = [xaxis, yaxis];
150  this.dataElement = dataElement;
151  this.x = x;
152  this.y = y;
153  this.data = data;
154  this.tag = tag;
155  this.n = 120;
156  this.update = function(event) { return tick(this, event); };
157 }
158 
159 function RedrawGraph(graph) {
160  for(var name in graph.data) {
161  while(graph.data[name].data.length > 0) {
162  graph.data[name].data.shift();
163  }
164  }
165 
166  for(var i = 0; i < events.length - 1; i++) {
167  var vals = $.map(events[i].fragments, function(v) {
168  return v.data[graph.dataElement];
169  });
170 
171  for(var name in graph.data) {
172  var plotName = graph.data[name].name;
173  var value = vals[name];
174  graph.data[name].data.push({event:events[i].event,value:value});
175  }
176  }
177 
178  graph.update(events[events.length - 1]);
179 }
180 
181 function CreateEventPlot(partition, dataElement)
182 {
183  if($("#p" + partition + dataElement + "plot").length == 0) {
184  $("#plots").append("<div id=\"p" +partition + dataElement + "plot\">"
185  + "<h3>"+dataElement+"</h3>"
186  +" <label id=\"p"+partition+dataElement+"value\"></label>&nbsp;&nbsp;"
187  + "<label>Number of Points to Plot:<input type=\"number\" min=1 value=120 id=\"p"+partition+dataElement+"nSelector\"></label>&nbsp;&nbsp;"
188  + "<button type=\"button\" id=\"p"+ partition + dataElement + "deletebutton\">Delete</button>"
189  + "<br>"
190  + "<div id=\"p" + partition + dataElement + "\"></div><br></div>");
191  $("#p"+partition+dataElement +"deletebutton").click(function() { DeleteGraph(dataElement); });
192  $("#p"+partition+dataElement +"nSelector").bind('keyup input', function() { graphs[dataElement].n = $("#p"+partition+dataElement+"nSelector").val(); RedrawGraph(graphs[dataElement]);});
193  graphs[dataElement] = new MakeEventGraph("#p" + partition + dataElement, dataElement);
194  graphs[dataElement].update(events[events.length - 1]);
195  }
196 }
197 
198 function Contains(arr, val)
199 {
200 for (var i = 0; i < arr.length; i++) {
201  if (arr[i] === val) {
202  return true;
203  }
204  }
205  return false;
206 }
207 
208 function UpdateGraphs()
209 {
210  if(!fetching) {
211  fetching = true;
212  var postData = {event: currentEvent, partition: partition};
213  d3.json("/"+moduleName+"/GetEvent").post(JSON.stringify(postData), function(error, data) {
214  //console.log("Data is " + data);
215  if(data && data != "" && data != "ENOEVT") {
216  updateInterval = 500;
217  var dataJSON = JSON.parse(data);
218  events.push(dataJSON);
219  var bigN = 120;
220  for(var graph in graphs) {
221  if(graphs[graph].n > bigN) { bigN = graphs[graph].n; }
222  graphs[graph] = graphs[graph].update(dataJSON);
223  }
224  while(events.length > bigN) { events.shift(); }
225  currentEvent = dataJSON.event + 1;
226  eventsBehind = dataJSON.lastEvent - dataJSON.event - 1;
227  }
228  else if(data && data == "ENOEVT") {
229  currentEvent++;
230  eventsBehind = 1;
231  }
232  else {
233  if(updateInterval < 10000) {
234  //Back off a bit
235  updateInterval += 500;
236  }
237  }
238  fetching = false;
239  });
240  }
241 
242  var gotBehind = false;
243  if(eventsBehind > 1 ) {
244  updateInterval = 10;
245  gotBehind = true;
246  }
247 
248  for(var graph in graphs) {
249  if(!gotBehind && graphs[graph].gotBehind) { graphs[graph].caughtUp = true; }
250  graphs[graph].gotBehind = gotBehind;
251  }
252 
253  setTimeout(function() { UpdateGraphs(); }, updateInterval);
254 }
255 
256 
257 function Onmon(tag, part, module)
258 {
259  moduleName = module;
260  partition = part;
261 
262  graphs = [];
263  events = [];
264  currentEvent = 0;
265  eventsBehind = 0;
266 
267  var postData = {event: 0, partition: partition};
268  d3.json("/"+moduleName+"/GetEvent").post(JSON.stringify(postData), function(error, serverdata) {
269  var data = JSON.parse(serverdata);
270  var names = [];
271  for(var frag in data.fragments) {
272  var fragData = data.fragments[frag];
273  if(fragData.header.data_type === 1) {
274  for(var iterator in fragData.data) {
275  if(!Contains(names, iterator)) {
276  names.push(iterator);
277  }
278  }
279  }
280  }
281 
282  var output = "";
283  for(var iterator in names) {
284  output += "<option value=\"" + names[iterator] + "\">" + names[iterator] + "</option>\n";
285  }
286  $(tag).html( "<fieldset>\n"
287  + "<select id=\"newPlotElement\">\n"
288  + output
289  + "</select>"
290  + "<button type=\"button\" id=\"addPlot\" onclick=\"CreateEventPlot(" + partition + ",$('#newPlotElement').val())\">Add</button>\n"
291  + "<div id=\"plots\"></div>"
292  + "</fieldset>");
293  });
294 
295  UpdateGraphs();
296 }