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

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

OpenCV Pythonで画像の切り抜き (トリミング)

OpenCVでいうところのRectをやるには、配列の一部をスライスすればよい。

dst1 はY=164からHeight=2960、X=356からWidth=2028ピクセル分。XとYが逆になってることに注意。

import cv2
import glob
files = glob.glob("*.jpg")
i=0
for file in files:
    im = cv2.imread(file,0)
    dst1 = im[164:164+2960,356:356+2028]
    dst2 = im[164:164+2960,2692:2692+2028]

    cv2.imwrite(f'a/{i:02d}.jpg',dst1)
    i+=1
    cv2.imwrite(f'a/{i:02d}.jpg',dst2)
    i+=1

トリミング前にどこがトリミングされるか確認するためのコード

import cv2
import glob
files = glob.glob(r"*.jpg")
i=0
s1 = [821,100]
s2 = [2484,100]
width = 1700
height = int(width*2**0.5)
for file in files:
    im = cv2.imread(file,0)
    s=s1
    cv2.rectangle(im, (s[0], s[1]), (s[0]+width, s[1]+height), 120)
    s=s2
    cv2.rectangle(im, (s[0], s[1]), (s[0]+width, s[1]+height), 120)
    cv2.imwrite(file+"_rect.jpg",im)

WSL用のFedora RemixでROOT PyROOT などを使う

WSL用のFedora Remixを購入しインストールする

Fedora Remix for WSL を購入 - Microsoft Store ja-JP

f:id:onsanai:20210506211715p:plain

$ sudo yum install root
$ sudo yum install root python3-root root-notebook

これで終わり。

WSLのデフォルトをFedora Remixにする

wsl --set-default fedoraremix
$ root
   ------------------------------------------------------------------
  | Welcome to ROOT 6.22/08                        https://root.cern |
  | (c) 1995-2020, The ROOT Team; conception: R. Brun, F. Rademakers |
  | Built for linuxx8664gcc on Mar 10 2021, 14:20:04                 |
  | From tags/v6-22-08@v6-22-08                                      |
  | Try '.help', '.demo', '.license', '.credits', '.quit'/'.q'       |
   ------------------------------------------------------------------

PyROOTをnotebookで使う

$ root --notebook --no-browser

PyROOTでROOTファイルを読む TFileとRDataFrameの比較

PyROOTでROOTファイルを扱うには、ROOTの作法に従うか、Numpyで頑張るかの2択となる。

ROOTの作法に従った例

ROOTファイルに、イベントごとに色んなパラメータが固定長で格納されているものとする。データ名 ADC の[0]に格納されているデータをヒストグラムで表示する。

import ROOT
file = ROOT.TFile.Open("filename.root")
tree = file.Get('tree')
c1 = ROOT.TCanvas("c1","c1",800,500)
h1 = ROOT.TH1I("h1", "h1", 150, 7000, 10000)
tree.Draw("ADC[0]>>h1")
c1.Draw()

f:id:onsanai:20210429200658p:plain

描画するだけなら楽。

次、Numpyオブジェクトにしてからmatplotlibで描画する。

import ROOT
import numpy as np
import matplotlib.pyplot as plt
df = ROOT.RDataFrame("tree", "filename.root")
npy = df.AsNumpy()
plt.hist([a[0] for a in npy["ADC"]],range=[7000,10000],bins=150)
plt.show()

f:id:onsanai:20210429200716p:plain

データの扱いがめんどくさいが、グラフの扱いは楽。数値計算をもっと便利にできるライブラリもあるとは思うが、僕は知らない。

データを加工したり、カットをかけたりする場合は、やはりROOTで頑張ったほうが楽だな、と。

例えば、ADC[0]が9000以上を、ADCの[0]と[1]の相乗平均でヒストグラムを描画する。

tree.Draw("(ADC[0]*ADC[1])**(1.0/2.0)>>h1","ADC[0]>9000")
c1.Draw()

上記を正規分布でフィッティングする

tree.Draw("(ADC[0]*ADC[1])**(1.0/2.0)>>h1","ADC[0]>9000")
f1 = ROOT.TF1("f1","gaus",7000,10000)
h1.Fit("f1")
ROOT.gStyle.SetOptFit(1)
c1.Draw()

f:id:onsanai:20210429201857p:plain

PyROOTになったところでROOTであることは変わらないので、ROOTの作法を覚える手間はほぼ変わらないので、ROOT C++でいいじゃんって思う。

仮に、Pythonで容易にデータ解析ができるフレームワークを持っている実験グループは、ROOTが内部でゴリゴリC++で実装しているように、誰かが裏でゴリゴリコーディングしてくれているおかげなのだ、ということを忘れないでほしい。

