@@ -1,637 +1,647 | |||
|
1 | 1 | |
|
2 | 2 | var icon = { |
|
3 | 3 | 'width': 20, |
|
4 | 4 | 'path': 'M18.303,4.742l-1.454-1.455c-0.171-0.171-0.475-0.171-0.646,0l-3.061,3.064H2.019c-0.251,0-0.457,0.205-0.457,0.456v9.578c0,0.251,0.206,0.456,0.457,0.456h13.683c0.252,0,0.457-0.205,0.457-0.456V7.533l2.144-2.146C18.481,5.208,18.483,4.917,18.303,4.742 M15.258,15.929H2.476V7.263h9.754L9.695,9.792c-0.057,0.057-0.101,0.13-0.119,0.212L9.18,11.36h-3.98c-0.251,0-0.457,0.205-0.457,0.456c0,0.253,0.205,0.456,0.457,0.456h4.336c0.023,0,0.899,0.02,1.498-0.127c0.312-0.077,0.55-0.137,0.55-0.137c0.08-0.018,0.155-0.059,0.212-0.118l3.463-3.443V15.929z M11.241,11.156l-1.078,0.267l0.267-1.076l6.097-6.091l0.808,0.808L11.241,11.156z', |
|
5 | 5 | 'ascent': 20, |
|
6 | 6 | 'descent': 2, |
|
7 | 7 | }; |
|
8 | 8 | |
|
9 | 9 | function list2dict(values) { |
|
10 | 10 | |
|
11 | 11 | var o = {}; |
|
12 | 12 | $.each(values, function () { |
|
13 | 13 | o[this.name] = this.value; |
|
14 | 14 | }); |
|
15 | 15 | return o; |
|
16 | 16 | }; |
|
17 | 17 | /* In this class is defined all the function to RTI plot */ |
|
18 | 18 | class PcolorBuffer { |
|
19 | 19 | constructor({ div, data }) { |
|
20 | 20 | this.div = document.getElementById(div); |
|
21 | 21 | this.n = 0; |
|
22 | 22 | this.divs = []; |
|
23 | 23 | this.wait = false; |
|
24 | 24 | this.lastRan = Date.now(); |
|
25 | 25 | this.lastFunc = null; |
|
26 | 26 | this.zbuffer = []; |
|
27 | 27 | this.xbuffer = []; |
|
28 | 28 | this.empty = Array(data.metadata.yrange.length).fill(null); |
|
29 | 29 | this.timespan = 12; |
|
30 | 30 | this.metadata = data.metadata; |
|
31 | 31 | this.setup(data); |
|
32 | 32 | } |
|
33 | 33 | /* This function is used to plot all the data that have the DB and just is used when is loaded or reloaded*/ |
|
34 | 34 | setup(data) { |
|
35 | 35 | this.last = data.time.slice(-1); |
|
36 | var diffArr = []; | |
|
37 | for(var i=0; i<data.time.length-1; i++){ | |
|
38 | diffArr.push(data.time[i+1]-data.time[i]); | |
|
39 | } | |
|
40 | this.interval = Math.round(Math.min.apply(null, diffArr)*100 / 100); | |
|
36 | 41 | if (data.time.length == 1) { |
|
37 | 42 | var values = { 'time': data.time, 'data': data['data'].map(function (x) { return [x] }) }; |
|
38 | 43 | } else { |
|
39 |
var values = this.fill_gaps(data.time, data['data'], |
|
|
44 | var values = this.fill_gaps(data.time, data['data'], this.interval, data['data'].length); | |
|
40 | 45 | } |
|
41 | 46 | var t = values.time.map(function (x) { |
|
42 | 47 | var a = new Date(x * 1000); |
|
43 | 48 | // This condition is used to change from UTC to LT |
|
44 | 49 | if (data.metadata.localtime == true){ |
|
45 | 50 | a.setTime( a.getTime() + a.getTimezoneOffset()*60*1000 ); |
|
46 | 51 | } |
|
47 | 52 | return a; |
|
48 | 53 | }); |
|
49 | 54 | |
|
50 | 55 | var label; |
|
51 | 56 | if (data.metadata.localtime == true){ |
|
52 | 57 | label = "[LT]"; |
|
53 | 58 | |
|
54 | 59 | } |
|
55 | 60 | else{ |
|
56 | 61 | label = "[UTC]"; |
|
57 | 62 | } |
|
58 | 63 | |
|
59 | 64 | for (var i = 0; i < data['data'].length; i++) { |
|
60 | 65 | var layout = { |
|
61 | 66 | height: 350, |
|
62 | 67 | xaxis: { |
|
63 | 68 | title: 'Time ' + label, |
|
64 | 69 | showgrid: false, |
|
65 | 70 | linewidth: 2, |
|
66 | 71 | size: 12, |
|
67 | 72 | mirror: true, |
|
68 | 73 | }, |
|
69 | 74 | yaxis: { |
|
70 | 75 | title: data.metadata.ylabel || 'km', |
|
71 | 76 | showgrid: false, |
|
72 | 77 | linewidth: 2, |
|
73 | 78 | size: 12, |
|
74 | 79 | mirror: true, |
|
75 | 80 | }, |
|
76 | 81 | titlefont: { |
|
77 | 82 | size: 16, |
|
78 | 83 | }, |
|
79 | 84 | margin: { |
|
80 | 85 | t: 30, |
|
81 | 86 | } |
|
82 | 87 | }; |
|
83 | 88 | var iDiv = document.createElement('div'); |
|
84 | 89 | iDiv.id = 'plot-' + i; |
|
85 | 90 | //iDiv.className += iDiv.className ? ' col-lg-6 col-md-6 col-sm-12' : 'col-lg-6 col-md-12 col-sm-12'; |
|
86 | 91 | this.zbuffer.push([]); |
|
87 | 92 | this.n = this.n + 1; |
|
88 | 93 | this.div.appendChild(iDiv); |
|
89 | 94 | this.divs.push(iDiv.id); |
|
90 | 95 | var trace = { |
|
91 | 96 | z: values.data[i], |
|
92 | 97 | x: t, |
|
93 | 98 | y: data.metadata.yrange, |
|
94 | 99 | colorscale: this.metadata.colormap || 'Jet', |
|
95 | 100 | transpose: true, |
|
96 | 101 | type: 'heatmap' |
|
97 | 102 | }; |
|
98 | 103 | |
|
99 | 104 | if (this.metadata.zmin) { trace.zmin = this.metadata.zmin } |
|
100 | 105 | if (this.metadata.zmax) { trace.zmax = this.metadata.zmax } |
|
101 | 106 | |
|
102 | 107 | layout.title = 'Ch ' + i + ' - ' + t.slice(-1).toLocaleString(); |
|
103 | 108 | var conf = { |
|
104 | 109 | modeBarButtonsToRemove: ['sendDataToCloud', 'autoScale2d', 'hoverClosestCartesian', 'hoverCompareCartesian', 'lasso2d', 'select2d', 'zoomIn2d', 'zoomOut2d', 'toggleSpikelines'], |
|
105 | 110 | modeBarButtonsToAdd: [{ |
|
106 | 111 | name: 'Edit plot', |
|
107 | 112 | icon: icon, |
|
108 | 113 | click: function (gd) { |
|
109 | 114 | var div = gd.id; |
|
110 | 115 | $('input[id=id_plotdiv]').val(div); |
|
111 | 116 | $('#setup').modal('show'); |
|
112 | 117 | } |
|
113 | 118 | }], |
|
114 | 119 | displaylogo: false, |
|
115 | 120 | showTips: true |
|
116 | 121 | }; |
|
117 | 122 | Plotly.newPlot('plot-' + i, [trace], layout, conf); |
|
118 | 123 | } |
|
119 | 124 | } |
|
120 | 125 | |
|
121 | 126 | getSize() { |
|
122 | 127 | var div = document.getElementById(this.divs[0]); |
|
123 | 128 | var t = this.xbuffer.slice(-1)[0]; |
|
124 | 129 | var n = 0; |
|
125 | 130 | var timespan = this.timespan * 1000 * 60 * 60; |
|
126 | 131 | |
|
127 | 132 | while ((t - div.data[0].x[n]) > timespan) { |
|
128 | 133 | n += 1; |
|
129 | 134 | } |
|
130 | 135 | return n; |
|
131 | 136 | } |
|
132 | 137 | |
|
133 | 138 | fill_gaps(xBuffer, zBuffer, interval, N) { |
|
134 | 139 | |
|
135 | 140 | var x = [xBuffer[0]]; |
|
136 | 141 | var z = []; |
|
137 | 142 | var last; |
|
138 | 143 | |
|
139 | 144 | for (var j = 0; j < N; j++) { |
|
140 | 145 | z.push([zBuffer[j][0]]); |
|
141 | 146 | } |
|
142 | 147 | |
|
143 | 148 | for (var i = 1; i < xBuffer.length; i++) { |
|
144 | 149 | var cnt = 0; |
|
145 | 150 | last = x[x.length-1]; |
|
146 | 151 | while (Math.abs(parseFloat(xBuffer[i]) - last ) > 1.5 * parseFloat(interval)) { |
|
147 | 152 | cnt += 1; |
|
148 | 153 | last = last + interval; |
|
149 | 154 | x.push(last); |
|
150 | 155 | for (var j = 0; j < N; j++) { |
|
151 | 156 | z[j].push(this.empty); |
|
152 | 157 | } |
|
153 | 158 | // Avoid infinite loop |
|
154 | 159 | if (cnt == 100) { break; } |
|
155 | 160 | } |
|
156 | 161 | x.push(xBuffer[i]); |
|
157 | 162 | for (var j = 0; j < N; j++) { |
|
158 | 163 | z[j].push(zBuffer[j][i]); |
|
159 | 164 | } |
|
160 | 165 | } |
|
161 | 166 | return { 'time': x, 'data': z }; |
|
162 | 167 | } |
|
163 | 168 | |
|
164 | 169 | plot() { |
|
165 | 170 | // add new data to plots and empty buffers |
|
166 | 171 | var N = this.getSize(); |
|
167 | 172 | console.log('Plotting...'); |
|
168 | 173 | for (var i = 0; i < this.n; i++) { |
|
169 | 174 | var div = document.getElementById(this.divs[i]); |
|
170 | 175 | if (N > 0) { |
|
171 | 176 | div.data[0].z = div.data[0].z.slice(N, ) |
|
172 | 177 | div.data[0].x = div.data[0].x.slice(N, ) |
|
173 | 178 | } |
|
174 | 179 | Plotly.extendTraces(div, { |
|
175 | 180 | z: [this.zbuffer[i]], |
|
176 | 181 | x: [this.xbuffer] |
|
177 | 182 | }, [0]); |
|
178 | 183 | this.zbuffer[i] = []; |
|
179 | 184 | } |
|
180 | 185 | this.xbuffer = []; |
|
181 | 186 | } |
|
182 | 187 | //This function just add the last data and is used if previously was used setup() |
|
183 | 188 | update(obj) { |
|
184 | 189 | |
|
185 | 190 | // fill data gaps |
|
186 | 191 | var cnt = 0; |
|
187 | 192 | |
|
188 |
while (Math.abs(parseFloat(obj.time[0]) - this.last) > 1.5 * parseFloat( |
|
|
193 | while (Math.abs(parseFloat(obj.time[0]) - this.last) > 1.5 * parseFloat(this.interval)) { | |
|
189 | 194 | cnt += 1; |
|
190 |
this.last += |
|
|
195 | this.last += this.interval; | |
|
191 | 196 | var newt = new Date((this.last) * 1000); |
|
192 | 197 | // This condition is used to change from UTC to LT |
|
193 | 198 | if (obj.metadata.localtime == true){ |
|
194 | 199 | newt.setTime( newt.getTime() + newt.getTimezoneOffset()*60*1000 ); |
|
195 | 200 | } |
|
196 | 201 | this.xbuffer.push(newt); |
|
197 | 202 | for (var i = 0; i < obj['data'].length; i++) { |
|
198 | 203 | this.zbuffer[i].push(this.empty); |
|
199 | 204 | } |
|
200 | 205 | // Avoid infinite loop |
|
201 | 206 | if (cnt == 100) { break; } |
|
202 | 207 | } |
|
203 | 208 | |
|
204 | 209 | // update buffers |
|
205 | 210 | this.last = parseFloat(obj.time[0]); |
|
206 | 211 | var t = new Date(obj.time[0] * 1000); |
|
207 | 212 | // This condition is used to change from UTC to LT |
|
208 | 213 | if (obj.metadata.localtime == true){ |
|
209 | 214 | t.setTime( t.getTime() + t.getTimezoneOffset()*60*1000 ); |
|
210 | 215 | } |
|
211 | 216 | this.xbuffer.push(t); |
|
212 | 217 | for (var i = 0; i < obj['data'].length; i++) { |
|
213 | 218 | this.zbuffer[i].push(obj['data'][i]); |
|
214 | 219 | var div = document.getElementById(this.divs[i]); |
|
215 | 220 | Plotly.relayout(div, { |
|
216 | 221 | title: 'Ch ' + i + ' - ' + t.toLocaleString(), |
|
217 | 222 | }); |
|
218 | 223 | } |
|
219 | 224 | |
|
220 | 225 | if (!this.wait) { |
|
221 | 226 | this.plot(); |
|
222 | 227 | this.wait = true; |
|
223 | 228 | } else { |
|
224 | 229 | clearTimeout(this.lastFunc) |
|
225 | 230 | this.lastFunc = setTimeout(function (scope) { |
|
226 | 231 | if ((Date.now() - scope.lastRan) >= 30000) { |
|
227 | 232 | scope.plot() |
|
228 | 233 | scope.lastRan = Date.now() |
|
229 | 234 | } |
|
230 | 235 | }, 30000 - (Date.now() - this.lastRan), this) |
|
231 | 236 | } |
|
232 | 237 | } |
|
233 | 238 | // With this function You can change parameters in your plot |
|
234 | 239 | restyle(values) { |
|
235 | 240 | |
|
236 | 241 | var values = list2dict(values); |
|
237 | 242 | var div = document.getElementById(values.plotdiv); |
|
238 | 243 | |
|
239 | 244 | Plotly.relayout(div, { |
|
240 | 245 | yaxis: { |
|
241 | 246 | range: [values.ymin, values.ymax], |
|
242 | 247 | title: this.metadata.ylabel || 'km', |
|
243 | 248 | linewidth: 2, |
|
244 | 249 | size: 12, |
|
245 | 250 | mirror: true, |
|
246 | 251 | } |
|
247 | 252 | |
|
248 | 253 | }); |
|
249 | 254 | |
|
250 | 255 | Plotly.restyle(div, { |
|
251 | 256 | zmin: values.zmin, |
|
252 | 257 | zmax: values.zmax, |
|
253 | 258 | colorscale: values.colormap |
|
254 | 259 | }); |
|
255 | 260 | } |
|
256 | 261 | } |
|
257 | 262 | /* In this class is defined all the function to SPC plot */ |
|
258 | 263 | class Pcolor { |
|
259 | 264 | constructor({ div, data }) { |
|
260 | 265 | this.div = document.getElementById(div); |
|
261 | 266 | this.n = 0; |
|
262 | 267 | this.divs = []; |
|
263 | 268 | this.metadata = data.metadata; |
|
264 | 269 | this.setup(data); |
|
265 | 270 | } |
|
266 | 271 | /* This function is used to plot all the data that have the DB and just is used when is loaded or reloaded*/ |
|
267 | 272 | setup(data) { |
|
268 | 273 | for (var i = 0; i < data['data'].length; i++) { |
|
269 | 274 | var layout = { |
|
270 | 275 | margin: { |
|
271 | 276 | t:30, |
|
272 | 277 | }, |
|
273 | 278 | height: 320, |
|
274 | 279 | xaxis: { |
|
275 | 280 | title: data.metadata.xlabel || 'Velocity', |
|
276 | 281 | showgrid: false, |
|
277 | 282 | zeroline: false, |
|
278 | 283 | linewidth: 2, |
|
279 | 284 | mirror: true, |
|
280 | 285 | size: 12, |
|
281 | 286 | }, |
|
282 | 287 | yaxis: { |
|
283 | 288 | title: data.metadata.ylabel || 'km', |
|
284 | 289 | showgrid: false, |
|
285 | 290 | linewidth: 2, |
|
286 | 291 | mirror: 'all', |
|
287 | 292 | size: 12, |
|
288 | 293 | }, |
|
289 | 294 | titlefont: { |
|
290 | 295 | size: 14 |
|
291 | 296 | }, |
|
292 | 297 | }; |
|
293 | 298 | var iDiv = document.createElement('div'); |
|
294 | 299 | iDiv.id = 'plot-' + i; |
|
295 | 300 | iDiv.className += iDiv.className ? ' col-md-5' : 'col-md-5'; |
|
296 | 301 | this.n = this.n + 1; |
|
297 | 302 | this.div.appendChild(iDiv); |
|
298 | 303 | this.divs.push(iDiv.id); |
|
299 | 304 | var iDiv = document.createElement('div'); |
|
300 | 305 | iDiv.className = 'col-md-1'; |
|
301 | 306 | this.div.appendChild(iDiv); |
|
302 | 307 | var trace1 = { |
|
303 | 308 | z: data['data'][i], |
|
304 | 309 | y: data.metadata.yrange, |
|
305 | 310 | x: data.metadata.xrange, |
|
306 | 311 | colorscale: this.metadata.colormap || 'Jet', |
|
307 | 312 | transpose: true, |
|
308 | 313 | type: 'heatmap' |
|
309 | 314 | }; |
|
310 | 315 | |
|
311 | 316 | if (this.metadata.zmin) { |
|
312 | 317 | trace1.zmin = this.metadata.zmin |
|
313 | 318 | } |
|
314 | 319 | if (this.metadata.zmax) { |
|
315 | 320 | trace1.zmax = this.metadata.zmax; |
|
316 | 321 | } |
|
317 | 322 | |
|
318 | 323 | var t = new Date(data.time * 1000); |
|
319 | 324 | if (data.metadata.localtime == true){ |
|
320 | 325 | t.setTime( t.getTime() + t.getTimezoneOffset()*60*1000 ); |
|
321 | 326 | } |
|
322 | 327 | if ('titles' in data.metadata){ |
|
323 | 328 | layout.title = data.metadata.titles[i] + ' ' + t.toLocaleString(); |
|
324 | 329 | }else{ |
|
325 | 330 | layout.title = 'Ch ' + i + ': ' + t.toLocaleString(); |
|
326 | 331 | } |
|
327 | 332 | var conf = { |
|
328 | 333 | modeBarButtonsToRemove: ['sendDataToCloud', 'autoScale2d', 'hoverClosestCartesian', 'hoverCompareCartesian', 'lasso2d', 'select2d', 'zoomIn2d', 'zoomOut2d', 'toggleSpikelines'], |
|
329 | 334 | modeBarButtonsToAdd: [{ |
|
330 | 335 | name: 'Edit plot', |
|
331 | 336 | icon: icon, |
|
332 | 337 | click: function (gd) { |
|
333 | 338 | var div = gd.id; |
|
334 | 339 | $('input[id=id_plotdiv]').val(div); |
|
335 | 340 | $('#setup').modal('show'); |
|
336 | 341 | } |
|
337 | 342 | }], |
|
338 | 343 | displaylogo: false, |
|
339 | 344 | showTips: true |
|
340 | 345 | }; |
|
341 | 346 | |
|
342 | 347 | var traces = [trace1] |
|
343 | 348 | |
|
344 | 349 | Plotly.newPlot('plot-' + i, traces, layout, conf); |
|
345 | 350 | } |
|
346 | 351 | } |
|
347 | 352 | |
|
348 | 353 | plot(obj) { |
|
349 | 354 | this.data = obj; |
|
350 | 355 | // add new data to plots and empty buffers |
|
351 | 356 | console.log('Plotting...'); |
|
352 | 357 | var t = new Date(obj.time[0] * 1000); |
|
353 | 358 | // This condition is used to change from UTC to LT |
|
354 | 359 | if (obj.metadata.localtime == true){ |
|
355 | 360 | t.setTime( t.getTime() + t.getTimezoneOffset()*60*1000 ); |
|
356 | 361 | } |
|
357 | 362 | for (var i = 0; i < this.n; i++) { |
|
358 | 363 | var div = document.getElementById(this.divs[i]); |
|
359 | 364 | |
|
360 | 365 | if ('titles' in obj.metadata){ |
|
361 | 366 | var title = obj.metadata.titles[i] + ' ' + t.toLocaleString(); |
|
362 | 367 | }else{ |
|
363 | 368 | var title = 'Ch ' + i + ': ' + t.toLocaleString(); |
|
364 | 369 | } |
|
365 | 370 | |
|
366 | 371 | Plotly.relayout(div, { |
|
367 | 372 | title: title, |
|
368 | 373 | }); |
|
369 | 374 | |
|
370 | 375 | Plotly.restyle(div, { |
|
371 | 376 | z: [obj['data'][i]], |
|
372 | 377 | x: [obj.xrange] |
|
373 | 378 | }, [0]); |
|
374 | 379 | } |
|
375 | 380 | } |
|
376 | 381 | |
|
377 | 382 | update(data) { |
|
378 | 383 | this.plot(data); |
|
379 | 384 | } |
|
380 | 385 | |
|
381 | 386 | restyle(values) { |
|
382 | 387 | |
|
383 | 388 | var values = list2dict(values); |
|
384 | 389 | var div = document.getElementById(values.plotdiv); |
|
385 | 390 | |
|
386 | 391 | Plotly.relayout(div, { |
|
387 | 392 | yaxis: { |
|
388 | 393 | title: this.metadata.ylabel || 'km', |
|
389 | 394 | linewidth: 2, |
|
390 | 395 | range: [values.ymin, values.ymax] |
|
391 | 396 | }, |
|
392 | 397 | xaxis: { |
|
393 | 398 | title: this.metadata.xlabel || 'Velocity', |
|
394 | 399 | linewidth: 2, |
|
395 | 400 | mirror: true, |
|
396 | 401 | range: [values.xmin, values.xmax] |
|
397 | 402 | } |
|
398 | 403 | }); |
|
399 | 404 | |
|
400 | 405 | Plotly.restyle(div, { |
|
401 | 406 | zmin: values.zmin, |
|
402 | 407 | zmax: values.zmax, |
|
403 | 408 | colorscale: values.colormap |
|
404 | 409 | }); |
|
405 | 410 | } |
|
406 | 411 | } |
|
407 | 412 | |
|
408 | 413 | class ScatterBuffer { |
|
409 | 414 | constructor({ div, data }) { |
|
410 | 415 | this.div = document.getElementById(div); |
|
411 | 416 | this.n = 0; |
|
412 | 417 | this.wait = false; |
|
413 | 418 | this.lastRan = Date.now(); |
|
414 | 419 | this.lastFunc = null; |
|
415 | 420 | this.ybuffer = []; |
|
416 | 421 | this.xbuffer = []; |
|
417 | 422 | this.timespan = 12; |
|
418 | 423 | this.metadata = data.metadata; |
|
419 | 424 | this.setup(data); |
|
420 | 425 | } |
|
421 | 426 | /* This function is used to plot all the data that have the DB and just is used when is loaded or reloaded*/ |
|
422 | 427 | setup(data) { |
|
423 | 428 | |
|
424 | //this.data = data; | |
|
425 | 429 |
|
|
426 | 430 | this.last = data.time.slice(-1); |
|
431 | var diffArr = []; | |
|
432 | for(var i=0; i<data.time.length-1; i++){ | |
|
433 | diffArr.push(data.time[i+1]-data.time[i]); | |
|
434 | } | |
|
435 | this.interval = Math.round(Math.min.apply(null, diffArr)*100 / 100); | |
|
436 | ||
|
427 | 437 | if (data.time.length == 1) { |
|
428 | 438 | var values = { 'time': data.time, 'data': data['data'] }; |
|
429 | 439 | } else { |
|
430 |
var values = this.fill_gaps(data.time, data['data'], |
|
|
440 | var values = this.fill_gaps(data.time, data['data'], this.interval, data['data'].length); | |
|
431 | 441 | } |
|
432 | 442 | |
|
433 | 443 | var t = values.time.map(function (x) { |
|
434 | 444 | var a = new Date(x * 1000); |
|
435 | 445 | // This condition is used to change from UTC to LT |
|
436 | 446 | if (data.metadata.localtime == true){ |
|
437 | 447 | a.setTime( a.getTime() + a.getTimezoneOffset()*60*1000 ); |
|
438 | 448 | } |
|
439 | 449 | return a; |
|
440 | 450 | }); |
|
441 | 451 | |
|
442 | 452 | for (var i = 0; i < data['data'].length; i++) { |
|
443 | 453 | |
|
444 | 454 | this.n = this.n + 1; |
|
445 | 455 | this.ybuffer.push([]); |
|
446 | 456 | var trace = { |
|
447 | 457 | x: t, |
|
448 | 458 | y: values.data[i], |
|
449 | 459 | mode: 'lines', |
|
450 | 460 | type: 'scatter', |
|
451 | 461 | name: 'Channel ' + i, |
|
452 | 462 | connectgaps: false, |
|
453 | 463 | }; |
|
454 | 464 | |
|
455 | 465 | traces.push(trace); |
|
456 | 466 | } |
|
457 | 467 | |
|
458 | 468 | var label; |
|
459 | 469 | if (data.metadata.localtime == true){ |
|
460 | 470 | label = "[LT]"; |
|
461 | 471 | |
|
462 | 472 | } |
|
463 | 473 | else{ |
|
464 | 474 | label = "[UTC]"; |
|
465 | 475 | } |
|
466 | 476 | |
|
467 | 477 | var layout = { |
|
468 | 478 | height: 300, |
|
469 | 479 | title: t.slice(-1).toLocaleString(), |
|
470 | 480 | font: { |
|
471 | 481 | size: 12, |
|
472 | 482 | }, |
|
473 | 483 | xaxis: { |
|
474 | 484 | title: 'Time ' + label, |
|
475 | 485 | size: 12, |
|
476 | 486 | linewidth: 2, |
|
477 | 487 | mirror: true, |
|
478 | 488 | }, |
|
479 | 489 | yaxis: { |
|
480 | 490 | title: data.metadata.ylabel || 'dB', |
|
481 | 491 | linewidth: 2, |
|
482 | 492 | mirror: true, |
|
483 | 493 | }, |
|
484 | 494 | titlefont: { |
|
485 | 495 | size: 16, |
|
486 | 496 | }, |
|
487 | 497 | margin: { |
|
488 | 498 | t: 30, |
|
489 | 499 | } |
|
490 | 500 | }; |
|
491 | 501 | |
|
492 | 502 | if (data.metadata.ymin) { layout.yaxis.range = [data.metadata.ymin, data.metadata.ymax] } |
|
493 | 503 | |
|
494 | 504 | var conf = { |
|
495 | 505 | modeBarButtonsToRemove: ['sendDataToCloud', 'autoScale2d', 'hoverClosestCartesian', 'hoverCompareCartesian', 'lasso2d', 'select2d', 'zoomIn2d', 'zoomOut2d', 'toggleSpikelines'], |
|
496 | 506 | modeBarButtonsToAdd: [{ |
|
497 | 507 | name: 'Edit plot', |
|
498 | 508 | icon: icon, |
|
499 | 509 | click: function (gd) { |
|
500 | 510 | $('#setup').modal('show'); |
|
501 | 511 | } |
|
502 | 512 | }], |
|
503 | 513 | displaylogo: false, |
|
504 | 514 | showTips: true |
|
505 | 515 | }; |
|
506 | 516 | Plotly.newPlot('plot', traces, layout, conf); |
|
507 | 517 | } |
|
508 | 518 | |
|
509 | 519 | getSize() { |
|
510 | 520 | var t = this.xbuffer.slice(-1)[0]; |
|
511 | 521 | var n = 0; |
|
512 | 522 | var timespan = this.timespan * 1000 * 60 * 60; |
|
513 | 523 | |
|
514 | 524 | while ((t - this.div.data[0].x[n]) > timespan) { |
|
515 | 525 | n += 1; |
|
516 | 526 | } |
|
517 | 527 | return n; |
|
518 | 528 | } |
|
519 | 529 | |
|
520 | 530 | fill_gaps(xBuffer, yBuffer, interval, N) { |
|
521 | 531 | |
|
522 | 532 | var x = [xBuffer[0]]; |
|
523 | 533 | var y = []; |
|
524 | 534 | |
|
525 | 535 | for (var j = 0; j < N; j++) { |
|
526 | 536 | y.push([yBuffer[j][0]]); |
|
527 | 537 | } |
|
528 | 538 | |
|
529 | 539 | var last; |
|
530 | 540 | |
|
531 | 541 | for (var i = 1; i < xBuffer.length; i++) { |
|
532 | 542 | var cnt = 0; |
|
533 | 543 | last = x.slice(-1)[0]; |
|
534 | 544 | while (Math.abs(parseFloat(xBuffer[i]) - last) > 1.5 * parseFloat(interval)) { |
|
535 | 545 | cnt += 1; |
|
536 | 546 | last = last + interval; |
|
537 | 547 | x.push(last); |
|
538 | 548 | for (var j = 0; j < N; j++) { |
|
539 | 549 | y[j].push(null); |
|
540 | 550 | } |
|
541 | 551 | // Avoid infinite loop |
|
542 | 552 | if (cnt == 50) { break; } |
|
543 | 553 | } |
|
544 | 554 | x.push(xBuffer[i]); |
|
545 | 555 | |
|
546 | 556 | for (var j = 0; j < N; j++) { |
|
547 | 557 | y[j].push(yBuffer[j][i]); |
|
548 | 558 | } |
|
549 | 559 | } |
|
550 | 560 | return { 'time': x, 'data': y }; |
|
551 | 561 | } |
|
552 | 562 | |
|
553 | 563 | plot() { |
|
554 | 564 | // add new data to plots and empty buffers |
|
555 | 565 | var xvalues = []; |
|
556 | 566 | var yvalues = []; |
|
557 | 567 | var traces = []; |
|
558 | 568 | var N = this.getSize(); |
|
559 | 569 | console.log('Plotting...'); |
|
560 | 570 | for (var i = 0; i < this.n; i++) { |
|
561 | 571 | if (N > 0) { |
|
562 | 572 | this.div.data[i].y = this.div.data[i].y.slice(N, ) |
|
563 | 573 | this.div.data[i].x = this.div.data[i].x.slice(N, ) |
|
564 | 574 | } |
|
565 | 575 | yvalues.push(this.ybuffer[i]); |
|
566 | 576 | xvalues.push(this.xbuffer); |
|
567 | 577 | traces.push(i); |
|
568 | 578 | this.ybuffer[i] = []; |
|
569 | 579 | } |
|
570 | 580 | Plotly.extendTraces(this.div, { |
|
571 | 581 | y: yvalues, |
|
572 | 582 | x: xvalues |
|
573 | 583 | }, traces); |
|
574 | 584 | this.xbuffer = []; |
|
575 | 585 | } |
|
576 | 586 | //This function just add the last data and is used if previously was used setup() |
|
577 | 587 | update(obj) { |
|
578 | 588 | // fill data gaps |
|
579 | 589 | var cnt = 0; |
|
580 |
while (Math.abs(parseFloat(obj.time[0]) - this.last ) > 1.5 * parseFloat( |
|
|
590 | while (Math.abs(parseFloat(obj.time[0]) - this.last ) > 1.5 * parseFloat(this.interval)) { | |
|
581 | 591 | cnt += 1; |
|
582 |
this.last += |
|
|
592 | this.last += this.interval; | |
|
583 | 593 | var newt = new Date((this.last) * 1000); |
|
584 | 594 | // This condition is used to change from UTC to LT |
|
585 | 595 | if (obj.metadata.localtime == true){ |
|
586 | 596 | newt.setTime( newt.getTime() + newt.getTimezoneOffset()*60*1000 ); |
|
587 | 597 | } |
|
588 | 598 | this.xbuffer.push(newt); |
|
589 | 599 | for (var i = 0; i < this.n; i++) { |
|
590 | 600 | this.ybuffer[i].push(null); |
|
591 | 601 | } |
|
592 | 602 | // Avoid infinite loop |
|
593 | 603 | if (cnt == 100) { break; } |
|
594 | 604 | } |
|
595 | 605 | |
|
596 | 606 | // update buffers |
|
597 | 607 | this.last = parseFloat(obj.time[0]); |
|
598 | 608 | var t = new Date(obj.time[0] * 1000); |
|
599 | 609 | // This condition is used to change from UTC to LT |
|
600 | 610 | if (obj.metadata.localtime == true){ |
|
601 | 611 | t.setTime( t.getTime() + t.getTimezoneOffset()*60*1000 ); |
|
602 | 612 | } |
|
603 | 613 | this.xbuffer.push(t); |
|
604 | 614 | for (var i = 0; i < this.n; i++) { |
|
605 | 615 | this.ybuffer[i].push(obj['data'][i][0]); |
|
606 | 616 | } |
|
607 | 617 | |
|
608 | 618 | Plotly.relayout(this.div, { |
|
609 | 619 | title: t.toLocaleString(), |
|
610 | 620 | }); |
|
611 | 621 | |
|
612 | 622 | if (!this.wait) { |
|
613 | 623 | this.plot(); |
|
614 | 624 | this.wait = true; |
|
615 | 625 | } else { |
|
616 | 626 | clearTimeout(this.lastFunc) |
|
617 | 627 | this.lastFunc = setTimeout(function (scope) { |
|
618 | 628 | if ((Date.now() - scope.lastRan) >= 30000) { |
|
619 | 629 | scope.plot() |
|
620 | 630 | scope.lastRan = Date.now() |
|
621 | 631 | } |
|
622 | 632 | }, 30000 - (Date.now() - this.lastRan), this) |
|
623 | 633 | } |
|
624 | 634 | } |
|
625 | 635 | |
|
626 | 636 | restyle(values) { |
|
627 | 637 | |
|
628 | 638 | var values = list2dict(values); |
|
629 | 639 | Plotly.relayout(this.div, { |
|
630 | 640 | yaxis: { |
|
631 | 641 | range: [values.ymin, values.ymax], |
|
632 | 642 | title: this.metadata.ylabel || 'dB' |
|
633 | 643 | } |
|
634 | 644 | |
|
635 | 645 | }); |
|
636 | 646 | } |
|
637 | 647 | } |
General Comments 0
You need to be logged in to leave comments.
Login now