物理の駅 Physics station by 現役研究者

テクノロジーは共有されてこそ栄える

Python+matplotlib で 2つの軸を左右・両方左に描画する

物理では、例えば、β と Energy [MeV/u] のように、同じ量だが異なる表記をすることがある。 これを1つのグラフに同時に表示したいとき、以下のようにする。

import numpy as np
import matplotlib.pyplot as plt

Zs = np.arange(1, 100, 1)
data1 = 0.5+Zs*0.002

mnucleon=931.49432  # MeV

def Energy2Beta(E):
    KE=E
    M=mnucleon
    P=((M+KE)**2-M**2)**0.5
    gamma2 = (1+(P/mnucleon)**2)
    beta = (1-(1/gamma2))**0.5
    return beta

plt.rcParams['figure.figsize'] = [6, 5]
plt.rcParams['figure.dpi'] = 72
plt.rcParams["font.size"] = 14

fig, ax1 = plt.subplots()

color = 'tab:red'
ax1.set_xlabel('Atomic number Z')
ax1.set_ylabel('Beta', color=color)
ax1.plot(Zs, data1, color='black')
ax1.tick_params(axis='y', labelcolor=color)
ax1.set_yticks(np.arange(0.5,0.72,0.025))
ax1.set_ylim(0.5,0.7)

ax2 = ax1.twinx()  # 同じX軸を共有する2番めの軸のインスタンスを作成

color = 'tab:blue'
ax2.set_ylabel('Energy [MeV/u]', color=color)  # xlabelはax1で作成済み
# ax2.plot(Zs, data1, color='tab:orange') # デバッグ用 コメントを外すと、ax1と同じデータを描画される
ax2.tick_params(axis='y', labelcolor=color)
ene_ticks = np.arange(150, 400, 25)
beta_ticks = Energy2Beta(ene_ticks)
ax2.set_yticks(beta_ticks,[str(ene) for ene in ene_ticks]) #文字列として描画するのがポイント

# ax2.spines['right'].set_visible(False) #右側の軸は表示させない
# ax2.spines['left'].set_position(('axes', -0.3)) # 左側の軸を軸の相対位置 -0.2の位置に表示
# ax2.yaxis.set_label_position('left') # labelの位置は左側
# ax2.yaxis.set_ticks_position('left') # ticksの位置は左側

ax2.set_ylim(0.5,0.7)

fig.tight_layout()  # 右側のY軸がはみ出した時に全部を表示させるオプション
plt.show()

2つの軸を左右に表示させる場合

