🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
Chart.js

Chart.jsは、多様なグラフを組み込めるJavaScriptのライブラリ。折れ線グラフや棒グラフ、円グラフ、レーダーチャートなどのグラフの種類が用意されています。HTML5のCanvasを用いて描画され、マークアップも分かりやすく、簡単に編集することが可能です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

1回答

3909閲覧

epochを使って散布図のリアルタイムチャートをブラウザ表示したい

Uka

総合スコア28

Chart.js

Chart.jsは、多様なグラフを組み込めるJavaScriptのライブラリ。折れ線グラフや棒グラフ、円グラフ、レーダーチャートなどのグラフの種類が用意されています。HTML5のCanvasを用いて描画され、マークアップも分かりやすく、簡単に編集することが可能です。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2021/01/28 15:12

前提・実現したいこと

下記のサイトを参考に、ラズパイでセンシングしたデータを、ブラウザ上にリアルタイム表示したいと考えています。サイトにあるように、時系列での折れ線チャートの表示はできたのですが、original.py中の{x:y0, y:y1}に対応した散布図の表示がうまくできません。アドバイスいただけますとありがたいです。よろしくお願いいたします。
参考サイト:https://qiita.com/shiro-kuma/items/0607e01a19e093fdb631

発生している問題・エラーメッセージ

散布図表示させるため、index5_1_.htmlの中で、以下のようにコードを修正しブラウザ表示を確認しましたが、原点に1点表示されただけで、その後データは更新されませんでした。その際、軸の目盛り表示や、テーブル表示もされませんでした。

var data = [ { label: "Series 1", values: [{x:obj.y0, y:obj.y1}] }, ]; var data1 = [{x:obj.y0, y:obj.y1}] var lineChart = $('#graph').epoch({ type: 'scatter', data: data, axes: ['left', 'right', 'bottom'] }); lineChart.push(data1);

該当のソースコード(original.py)

import os import json import datetime import random import time from gevent import pywsgi from geventwebsocket.handler import WebSocketHandler from flask import Flask, request, render_template import spidev spi=spidev.SpiDev() spi.open(0,0) spi.max_speed_hz=1000000 a1 = [] data1 = {} def analog_read(channel): r=spi.xfer2([6+((channel&4)>>2),(channel&3)<<6,0]) adc_out=((r[1]&15)<<8)+r[2] return adc_out app = Flask(__name__) @app.route('/') def index(): return render_template('index5_1.html') @app.route('/publish') def publish(): if request.environ.get('wsgi.websocket'): ws = request.environ['wsgi.websocket'] for t in range(0,2): data1[t] = ws.receive() a1.append(data1[t]) print(a1[0]) print(a1[1]) while True: t = int(time.mktime(datetime.datetime.now().timetuple())) data=analog_read(0)        data1=analog_read(1) datas={"time": t, "y0": data*float(a1[0]), "y1": data*float(a1[1])} ws.send(json.dumps(datas)) time.sleep(1) return if __name__ == '__main__': app.debug = True server = pywsgi.WSGIServer(('localhost', 5000), app, handler_class=WebSocketHandler) server.serve_forever()

該当のソースコード(index5_1.html)

<html> <head> <title>graph test</title> <script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script> <script type="text/javascript" src="http://code.jquery.com/jquery-1.4.2.min.js"></script> <script type="text/javascript" src="Chart.min.js"></script> <script type="text/javascript" src="moment.js"></script> <script type="text/javascript" src="Chart.bundle.js"></script> <script type="text/javascript" src="chartjs-plugin-streaming.js"></script> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script type="text/javascript" src="{{ url_for('static', filename='js/epoch.min.js') }}"></script> <link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='css/epoch.min.css') }}"> </head> <style> /* Data Table Styling */ #dataTable { font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; border-collapse: collapse; width: 100%; } #dataTable td, #dataTable th { border: 1px solid #ddd; padding: 5px; } #dataTable tr:nth-child(even){background-color: #f2f2f2;} #dataTable tr:hover {background-color: #ddd;} #dataTable th { padding-top: 6px; padding-bottom: 6px; text-align: left; background-color: #4CAF50; color: white; } </style> <body> <h1>Send:</h1> <form method='POST' action='#'> <input type="text" name='data1' id="Text1" class="textBox"> <input type="text" name='data2' id="Text2" class="textBox"> <div><input type='submit'></div> </form> <h1>Receive:</h1> <div id="log"></div> <h1>Real time chart</h1> <div id="graph" class="epoch" style="height: 200px;"></div> <table id="dataTable"> <tr><th>Local_time</th><th>original value(x1)</th><th>calculation value(x10)</th></tr> </table> <script type="text/javascript"> $(document).ready(function(){ $('form').submit(function(event){ var inputText=$(".textBox").map(function(index,el){ ws.send($(this).val()) console.log($(this).val()) return false; }); }); }); var ws = new WebSocket("ws://localhost:5000/publish"); ws.onmessage = function(msg) { var obj = JSON.parse(msg.data); console.log(obj.time,obj.y0,obj.y1); var data = [ { label: "Series 1", values: [{x:obj.time, y:obj.y0}] }, { label: "Series 2", values: [{x:obj.time, y:obj.y1}] }, ]; var data1 = [{x:obj.time, y:obj.y0}, {x:obj.time, y:obj.y1}] var lineChart = $('#graph').epoch({ type: 'time.line', data: data, axes: ['left', 'right', 'bottom'] }); lineChart.push(data1); var table = document.getElementById("dataTable"); var row = table.insertRow(1); //Add after headings var cell1 = row.insertCell(0); var cell2 = row.insertCell(1); var cell3 = row.insertCell(2); cell1.innerHTML = obj.time; cell2.innerHTML = obj.y0; cell3.innerHTML = obj.y1; }; </script> </body> </html>

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

