【Pyscript入門】データ入力してグラフを描画する方法【Matplotlib】

この記事は約13分で読めます。

Pyscriptをいろいろ実験したまとめです。
Matplotlibで使うデータを入力できるようなサンプルを作りました。
XとYとグラフタイプを入力できるようにしています。

完成品 Matplotlibにデータ入力

Pyscriptを使用するときはhtmlファイルのheadタグの中に以下2行追加だけで使えます。

<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>

<py-script>と<script>は違う

<py-script>と<script>で同じように使えるものと使えないものがある。
varやconstなどは<py-script>では使えない。
pythonでは型の定義がないからだと思います。
何が使えるかは最初<script>で作って動かし
<py-script>に変更すると使えないものは使えなくなるので判断できます。

Elementオブジェクトについて違いが分かるサンプルを用意しました。

<b>タグは囲まれたテキストが太字になります。
太文字 これを実行すると以下のようになります。

赤文字は<script>内でdocument.getElementByIdを使用したもの。
緑色は<py-script>内でdocument.getElementByIdを使用したもの。
青色は<py-script>内でdocument.getElementByIdではなくElementを使用したものになります。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8" />
  <title>太文字</title>
  <link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
  <script defer src="https://pyscript.net/alpha/pyscript.js"></script>
</head>

<body>
  <p id="p1"></p>
  <p id="p2"></p>
  <p id="p3"></p> 
  
<script>
	const p1 = document.getElementById('p1')
	p1.innerHTML = '<b>scriptの場合:太文字です</b>'
  p1.style.color='red'
</script>

<py-script>
  p2 = document.getElementById('p2')
  p2.innerHTML = '<b>py-scriptの場合:太文字になりません</b>'
  p2.style.color='green'
  p3 = Element('p3')
  p3.element.innerText = '<b>Elementの場合:太文字になりません</b>'
  p3.element.style.color='blue'
</py-script>

</body>
</html>

<script>は型定義(const)が必要<py-script>は不要
<script>はinnerHTMLでタグを変更できる。<py-script>はinnerHTMLでテキストのみの変更になる。
<py-script>ではdocument.getElementByIdのかわりにElementが使える。(公式のサンプルを見るとElementが使われている。)
Elementを取得した場合は.elementを付ける。

<script>で以下のようにElementにしてみたが反応がなかった。
const p1 = Element('p1');

JavaScriptでは文末に;を書くが<script>内でも;なくても大丈夫だった。

いろいろ書きましたがpy-scriptに関して情報が少ないので
紹介したように、まず<script>で作って<py-script>にしてみるのも手です。

今回の値を入力する部分

plotとbarはボタンを押したときの関数で区別しています。
<button id ="plot" class="btn" pys-onClick="setPlot">plot</button> 
<button id="bar" class="btn" pys-onClick="setBar">bar</button>

値の取得は各関数内で
<label>X: 
    <input type="text" class='textlines' value="" id="xvalue" name="xvalue"> </label>
  x_element = Element("xvalue")  id="xvalue"の要素を取得してx_elementに代入。
  x0 = x_element.element.value  x_elementのvalue(値)をx0に代入
x0は文字列ですので数字とリストに変換する処理を後でしています。
以下のように関数の外で定義した変数はJupiterNotebookなどと違い
ボタンを押すたびに毎回実行されるようなので注意が必要です。
変数の中に値を保持しておくことはできないようです。
入力欄のほうには残るので毎回読み込むようにしてます。
<py-script>
import matplotlib.pyplot as plt
mode="plot"
x=[]
y=[]

aタグやimgを動的に変更したものもできます。完成品
目次へ

CSS

<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" /><py-script>を読み込んでいるので
Pyscript DEMOのソースから対象要素のclass名をコピーすれば、スタイルが真似できます。
今回はToDoリストのtodo.htmlから<main class="max-w-xs mx-auto mt-4">をコピーして全体のスタイルを真似しています。
逆に読み込んだcssの影響でh1タグとかは文字を大きくしたかったのですが思うようにスタイルを変更できませんでした。
大きく表示したい場合はclass="max-w-xs mx-auto mt-4"を削除すればCSSが外れて大きく表示します。

コード

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="description" content="Pyscriptを使ってMatplotlibで使うデータを入力できるアプリです。
XとYとグラフタイプを入力できるようにしています。詳細はhttps://kikuichige.com/https://kikuichige.com/11693/"/>
<meta name="viewport" content="width=device-width,initial-scale=1" />
  <title>Pyscript+Matplotlib</title>

