как изменить скорость потока данных моего графика - PullRequest
0 голосов
/ 11 февраля 2019

Я получил график ЭКГ, который транслируется в браузере в прямом эфире с использованием фляги Python и что я узнал из этого блога.http://theblogofpeterchen.blogspot.com/2015/02/html5-high-performance-real-time.html

Мой график выглядит хорошо и отображается так, как я хочу, но я бы хотел, чтобы пользователь мог изменять частоту сердечных сокращений, чтобы график изменился.Будем весьма благодарны за любые предложения о том, как этого добиться.

Я попытался отрегулировать настройку g.speed, но, похоже, это никак не повлияло на скорость.Я уверен в добавлении контроля пульса в пользовательский интерфейс. Я просто не уверен, как принять пользовательский ввод и заставить график работать быстрее / медленнее в ответ на этот вход, так как параметр g.speed, похоже, не влияетскорость, с которой потоки данных.

liveGraph.js:

   /*
   * Helper function to convert a number to the graph coordinate
   * ----------------------------------------------------------- */
  function convertToGraphCoord(g, num){
      return Math.floor((g.height / 2) * -(num * g.scaleFactor) + 
g.height / 2);
  }

  /*
   * Constructor for the LiveGraph object
   * ----------------------------------------------------------- */
  function LiveGraph(cid, datacb){

var g             =   this;
g.canvas_id       =   cid;
g.canvas          =   $("#" + cid);
g.context         =   g.canvas[0].getContext("2d");
g.width           =   $("#" + cid).width();
g.height          =   $("#" + cid).height();
g.white_out       =   g.width * 0.01;
g.fade_out        =   g.width * 0.10;
g.fade_opacity    =   0.2;
g.current_x       =   0;
g.current_y       =   0;
g.erase_x         =   null;
g.speed           =   2;
g.linewidth       =   1;
g.scaleFactor     =   1;
g.stop_graph      =   true;
g.plethStarted    =   false;
g.plethBuffer     =   new Array();

devicePixelRatio = window.devicePixelRatio || 1,
backingStoreRatio = g.context.webkitBackingStorePixelRatio ||
                    g.context.mozBackingStorePixelRatio ||
                    g.context.msBackingStorePixelRatio ||
                    g.context.oBackingStorePixelRatio ||
                    g.context.backingStorePixelRatio || 1,

ratio = devicePixelRatio / backingStoreRatio;


var oldWidth = g.canvas[0].width;
var oldHeight = g.canvas[0].height;

g.canvas[0].width = oldWidth * ratio;
g.canvas[0].height = oldHeight * ratio;

g.canvas[0].style.width = oldWidth + 'px';
g.canvas[0].style.height = oldHeight + 'px';

// scale the context to counter
// the fact that we've manually scaled
// the canvas element
g.context.scale(ratio, ratio);


/*
 * The call to fill the data buffer using
 * the data callback
 * ---------------------------------------- */
g.fillData = function() {
  g.plethBuffer = datacb();
  };

/*
 * The call to check whether graphing is on
 * ---------------------------------------- */
g.isActive = function() {
  return !g.stop_graph;
};

/*
 * The call to stop the graphing
 * ---------------------------------------- */
g.stop = function() {
  g.stop_graph = true;
};


/*
 * The call to wrap start the graphing
 * ---------------------------------------- */
g.start = function() {
  g.stop_graph = false;
  g.animate();
};


/*
 * The call to start the graphing
 * ---------------------------------------- */
g.animate = function() {
  reqAnimFrame =   window.requestAnimationFrame       ||
                   window.mozRequestAnimationFrame    ||
                   window.webkitRequestAnimationFrame ||
                   window.msRequestAnimationFrame     ||
                   window.oRequestAnimationFrame;

  // Recursive call to do animation frames
  if (!g.stop_graph) reqAnimFrame(g.animate);

  // fill in data into the buffer so we know what to draw
  g.fillData();

  // Draw the frame (with the supplied data buffer)
  g.draw();
};


g.draw = function() {
  // Circle back the draw point back to zero when needed (ring drawing)
  g.current_x = (g.current_x > g.width) ? 0 : g.current_x;

  // "White out" a region before the draw point
  for( i = 0; i < g.white_out ; i++){
    g.erase_x = (g.current_x + i) % g.width;
    g.context.clearRect(g.erase_x, 0, 1, g.height);
  }

  // "Fade out" a region before the white out region
  for( i = g.white_out ; i < g.fade_out ; i++ ){
    g.erase_x = (g.current_x + i) % g.width;
    g.context.fillStyle="rgba(255, 255, 255, " + g.fade_opacity.toString() + ")";
    g.context.fillRect(g.erase_x, 0, 1, g.height);
  }

  // If this is first time, draw the first y point depending on the buffer
  if (!g.started) {
    g.current_y = convertToGraphCoord(g, g.plethBuffer[0]);
    g.started = true;
  }

  // Start the drawing
  g.context.beginPath();

  // first move to the current x and y position (last point)
  g.context.moveTo(g.current_x, g.current_y);

  for (i = 0; i < g.plethBuffer.length; i++) {
    // Put the new y point in from the buffer
    g.current_y = convertToGraphCoord(g, g.plethBuffer[i]);

    // Draw the line to the new x and y point
    g.context.lineTo(g.current_x += g.speed, g.current_y);

    // Set the 
    g.context.lineWidth   = g.linewidth;
    g.context.lineJoin    = "round";

    // Create stroke
    g.context.stroke();
  }

  // Stop the drawing
  g.context.closePath();
};
 }

  var lastData =0;

  // Create a random function that is dependent on the last value
  function hysteresisRandom(){
    lastData += (Math.floor((Math.random() * 5) + 1)-3)/50;
    if (Math.abs(lastData) >= 1) lastData = (lastData > 0) ? 1 : -1;
    return lastData;
  }

  // Generate a real time data grab of various length
  function generateData(){
    buffer = new Array();
    var inputLength = Math.floor((Math.random() * 1) + 1);;
    for( i = 0 ; i < inputLength ; i++ ) buffer[i] = hysteresisRandom();
    return buffer;
  }