「epochを使って散布図のリアルタイムチャートをブラウザ表示したい」とのことですが、
Epochの公式ページを見れば一目瞭然の通り、
Epochでリアルタイムチャートに対応しているのは、Area、Bar、Gauge、Heatmap、Lineだけであり、
Scatter(いわゆる散布図)は対応していません。

仮にEpochのScatterがリアルタイム更新に対応としていたとしても、ご質問中のコードは、websocketでデータを受け取るたびにEpochのチャートオブジェクト自体を更新しているようなので、かなり重いものになるのかなと思いました。

(あとtimeがX軸、データがY軸のScatterというのがどういうものなのか想像しづらいです)

なお手元で、Chart.jsを使っての散布図リアルタイム更新は普通に作れました。

Chart.jsによるサンプル

コメント欄でChart.jsでの例が欲しいとのことだったので、最低限のコードを示します。
センシングデータがどのような形式であるのか、質問文では全く示されていないため、
下記ではダミーデータを作成し表示しています。
実際はセンシングデータの出力形式に合わせてflask側、html側を変える必要があります。

アニメーションのオン・オフやグラフ枠の固定などは調べれば出てきますので自力でやってください。
補足:実際の手元verではChart.bundle.jsはCDNをリンクしています。

original.py

python

1import json 2import random 3import time 4from gevent import pywsgi 5from geventwebsocket.handler import WebSocketHandler 6from flask import Flask, request, render_template 7 8app = Flask(__name__) 9 10@app.route('/') 11def index(): 12 return render_template('index.html') 13 14@app.route('/publish') 15def publish(): 16 if request.environ.get('wsgi.websocket'): 17 ws = request.environ['wsgi.websocket'] 18 while True: 19 ''' 20 ダミーのサンプルデータ。 21 Chart.jsに渡す場合は、 22 [ 23 [{x: 10, y: 15}, {x: 8, y: 20}, {...},...], 24 [{x: **, y: **}, {x: , y: }, {...},...], 25 [{x: **, y: **}, {x: , y: }, {...},...], 26 ... 27 ] 28 という形をjson.dumpsして渡す。各行がグループとなる。 29 ''' 30 ws.send(json.dumps( 31 [[{"x": random.random()*10, "y": random.random()*10} for _ in range(10)]for _ in range(3)])) 32 33 time.sleep(1) 34 return 35 36if __name__ == '__main__': 37 app.debug = True 38 server = pywsgi.WSGIServer(('localhost', 8080), app, handler_class=WebSocketHandler) 39 server.serve_forever()

 
index.html

<html> <head> <title>graph test</title> </head> <body> <h1>Real time chart</h1> <canvas id="graph" style="height: 200px;"></canvas> <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script> <script type="text/javascript" src="Chart.bundle.js"></script> <script type="text/javascript"> var ws = new WebSocket("ws://localhost:8080/publish"); // 初期データ var data = [[], [], []]; var ctx = document.getElementById('graph').getContext('2d'); var myChart = new Chart(ctx, { type: 'line', data: { datasets: [ { label: "Group 1", data: data[0], pointRadius: 5, pointBorderRadius: 5, borderColor: '#F00', showLine: false }, { label: "Group 2", data: data[1], pointRadius: 5, pointBorderRadius: 5, borderColor: '#0F0', showLine: false }, { label: "Group 3", data: data[2], pointRadius: 5, pointBorderRadius: 5, borderColor: '#00F', showLine: false } ] }, options: { responsive: true, scales: { xAxes: [{ type: 'linear', position: 'bottom' }] }, legend: { position: 'bottom', lineWidth: 0, labels: { fontSize: 12, boxWidth: 12, usePointStyle: true, generateLabels: function (chart) { return chart.data.datasets.map(function (dataset, i) { return { text: dataset.label, fillStyle: dataset.backgroundColor, hidden: !chart.isDatasetVisible(i), lineCap: dataset.borderCapStyle, strokeStyle: dataset.borderColor, pointStyle: dataset.pointStyle, datasetIndex: i }; }) } } }, } }); //websocket経由で受け取ったデータをparseしてChart.jsのデータに渡す ws.onmessage = function (msg) { myChart.data.datasets.forEach(function (dataset, index) { dataset.data = JSON.parse(msg.data)[index]; }); myChart.update(); }; </script> </body> </html>

投稿2021/01/29 04:43

編集2021/01/29 16:31
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Uka

2021/01/29 15:47 編集

qnoirさん ご回答いただきありがとうございます。公式ページ確認しました。Basic chartのほうにscatterがあったのでできるのではないかと思ったのですが、Real-timeチャートはそもそも時系列データが前提なんですね。こちらのほうでも、EpochでなくChart.jsを使ったリアルタイム散布図のコードにかきかえて試してみたのですが、うまく表示されません。もしよろしければ、chart.jsでの散布図作図方法についてご教示いただくことはできないでしょうか?よろしくお願いいたします。
退会済みユーザー

退会済みユーザー

2021/01/29 16:31

追記しました。
Uka

2021/01/30 16:20

Chart.jsでのサンプルコードをご教示いただきありがとうございます。大変参考になります。いただいたコードをセンシングデータ用に変更して試しているもののプロットできるまでにはまだ至っていませんが、ひとつひとつ確認していきたいと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問