<script defer src="https://pyscript.net/alpha/pyscript.js"></script>
<py-env>
  - matplotlib
</py-env>
<style type="text/css">
@media screen and (max-width: 960px) {
	/* 960px以下適用されるCSS(PC以外用) */
<link rel="stylesheet" href="https://pyscript.net/alpha/pyscript.css" />
}
body {margin: 0;padding: 0;}
#outer {padding: 0;border-top: 2px solid #7a9f37;
line-height: 1.6;font-family: 'メイリオ', 'Hiragino Kaku Gothic Pro', Meiryo, 'ヒラギノ角ゴ Pro W3', 'MS PGothic', 'MS UI Gothic', Helvetica, Arial, sans-serif;font-size: 93.75%;}
#header {padding: 0;border-bottom:1px #ccc solid;}
#content {background-color:#f8f9fa;}
main {display:block;}
#main {background-color: #fff;margin: 0 auto;width: 800px;padding: 0;}
#inner {padding: 16px 30px 10px 30px;display:block;}
p {margin: 1em 0;word-wrap:break-word;}
#logo {font-size: 16px;	padding: 22px 0 22px 0;margin: 0 auto;width: 740px;}
#logo a {font-weight: bold;	color: #8c0000;	text-decoration: none;padding-left:10px;}
#logo a:hover {text-decoration: underline;}
h1 {font-size: 26px;padding: 0;margin:0;}
h2, h3 {font-size: 24px;padding: 0;border-bottom: 1px solid #ccc;}



<!--追加bigin-->
h1{
  font-size: 26px;padding: 0;margin:0;
  color: #ff0000;
  background-color: #ffffff;
}

.btn{
  color: #fff;
  background-color: #eb6100;
  width: 100px;
  height: 30px;
}
.textlines {
    border: 2px solid #0a0; 
}

<!--追加end-->



h1,p,a{overflow-wrap: break-word;}
.border{
outline:solid 2px blue;
height:30px;
}
@media screen and (min-width: 960px) {
	/* 960px以上に適用されるCSS(PC用) */
.max-w-xs mx-auto mt-4 {width:100%;padding: 0;}


}
</style>
</head>

<body>
<main class="max-w-xs mx-auto mt-4">


<div id="outer">
 <header id="header">
	<div id="logo">イチゲブログ2</div>
 </header>
 <div id="content">
  
  <div id="inner">
	<h1>Matplotlibアプリ</h1>
    <br>
<p>このサイトの詳細は<a href="https://kikuichige.com">イチゲブログ</a></p>
    <p>XとYにそれぞれカンマ(,)区切りでデータを入力→グラフタイプplotまたはbarを押せば表示します。</p><br>
  <div>
    <label>X: 
    <input type="text" class='textlines' value="" id="xvalue" name="xvalue"> </label>
    <p>  例1,2,3,4,5,6,7</p>
  </div>
      <br>
  <div>
    <label>Y: 
    <input type="text" class='textlines' value="" id="yvalue" name="yvalue"></label>
    <p>  例10,20,30,40,50,60,70</p>
  </div>
    <br>

<div>
  <button id ="plot" class="btn" pys-onClick="setPlot">plot</button>
  <button id="bar" class="btn" pys-onClick="setBar">bar</button>
</div>

  <div id="mes"></div>
  <div id="plotfig"></div>


</div> 
</div>
</div>
</main>

<py-script>
import matplotlib.pyplot as plt
mode="plot"
x=[]
y=[]
def setPlot(*ags,**kws):
  mode="plot"
  plotfunc(mode)

def setBar(*ags,**kws):
  mode="bar"
  plotfunc(mode)
 
def plotfunc(mode0):
  mode=mode0
  x_element = Element("xvalue")
  y_element = Element("yvalue")
  x0 = x_element.element.value
  y0 = y_element.element.value
  if x0=='' or y0=='':
    mes='値を入力してください'
  else:
    x1=x0.split(',')
    x=[int(s) for s in x1]
    y1=y0.split(',')
    y=[int(s) for s in y1]
    if len(x)==len(y):
      fig, ax = plt.subplots()
      if mode=='plot':
        ax.plot(x,y)
      else:
        ax.bar(x,y)
      plt.title("X-Y var")
      plt.xlabel("X")
      plt.ylabel("Y")
      mes=''
      pyscript.write('plotfig',fig)
    else:
      mes='xとyの個数がちがいます'
    
  pyscript.write("mes",mes)

</py-script>

</body>
</html>

目次へ

このブログを書いてるイチゲをOFUSEで応援する

MENTAやってます(ichige)

コメント

タイトルとURLをコピーしました