WSL上のJupyter LabでPython/ROOT C++/PyROOT、Jupyter Notebookでjsrootを動かす

超メモです。$は削除して実行してください

WSLでJupyter Labを動かす方法

nodejsは最新版を推奨する。それ以外だとエラーが出ることがある。pip3でsudoは付けない。以下、実行すべきコマンド。

$ sudo sed -i.bak -e 's%http://[^ ]\+%mirror://mirrors.ubuntu.com/mirrors.txt%g' /etc/apt/sources.list
$ sudo apt -y update && sudo apt -y upgrade && sudo apt -y install build-essential python3-pip
$ curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
$ sudo apt -y install nodejs
$ pip3 install --upgrade setuptools
$ pip3 install testresources metakernel nodejs
$ pip3 install jupyterlab widgetsnbextension 

pip3をユーザー権限で叩くと、$HOME/.local/binに実行ファイルが置かれるので、~/.bashrcに以下を追記する。

PATH="$HOME/.local/bin:$PATH"

Jupyter Labを起動してみる。 Windows上だと --no-browser は必要ないが、WSLからブラウザは開けないので、--no-browser オプションを必ず付けて、ブラウザなしで起動する。

$ jupyter lab --no-browser

とすると、

Or copy and paste one of these URLs:
http://localhost:8889/lab?token=94b26.............
http://127.0.0.1:8889/lab?token=94b26.............

とURLが表示されるので、これをWindowsのブラウザ(Google Chrome)のURLが表示されているところに貼り付ける。

拡張機能をインストールすると、再ビルドを求められることがある。

$ jupyter lab build
$ jupyter lab --no-browser

拡張機能をブラウザからインストールできないときは、コマンドラインからインストールを試す。補完用のtocはブラウザからなぜかインストールできなかった。

$ jupyter labextension install "@jupyterlab/toc"

Jupyter Lab上でROOT C++/PyROOTを動かす

まず、ROOTを入れる。ハードルは高いが頑張る。権限の問題から、/opt/root/6.22.08 ではなく、ユーザーディレクトリ、例えば $HOME/root/6.22.08 にインストールするのが望ましい。

github.com

プリコンパイルバージョンは、画像のライブラリの一部がコンパイルされていないため使えない。

~/.bashrc に、ROOTのPATHを追加する

export ROOTSYS=$HOME/root/6.22.08
cd $ROOTSYS
source bin/thisroot.sh
cd - > /dev/null

Jupyter Labをインストールする。以下、実行すべきコマンド。

$ sudo apt -y install python3-pip
$ curl -fsSL https://deb.nodesource.com/setup_16.x | sudo -E bash -
$ sudo apt -y install nodejs
$ pip3 install --upgrade setuptools
$ pip3 install testresources metakernel nodejs
$ pip3 install jupyterlab widgetsnbextension 

Jupyter-Labを起動し、URLをブラウザで開く。

jupyter lab --no-browser

すると、以下のように、PythonとROOT C++が表示されるはずである。

f:id:onsanai:20210428202232p:plain

サンプルコードは公式から引用する。

HowTo_ROOT-Notebooks

TH1F *h = new TH1F("gauss","Example histogram",100,-4,4);
h->FillRandom("gaus");
TCanvas *c = new TCanvas("myCanvasName","The Canvas Title",800,600);
h->Draw();
c->Draw();

f:id:onsanai:20210428202711p:plain

こうなればOK。当然Pythonからpyrootも動くのでPython 3の方からノートを作り、

import ROOT
h = ROOT.TH1F("gauss","Example histogram",100,-4,4)
h.FillRandom("gaus")
c = ROOT.TCanvas("myCanvasName","The Canvas Title",800,600)
h.Draw()
c.Draw()

f:id:onsanai:20210428202838p:plain

こうなればOK。

Jupyter Notebook上でjsrootを動かす

jsrootはブラウザ上でROOTファイルを動的に扱うJavaScriptのライブラリ。Jupyter Labでは使えないので、Jupyter Notebookを動かす。

root --notebook --no-browser

でJupyter Notebookを開くと、%jsroot (jsrootの有効化)で、Drawすると軸が動的に触れるようになる。

有効化するには ROOT.enableJSVis()と書いても良い。無効化するには ROOT.disableJSVis() で静的に戻る。

f:id:onsanai:20210429151144p:plain

参照: nodejsのインストール方法

GitHub - nodesource/distributions: NodeSource Node.js Binary Distributions

途中で出たエラー(検索用)

ImportError: cannot import name 'StaticModule' from 'setuptools.config' (/usr/lib/python3/dist-packages/setuptools/config.py)