ecg.js:

/*45 data points*/
var ECG_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
            0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
            0.08, 0.18, 0.08, 0, 0, 0, 0, 0, 0, -0.04, 
            -0.08, 0.3, 0.7, 0.3, -0.17, 0.00, 0.04, 0.04, 
            0.05, 0.05, 0.06, 0.07, 0.08, 0.10, 0.11, 0.11, 
            0.10, 0.085, 0.06, 0.04, 0.03, 0.01, 0.01, 0.01, 
            0.01, 0.02, 0.03, 0.05, 0.05, 0.05, 0.03, 0.02, 0, 0, 0];

var ECG_idx = 0;

function get_ECG_data(){
  if (ECG_idx++ >= ECG_data.length - 1) ECG_idx=0;
  var output = new Array();
  output[0] = ECG_data[ECG_idx] + hysteresisRandom()/10;
  return output;
}
var ecg;



$(document).ready(function(){
    ecg = new LiveGraph("ecg", get_ECG_data);
    ecg.speed = 1.4; 
    ecg.scaleFactor = 0.8;
    ecg.start();

});

index.html:

<!DOCTYPE html>
<html lang="en">
    <head>
    <meta charset="utf-8" />
    <meta http-equiv="x-ua-compatible" content="ie=edge">
    <title>{{ title }}</title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="/static/normalize.css">
    <link rel="stylesheet" href="/static/main.css">

    <script type="text/javascript" src="{{ url_for('static', filename='smoothie.js') }}"></script>

    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
    <script type="text/javascript" src="{{ url_for('static', filename='modernizr-3.6.0.min.js') }}"></script>

</head>
<body>
    <script type="text/javascript" src="{{ url_for('static', filename='jquery-3.3.1.min.js') }}"></script>
      <div class="hidden-on-main-page">

    <script type="text/javascript" src="{{ url_for('static', filename='liveGraph.js') }}"></script>

    <h1>{{ title }}!</h1>
    <h2> The date and time on the server is: {{ time }}</h2>
    <h2> GPIO mode status: {{ gpio_mode }}</h2>
    <h2> Last Command sent: {{ last_cmd }}</h3>
    <br>
    <h2> Commands </h2>
    <h3>
        Lung Rate Control:
        <h4>
        <a href="/lung_rate_apnea" class="button"> APNEA</a>
        <a href="/lung_rate_5" class="button"> RR=5</a>
        <a href="/lung_rate_30" class="button"> RR=30</a>
        </h4>
    </h3>
    <h3>
        Pupil Control:
        <h4>
        <a href="/pupil_r_constricted" class="button"> constricted</a>
        <a href="/pupil_r_normal" class="button"> normal</a>
        <a href="/pupil_r_dilated" class="button"> dilated</a>
        </h4>
    </h3>

    <div class="container" id="content">
        <div class="row">
            <p>ECG</p>
            <div id="log">
            </div> <!-- /#log -->
        </div>
    </div>
    <div class="wrapper">
      <h1>ECG</h1>

    <div style="width: 100%;">
    <center>
    <canvas id="ecg" width="1200"  height="200" style="border: 1px solid #cccccc; border-radius: 5px; cursor: pointer;"></canvas>
    <script type="text/javascript" src="{{ url_for('static', filename='ecg.js') }}"></script>
    </center>
    </div>
</body>

Мне бы хотелось, чтобы график ЭКГ можно было регулировать, чтобы клиент мог регулировать частоту сердечных сокращений.

ОБНОВЛЕНИЕ: 13/02/2019:

Я нашелспособ (вероятно, не очень хороший), но, тем не менее, способ изменить частоту сердечных сокращений путем изменения числа нулей в начале массива ECG_data.увеличение числа нулей приведет к замедлению сердечного ритма, а уменьшение числа нулей - к ускорению сердечного ритма.Проблема сейчас в моей неопытности с javascript.Я могу жестко закодировать нули, чтобы увидеть результаты, но я не могу заставить его работать, когда добавляю некоторые функции в javascript, которые в основном используют array.splice () и array.push () для контроля количества нулей.Я использую .push (), потому что мне было проще работать со всеми нулями в конце массива, а не в начале, как показано в моем примере.Может кто-нибудь помочь мне с рабочим примером того, как заставить это работать, или с лучшей идеей, если таковая имеется?

...