var icon = { 'width': 20, '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', 'ascent': 20, 'descent': 2, }; function list2dict(values) { var o = {}; $.each(values, function () { o[this.name] = this.value; }); return o; }; /* In this class is defined all the function to RTI plot */ class PcolorBuffer { constructor({ div, data, key, props }) { this.div = document.getElementById(div); this.n = 0; this.divs = []; this.wait = false; this.key = key; this.timer = (props.throttle || 30) * 1000; this.lastRan = Date.now(); this.lastFunc = null; this.zbuffer = []; this.xbuffer = []; this.empty = Array(data.yrange.length).fill(null); this.props = props; this.setup(data); } /* This function is used to plot all the data that have the DB and just is used when is loaded or reloaded*/ setup(data) { this.last = data.time.slice(-1); if (data.time.length == 1) { var values = { 'time': data.time, 'data': data[this.key].map(function (x) { return [x] }) }; } else { var values = this.fill_gaps(data.time, data[this.key], data.interval, data[this.key].length); } var t = values.time.map(function (x) { var a = new Date(x * 1000); // This condition is used to change from UTC to LT if (data.localtime == true){ a.setTime( a.getTime() + a.getTimezoneOffset()*60*1000 ); } return a; }); var label; if (data.localtime == true){ label = "LT"; } else{ label = "UTC"; } for (var i = 0; i < data[this.key].length; i++) { var layout = { xaxis: { title: 'Time ' + label, showgrid: false, linecolor: 'rgb(40, 223, 247)', color: 'rgb(40, 223, 247)', size: 24, titlefont: { color: 'white', size: 24 }, }, yaxis: { title: 'km', showgrid: false, linecolor: 'rgb(40, 223, 247)', color: 'rgb(40, 223, 247)', size: 24, titlefont: { color: 'white', size: 24 }, }, paper_bgcolor: 'black', plot_bgcolor: 'white', titlefont: { color: 'white', size: 24, }, font: { color: 'rgb(40, 223, 247)' } }; var iDiv = document.createElement('div'); iDiv.id = 'plot-' + i; this.zbuffer.push([]); this.n = this.n + 1; this.div.appendChild(iDiv); this.divs.push(iDiv.id); var trace = { z: values.data[i], x: t, y: data.yrange, colorscale: this.props.colormap || 'Jet', transpose: true, type: 'heatmap' }; if (this.props.zmin) { trace.zmin = this.props.zmin } if (this.props.zmax) { trace.zmax = this.props.zmax } layout.title = 'Channel ' + i + ' - ' + t.slice(-1).toLocaleString(); var conf = { modeBarButtonsToRemove: ['sendDataToCloud', 'autoScale2d', 'hoverClosestCartesian', 'hoverCompareCartesian', 'lasso2d', 'select2d', 'zoomIn2d', 'zoomOut2d', 'toggleSpikelines'], modeBarButtonsToAdd: [{ name: 'Edit plot', icon: icon, click: function (gd) { var div = gd.id; $('input[id=id_plotdiv]').val(div); $('#setup').modal('show'); } }], displaylogo: false, showTips: true }; Plotly.newPlot('plot-' + i, [trace], layout, conf); } } getSize() { var div = document.getElementById(this.divs[0]); var t = this.xbuffer.slice(-1)[0]; var n = 0; var timespan = (this.props.timespan || 8) * 1000 * 60 * 60; //If i dont put timespan in rti.html, by default is 8hs while ((t - div.data[0].x[n]) > timespan) { n += 1; } return n; } fill_gaps(xBuffer, zBuffer, interval, N) { var x = [xBuffer[0]]; var z = []; var last; for (var j = 0; j < N; j++) { z.push([zBuffer[j][0]]); } for (var i = 1; i < xBuffer.length; i++) { var cnt = 0; last = x.slice(-1)[0]; while (Math.abs(parseFloat(xBuffer[i]) - last ) > 1.5 * parseFloat(interval)) { //console.log(parseFloat(xBuffer[i])); //console.log(last); //console.log(Math.abs(parseFloat(xBuffer[i]) - last)); //console.log(parseFloat(interval)); //console.log("=========="); cnt += 1; last = last + interval; x.push(last); for (var j = 0; j < N; j++) { z[j].push(this.empty); } // Avoid infinite loop if (cnt == 100) { break; } } x.push(xBuffer[i]); for (var j = 0; j < N; j++) { z[j].push(zBuffer[j][i]); } } return { 'time': x, 'data': z }; } plot() { // add new data to plots and empty buffers var N = this.getSize(); console.log('Plotting...'); for (var i = 0; i < this.n; i++) { var div = document.getElementById(this.divs[i]); if (N > 0) { div.data[0].z = div.data[0].z.slice(N, ) div.data[0].x = div.data[0].x.slice(N, ) } Plotly.extendTraces(div, { z: [this.zbuffer[i]], x: [this.xbuffer] }, [0]); this.zbuffer[i] = []; } this.xbuffer = []; } //This function just add the last data and is used if previously was used setup() update(obj) { // fill data gaps var cnt = 0; console.log('updating'); while (Math.abs(parseFloat(obj.time[0]) - this.last) > 1.5 * parseFloat(obj.interval)) { cnt += 1; this.last += obj.interval; var newt = new Date((this.last) * 1000); // This condition is used to change from UTC to LT if (obj.localtime == true){ newt.setTime( newt.getTime() + newt.getTimezoneOffset()*60*1000 ); } this.xbuffer.push(newt); for (var i = 0; i < obj[this.key].length; i++) { this.zbuffer[i].push(this.empty); } // Avoid infinite loop if (cnt == 100) { break; } } // update buffers this.last = parseFloat(obj.time[0]); var t = new Date(obj.time[0] * 1000); // This condition is used to change from UTC to LT if (obj.localtime == true){ t.setTime( t.getTime() + t.getTimezoneOffset()*60*1000 ); } this.xbuffer.push(t); for (var i = 0; i < obj[this.key].length; i++) { this.zbuffer[i].push(obj[this.key][i]); // update title var title = this.props.title || '' var div = document.getElementById(this.divs[i]); Plotly.relayout(div, { title: title + ': Channel ' + i + ' - ' + t.toLocaleString(), }); } // plot when ready (every 10 secs) if (!this.wait) { this.plot(); this.wait = true; } else { clearTimeout(this.lastFunc) this.lastFunc = setTimeout(function (scope) { if ((Date.now() - scope.lastRan) >= scope.timer) { scope.plot() scope.lastRan = Date.now() } }, this.timer - (Date.now() - this.lastRan), this) } } // With this function You can change parameters in your plot restyle(values) { var values = list2dict(values); var div = document.getElementById(values.plotdiv); Plotly.relayout(div, { yaxis: { range: [values.ymin, values.ymax] } }); Plotly.restyle(div, { zmin: values.zmin, zmax: values.zmax, colorscale: values.colormap }); } } /* In this class is defined all the function to SPC plot */ class Pcolor { constructor({ div, data, props }) { this.div = document.getElementById(div); this.n = 0; this.divs = []; this.props = props; this.setup(data); } /* This function is used to plot all the data that have the DB and just is used when is loaded or reloaded*/ setup(data) { console.log(data); for (var i = 0; i < data.spc.length; i++) { var layout = { height: 400, xaxis: { title: 'Velocity', showgrid: false, zeroline: false, domain: [0, 0.7], linecolor: 'rgb(40, 223, 247)', color: 'rgb(40, 223, 247)', size: 24, titlefont: { color: 'white', size: 24 }, }, yaxis: { title: 'km', showgrid: false, linecolor: 'rgb(40, 223, 247)', color: 'rgb(40, 223, 247)', size: 24, titlefont: { color: 'white', size: 24 }, }, xaxis2: { title: 'dB', domain: [0.75, 1], ticks: 'outside', linecolor: 'rgb(40, 223, 247)', color: 'rgb(40, 223, 247)', size: 24, titlefont: { color: 'white', size: 24 }, }, titlefont: { color: 'white', size: 18 }, font:{ color:'rgb(40, 223, 247)' }, paper_bgcolor: 'black', plot_bgcolor: 'white', }; var iDiv = document.createElement('div'); iDiv.id = 'plot-' + i; iDiv.className += iDiv.className ? ' col-md-6' : 'col-md-6'; this.n = this.n + 1; this.div.appendChild(iDiv); this.divs.push(iDiv.id); var trace1 = { z: data.spc[i], x: data.xrange, y: data.yrange, colorscale: this.props.colormap || 'Jet', transpose: true, type: 'heatmap' }; var trace2 = { x: data.rti[i], y: data.yrange, xaxis: 'x2', yaxis: 'y', type: 'scatter', }; if (this.props.zmin) { trace1.zmin = this.props.zmin } if (this.props.zmax) { trace1.zmax = this.props.zmax; layout.xaxis2.range = [this.props.zmin, this.props.zmax] } var t = new Date(data.time * 1000); // This condition is used to change from UTC to LT if (data.localtime == true){ t.setTime( t.getTime() + t.getTimezoneOffset()*60*1000 ); } layout.title = 'Channel ' + i + ': ' + data.noise[i] + 'dB - ' + t.toLocaleString(); var conf = { modeBarButtonsToRemove: ['sendDataToCloud', 'autoScale2d', 'hoverClosestCartesian', 'hoverCompareCartesian', 'lasso2d', 'select2d', 'zoomIn2d', 'zoomOut2d', 'toggleSpikelines'], modeBarButtonsToAdd: [{ name: 'Edit plot', icon: icon, click: function (gd) { var div = gd.id; $('input[id=id_plotdiv]').val(div); $('#setup').modal('show'); } }], displaylogo: false, showTips: true }; Plotly.newPlot('plot-' + i, [trace1, trace2], layout, conf); } } plot(obj) { this.data = obj; // add new data to plots and empty buffers console.log('Plotting...'); var t = new Date(obj.time[0] * 1000); // This condition is used to change from UTC to LT if (obj.localtime == true){ t.setTime( t.getTime() + t.getTimezoneOffset()*60*1000 ); } for (var i = 0; i < this.n; i++) { var div = document.getElementById(this.divs[i]); Plotly.relayout(div, { title: 'Channel ' + i + ': ' + obj.noise[i] + 'dB - ' + t.toLocaleString(), }); Plotly.restyle(div, { z: [obj.spc[i], null], x: [obj.xrange, obj.rti[i]] }, [0, 1]); } } // With this function You can change parameters in your plot restyle(values) { var values = list2dict(values); var div = document.getElementById(values.plotdiv); Plotly.relayout(div, { yaxis: { range: [values.ymin, values.ymax] }, }); /*Plotly.relayout(div, { xaxis: { range: [values.xmin, values.xmax] }, });*/ Plotly.restyle(div, { zmin: values.zmin, zmax: values.zmax, xmin: values.xmin, xmax: values.xmax, colorscale: values.colormap }); } } /* In this class is defined all the function to Scatter(noise) plot */ class Scatter { constructor({ div, data, key, props }) { this.div = document.getElementById(div); this.n = 0; this.key = key; this.wait = false; this.timer = (props.throttle || 30) * 1000; this.lastRan = Date.now(); this.lastFunc = null; this.ybuffer = []; this.xbuffer = []; this.props = props; this.setup(data); } /* This function is used to plot all the data that have the DB and just is used when is loaded or reloaded*/ setup(data) { this.data = data; //le agrego juan carlos para ver la data en mi consola var traces = []; this.last = data.time.slice(-1); if (data.time.length == 1) { var values = { 'time': data.time, 'data': data[this.key] }; } else { var values = this.fill_gaps(data.time, data[this.key], data.interval, data[this.key].length); } var t = values.time.map(function (x) { var a = new Date(x * 1000); // This condition is used to change from UTC to LT if (data.localtime == true){ a.setTime( a.getTime() + a.getTimezoneOffset()*60*1000 ); } return a; }); for (var i = 0; i < data[this.key].length; i++) { this.n = this.n + 1; this.ybuffer.push([]); var trace = { x: t, y: data[this.key][i], mode: 'lines', type: 'scatter', name: 'Channel ' + i, connectgaps:false, }; traces.push(trace); } var title = this.props.title || '' var layout = { // autosize: false, // width: 800, // height: 400, title: title + ' - ' + t.slice(-1).toLocaleString(), font: { size: 18, color: 'white' }, plot_bgcolor: 'black', paper_bgcolor: 'black', xaxis: { title: 'Time', linecolor: 'rgb(40, 223, 247)', color: 'rgb(40, 223, 247)', size: 24, titlefont: { color: 'white', size: 24 }, }, yaxis: { title: this.props.ylabel || 'dB', linecolor: 'rgb(40, 223, 247)', color: 'rgb(40, 223, 247)', size: 24, titlefont: { color: 'white', size: 24 }, }, titlefont: { size: 24, } }; if (this.props.ymin) { layout.yaxis.range = [this.props.ymin, this.props.ymax] } var conf = { modeBarButtonsToRemove: ['sendDataToCloud', 'autoScale2d', 'hoverClosestCartesian', 'hoverCompareCartesian', 'lasso2d', 'select2d', 'zoomIn2d', 'zoomOut2d', 'toggleSpikelines'], modeBarButtonsToAdd: [{ name: 'Edit plot', icon: icon, click: function (gd) { $('#setup').modal('show'); } }], displaylogo: false, showTips: true }; Plotly.newPlot('plot', traces, layout, conf); } getSize() { var t = this.xbuffer.slice(-1)[0]; var n = 0; var timespan = (this.props.timespan || 12) * 1000 * 60 * 60; while ((t - this.div.data[0].x[n]) > timespan) { n += 1; } return n; } fill_gaps(xBuffer, yBuffer, interval, N) { var x = [xBuffer[0]]; var y = []; for (var j = 0; j < N; j++) { y.push([yBuffer[j][0]]); } var last; for (var i = 1; i < xBuffer.length; i++) { var cnt = 0; last = x.slice(-1)[0]; while (Math.abs(parseFloat(xBuffer[i]) - last) > 1.5 * parseFloat(interval)) { cnt += 1; last = last + interval; x.push(last); for (var j = 0; j < N; j++) { y[j].push(null); } // Avoid infinite loop if (cnt == 50) { break; } } x.push(xBuffer[i]); for (var j = 0; j < N; j++) { y[j].push(yBuffer[j][i]); } } return { 'time': x, 'data': y }; } plot() { // add new data to plots and empty buffers var xvalues = []; var yvalues = []; var traces = []; var N = this.getSize(); console.log('Plotting...'); for (var i = 0; i < this.n; i++) { if (N > 0) { this.div.data[i].y = this.div.data[i].y.slice(N, ) this.div.data[i].x = this.div.data[i].x.slice(N, ) } yvalues.push(this.ybuffer[i]); xvalues.push(this.xbuffer); traces.push(i); this.ybuffer[i] = []; } Plotly.extendTraces(this.div, { y: yvalues, x: xvalues }, traces); this.xbuffer = []; } //This function just add the last data and is used if previously was used setup() update(obj) { // fill data gaps var cnt = 0; while (Math.abs(parseFloat(obj.time[0]) - this.last ) > 1.5 * parseFloat(obj.interval)) { cnt += 1; this.last += obj.interval; var newt = new Date((this.last) * 1000); // This condition is used to change from UTC to LT if (obj.localtime == true){ newt.setTime( newt.getTime() + newt.getTimezoneOffset()*60*1000 ); } this.xbuffer.push(newt); for (var i = 0; i < this.n; i++) { this.ybuffer[i].push(null); } // Avoid infinite loop if (cnt == 100) { break; } } // update buffers this.last = parseFloat(obj.time[0]); var t = new Date(obj.time[0] * 1000); // This condition is used to change from UTC to LT if (obj.localtime == true){ t.setTime( t.getTime() + t.getTimezoneOffset()*60*1000 ); } this.xbuffer.push(t); for (var i = 0; i < this.n; i++) { this.ybuffer[i].push(obj[this.key][i][0]); } var title = this.props.title || '' Plotly.relayout(this.div, { title: title + ' - ' + t.toLocaleString(), }); // plot when ready (every 10 secs) if (!this.wait) { this.plot(); this.wait = true; } else { clearTimeout(this.lastFunc) this.lastFunc = setTimeout(function (scope) { if ((Date.now() - scope.lastRan) >= scope.timer) { scope.plot() scope.lastRan = Date.now() } }, this.timer - (Date.now() - this.lastRan), this) } } // With this function You can change parameters in your plot restyle(values) { var values = list2dict(values); Plotly.relayout(this.div, { yaxis: { range: [values.ymin, values.ymax] } }); } }