途中のコメントアウトした4行をアンコメント (行頭の#を外す)と、2つの軸を左に表示させることができる。

ax2.spines['right'].set_visible(False) #右側の軸は表示させない
ax2.spines['left'].set_position(('axes', -0.3)) # 左側の軸を軸の相対位置 -0.2の位置に表示
ax2.yaxis.set_label_position('left') # labelの位置は左側
ax2.yaxis.set_ticks_position('left') # ticksの位置は左側

Python: jsonをdumpsするときの浮動小数点の桁数を制御する

dumpsで桁数を制御することはできないが、loadsで制御することが可能。速度は遅くなるが、dumps→loads→dumps にすると良い。

import json

print(json.dumps([23.67, 23.97, 23.87]))
print(json.dumps([23.67000000000002, 23.96999999999999, 23.87000000000001]))
print(json.dumps(json.loads(json.dumps([23.67000000000002, 23.96999999999999, 23.87000000000001]), parse_float=lambda x: round(float(x), 3)))) #3桁まで
print(json.dumps(json.loads(json.dumps([23.67000000000002, 23.96999999999999, 23.87000000000001]), parse_float=lambda x: round(float(x), 14)))) #14桁まで

出力

[23.67, 23.97, 23.87]
[23.67000000000002, 23.96999999999999, 23.87000000000001]
[23.67, 23.97, 23.87]
[23.67000000000002, 23.96999999999999, 23.87000000000001]

参照

stackoverflow.com

Python Jupyter Lab で RuntimeError: Cannot enter into task <1> while another task <2> を解消する

Jupyter Lab

で以下のようなエラーが出た。tornado がエラーだとか。

Exception in callback <TaskWakeupMethWrapper object at 0x000002767EB13B80>(<Future finis...a24"\r\n\r\n'>)
handle: <Handle <TaskWakeupMethWrapper object at 0x000002767EB13B80>(<Future finis...a24"\r\n\r\n'>)>
Traceback (most recent call last):
  File "c:\users\masahiro\appdata\local\programs\python\python38\lib\asyncio\events.py", line 81, in _run
    self._context.run(self._callback, *self._args)

RuntimeError: 
Cannot enter into task <1> while another task <2>
1: <Task pending name='Task-1' coro=<HTTP1ServerConnection._server_request_loop() running at c:\users\masahiro\appdata\local\programs\python\python38\lib\site-packages\tornado\http1connection.py:825> wait_for=<Future finished result=b'GET /api/ke...2a24"\r\n\r\n'> cb=[IOLoop.add_future.<locals>.<lambda>() at c:\users\masahiro\appdata\local\programs\python\python38\lib\site-packages\tornado\ioloop.py:687]> 
2: <Task pending name='Task-3629' coro=<PeriodicCallback._run() running at c:\users\masahiro\appdata\local\programs\python\python38\lib\site-packages\tornado\ioloop.py:921>

cb=[IOLoop.add_future.<locals>.<lambda>() at c:\users\masahiro\appdata\local\programs\python\python38\lib\site-packages\tornado\ioloop.py:694]> is being executed.

エラーは見やすくするため一部改変している。

github.com

によると、tornado のバージョンを 6.2から6.1に落とせばfixできるとのことなので、開いていたJupyter labを一旦全部閉じて、

pip install tornado==6.1

とした。すると、エラーは出なくなった。

このエラーがでたときのJupyterのバージョン

>jupyter --version
Selected Jupyter core packages...
IPython          : 8.4.0
ipykernel        : 6.15.1
ipywidgets       : 7.7.1
jupyter_client   : 7.3.4
jupyter_core     : 4.11.1
jupyter_server   : 1.18.1
jupyterlab       : 3.4.5
nbclient         : 0.6.6
nbconvert        : 6.5.3
nbformat         : 5.4.0
notebook         : 6.4.12
qtconsole        : 5.3.1
traitlets        : 5.3.0

Windows cipher /w でディスクの空き容量を完全に消去する

HDDのデータを完全に消去したいとき、いくつかの方法があるが、Windows上で比較的安全に容易に行えるのが cipher /w というコマンドである。公式のドキュメントに

docs.microsoft.com

ボリューム全体で使用可能な未使用のディスク領域からデータを削除します。 /w パラメーターを使用する場合、他のすべてのパラメーターが無視されます。 指定したディレクトリは、ローカル ボリューム内の任意の場所に存在できます。 マウント ポイントである場合、または別のボリューム内のディレクトリを指している場合、そのボリューム上のデータは削除されます。

とあるように、未使用の領域からデータを削除するので、使用中の領域からはデータを削除できないことに注意しよう。一部のサイトではNTFSシステムにしか使えないと言った記述があるが、このコマンドは、そのディスクで作成可能な最大ファイルを作成するものなので、巨大ファイルを作成できるファイルシステムであれば(例 exFAT等)動く。空き容量に書き込むので、既存のデータを削除することはない。

Eドライブの空き容量を消去するときは

cipher /w:e:

とする。

C:\Users\Masahiro>cipher /w:e:
できるだけ多くのデータを削除するために、CIPHER /W の実行中
はほかのアプリケーションをすべて終了してください。
0x00 に書き込み中
...

相当時間がかかるので気長に待つ。

まp.Cドライブ(システム用パーティション)に対しても cipher /w:c: で実行できるが、空き容量が限りなく0になってシステムが不安定になるので実行中はPCでの操作は控えよう。

Google Chromeで起動時のプロファイル(ユーザー)を固定する

Google Chromeは、複数のプロファイルを使い分けることができる。つまり、ユーザーごとにブラウザを分けられて、それぞれのブラウザは各ユーザーがログイン済みの状態になる。しかし、普通にGoogle Chromeを開くと、最後に閉じたユーザーのブラウザが開いてしまう。

常に、あるユーザーのブラウザを最初に開きたいときは、プロパティ→リンク先を編集する。

通常は、 "C:\Program Files\Google\Chrome\Application\chrome.exe"

となっているところを、 "C:\Program Files\Google\Chrome\Application\chrome.exe" --profile-directory="Default"

と変える。profile-directoryDefaultは、最初に開きたいユーザーのブラウザ上でchrome://version/

とすると、

プロフィール パス
C:\Users\Masahiro\AppData\Local\Google\Chrome\User Data\Default (←ココ)

に書いてある。Profile 1であれば

"C:\Program Files\Google\Chrome\Application\chrome.exe" --profile-directory="Profile 1"

とする。