【備忘録】Pythonのserialモジュールは似たようなものが2つある
はじめに
このくそ忙しい時期にRS-232Cのシリアル通信で実験機器のパラメータを早急に変える必要があった。
滅多に行わない処理で、常設のコードなんてものはないので、Pythonでパラメータを先に変えてしまおうと判断した。
問題
シリアル通信のモジュールをpip installし、いざ
import serial conn = serial.Serial("COM3", baudrate=9600) >>> AttributeError: module 'serial' has no attribute 'Serial'
serialにSerialがないと怒られる。
原因
Pythonのシリアル通信モジュールには2種類ある
・pySerial
・serial
このうち、pyserialには「Serial」があり、serialにはないらしい。
両方ともimport serialでモジュールをインポートするので、「Serial」が呼ばれない。
対策
pip uninstall serial pip uninstall pyserial pip install pyserial
一度全部消してからpyserialのほうをインストールすればよい
所感
少しだけ調べた限り、pyserialを使った記事のほうが多いのでpyserialのみを使用したほうが無難。
筆者のようなネット記事のサンプルコードのimport文だけを見て「pip install serial」をしてしまうPythonをちょっとかじった人がハマりそう。
【備忘録】Classのカッコの有無【Python】
概要
PythonのClassを使用するとき、カッコを付けないと処理が変わる。
たまに大きめの処理をするコードを1から書くことがあり、仕様を忘れて調べる羽目になっているので備忘録を残す。
ついでに、listにclassを入れた後の変更も反映されているか確認する。
カッコ有①
class TmpCls: a = 1 li = [] for i in range(4): tmp = TmpCls() #←ここ print("値変更前",i,tmp.a) li.append(tmp) tmp.a = i print("値変更後",i,tmp.a) for ttmp in li: print("for外 : a",ttmp.a) ##出力 値変更前 0 1 値変更後 0 0 値変更前 1 1 値変更後 1 1 値変更前 2 1 値変更後 2 2 値変更前 3 1 値変更後 3 3 for外 : a 0 for外 : a 1 for外 : a 2 for外 : a 3
カッコ無①
class TmpCls: a = 1 li = [] for i in range(4): tmp = TmpCls #←ここ print("値変更前",i,tmp.a) li.append(tmp) tmp.a = i print("値変更後",i,tmp.a) for ttmp in li: print("for外 : a",ttmp.a) ##出力 値変更前 0 1 値変更後 0 0 値変更前 1 0 値変更後 1 1 値変更前 2 1 値変更後 2 2 値変更前 3 2 値変更後 3 3 for外 : a 3 for外 : a 3 for外 : a 3 for外 : a 3
カッコを付けない場合は文字通り「tmp=TmpCls」ってコト?
確認
class TmpCls: a = 1 def __init__(self): self.b = 7 tmp = TmpCls print("a =",tmp.a) print("b =",tmp.b) ##出力 a = 1 >>例外が発生しました: AttributeError type object 'TmpCls' has no attribute 'b' in line 8 print("b =",tmp.b)
インスタンスも当然読めないっぽい
VSCodeとgithubのSSH接続をした時の備忘録
はじめに
VSCode管理しているワークスペースをgitで同様に管理できるのはよく知られている。
筆者は普段仕事(Private,HTML)用しか使っていなかったため、それ以外(Public,SSH)で管理するためにややてこずった。
今後もあり得るので備忘録を残しておく。備忘録なので説明不足は悪しからず。
方法
ホストPCでgitのSSH設定
① 公開鍵と秘密鍵を作る
② /home/janedoe/.ssh/configに以下の設定を書き加える
Host github HostName github.com User git IdentityFile /home/ janedoe /.ssh/id_ssh_key
この時ホスト名を「github」にするところがポイント。なぜか「git@github.com」だと後々のSSHが失敗する。
③ 公開鍵(.pubの方)の中身をhttps://github.com/settings/keysから「newkey」として貼り付け
④ SSH接続が通るか確認
$ ssh -T github Hi junedoe! You've successfully authenticated, but GitHub does not provide shell access.
上の返答があればOK
VSCodeでgit設定
① リモートエクスプローラからホストのプロジェクトファイルを開く
この時、ホスト・ゲスト間でも公開鍵認証を通しているととても楽
② [Ctrl]+[Shift]+[G]でソース管理タブを開いてgitを接続する
③ プロジェクトファイル/.git/configを開いてurlの部分を変更する
[remote "origin"] url = github:janedoe/プロジェクト名.git fetch = +refs/heads/*:refs/remotes/origin/*
※ここで.ssh/confのHost名の「github」が参照されるので注意
※よく$ git remoteで変更する記事では「git@github.com」で変更しているのでつられないこと
VSCodeでpythonがF5キーで実行できないバグ(?)
症状
・ちょっと前から(2022年8月入ってから?) VSCodeで[F5]キーを押しても実行されない状態になった。
・[デバッグの開始][デバッグなしで実行]ともに実行できない。
・一瞬実行時のツールバーみたいなもの(ブレークポイントでデバッグするときに使うやつ)が出現するが、何も起こらない。
・コンソールの[出力]タブの[Python]には実行履歴だけが残る。
・エラーは出ない
・右上にある[新しいPythonファイル]と書かれた▷を押すと一応動く
2022/08/18追伸
VSCodeの自動更新を切る方法
自動更新を切っておかないとふとした拍子に最新版になってしまう。
- [Ctrl]+[,]で設定を開く
- 検索boxにupdate.modeと入力する
- [Default]を[None]にして無効化
【2022年2月】CentOS8でyum(dnf)が使えない時の対処法
はじめに
2021年12月31日にCentOS8がEOLになった。続いて2022年2月に公式のURLが切れたことでyum(dnf)のコマンドが使えなくなった。
しばらくはCentOS7にもStreamにも移行する気力はないが、開発はしたいので備忘録を記しておく。
多分2024年6月30日にCentOS7がEOLになった時も同じことになりそうな気がする。
以降yumもdnfも同じことをすればいい(はず)なので特に記さない限り共通の方法を記しておく。
エラー
これが出た人が対象。
[daq@localhost ~]$ su [root@localhost ~]# yum list Error: Failed to download metadata for repo 'AppStream': Cannot prepare internal mirrorlist: No URLs in mirrorlist
方針
/etc/yum.repos.d/のディレクトリの中にyumのURLを指定できる.repoというファイルがいくつかある。
今回のyumのエラーはURL切れが原因なのでこのURLを別の場所に書き換えてしまえばよい。
あまりうまくいかなかった方法
①「mirrorlist=~」で始まる行をコメントアウト
②「baseurl=~」で始まる行を有効化して参照先のURLを変更
一々エディタで変更するのも面倒なので一括で行う。以下のコマンドを使えばよい。
[daq@localhost ~]$ su [root@localhost ~]# sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/C [root@localhost ~]# sed -i 's|#baseurl=http://mirror.centos.org|baseurl=http://vault.centos.org|g' /etc/yum.repos.d/CentOS-Linux-*;
↑コマンドが勝手に改行されるが、3つ目のコマンドは1行で張り付けてほしい。
結果
URLのエラーは出ないがvaultのURLが死ぬほど遅くてタイムアウトになる。
うまくいった方法
基本は先ほどと同じだが参照先のURLを公式のvaultから理研にしてしまう。
ただ、理研の場合CentOS8のバージョンによって参照先が違うので以下のコマンドで現在のバージョンを確認する。
[daq@localhost ~]$ su [root@localhost ~]# cat /etc/redhat-release CentOS Linux release 8.4.2105
自分のバージョンがあるかどうかの確認はこちら
ftp.riken.jp
あったら先ほどと同じように変更する。
「あまりうまくいかなかった方法」を試していない人向け
[daq@localhost ~]$ su [root@localhost ~]# sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-Linux-*; [root@localhost ~]# sed -i 's|#baseurl=http://mirror.centos.org/$contentdir/$releasever/|baseurl=https://ftp.riken.jp/Linux/centos-vault/8.4.2105/|g' /etc/yum.repos.d/CentOS-Linux-*;
↑コマンドが勝手に改行されるが、すべてのコマンドはそれぞれ1行で張り付けてほしい。
「あまりうまくいかなかった方法」を試してしまった人向け
[daq@localhost ~]$ su [root@localhost ~]# sed -i 's/mirrorlist/#mirrorlist/g' /etc/yum.repos.d/CentOS-Linux-*; [root@localhost ~]# sed -i 's|baseurl=http://vault.centos.org/$contentdir/$releasever/|baseurl=https://ftp.riken.jp/Linux/centos-vault/8.4.2105/|g' /etc/yum.repos.d/CentOS-Linux-*;
↑コマンドが勝手に改行されるが、すべてのコマンドはそれぞれ1行で張り付けてほしい。
【超初心者向け】C++とPyROOTの2方法でテキストデータをrootファイルに変換する
方法
今回はC++を使ったオーソドックスな方法とPyROOTを使った方法を紹介する。
ちなみに完成系はこのような形になる。
C++を使った方法
筆者はCentOS8を使用。真似したい場合は以下の記事を参照。
phbe.hateblo.jp
※CERN ROOTを入れいない人は以下の記事を参照。
phbe.hateblo.jp
データの準備
今回は以下の記事で作ったテキストデータをそのまま使用する。
phbe.hateblo.jp
makefileの作成
C++で作ったコードは一度コンパイルしてから実行する。
コンパイルを楽にするおまじない的なものがmakefileだ。
ファイルの名前もそのままmakefileにして作成する。
よくわからない人は丸写しを推奨する。
TARGET = mkNT SRCS = $(TARGET).cc OBJS = $(TARGET).o ROOTFLAGS = $(shell root-config --cflags) ROOTLIBS = $(shell root-config --libs) CXXFLAGS = -Wall -O2 $(ROOTFLAGS) CXXLIBS = $(ROOTLIBS) CC = g++ all: $(TARGET) $(TARGET): $(OBJS) $(CC) $(CXXLIBS) $(OBJS) -o $@ $(TARGET).o:$(TARGET).cc $(CC) $(CXXFLAGS) -c $< clean: rm -f $(TARGET) $(OBJS)
1行目の「mkNT」というのが今回作りたいコードの名前である。
「mkNT.cc」という名前のC++コードをコンパイルできるようになった。
もちろん別の名前のコードをコンパイルしたい場合は「mkNT」の部分をその名前に変えて実行する。
複数のコードを同時にコンパイルする方法もあるが、今回は触れない。
コードの作成
コード作成前に今回のデータを整理する。
今回のデータは以下のように書かれている
イベント番号 | ADC値 | TDC値1~3 | ランダム数1~6 |
整数 | 整数 | 整数 | 小数 |
このうちTDC値を1次元配列に、ランダム数を2次元配列にしてみる
#include "TApplication.h" #include <math.h> #include <TROOT.h> #include <TNtuple.h> #include <TStyle.h> #include <TFile.h> #include <fstream> #include <iostream> using namespace std; const char kNameInFile[20] = "output.dat"; const char kNameOutFile[20] = "output.root"; int main(){ cout << "Input File = " << kNameInFile << endl; cout << "Output File = " << kNameOutFile << endl; // define value Int_t ieve; Int_t adc; Int_t tdc[3]; Double_t rand[2][3]; //open root gROOT->SetStyle("Plain"); gStyle->SetOptStat("neiuoMR"); gStyle->SetPalette(1); TTree *tree = new TTree("raw", "raw tree"); tree->Branch("ieve", &ieve, "ieve/I"); tree->Branch("adc", &adc, "adc/I"); tree->Branch("tdc",tdc, "tdc[3]/I"); tree->Branch("rand",rand, "rand[2][3]/D"); // open dat file ifstream indata(kNameInFile); // file exist check if (indata.fail()) { cout << "### program err ###" << endl; std::cerr << "!!!Failed to open file!!! \n!!!Not found this file!!!" << std::endl; cout << "### program close ###" << endl; return -1; } // get data & write while (indata >> ieve >> adc >> tdc[0] >> tdc[1] >> tdc[2] >> rand[0][0]>> rand[0][1]>> rand[0][2]>> rand[1][0]>> rand[1][1]>> rand[1][2] ) { tree->Fill(); if (ieve%1000 == 0){ cout << "event_loop = "<< ieve << endl;} } cout << "event num = " << ieve+1 << endl; indata.close(); // write rootfile TFile *fout = new TFile(kNameOutFile, "recreate"); tree->Write(); fout->Close(); // end cout << "F!!!!!!!!!!!!!!!!!!!!!!" << endl; return 0; }
コンパイル、実行
[***@localhost **] $ make
エラーとかが出なければコンパイル完了なのでそのまま実行。
[***@localhost **] $ ./mkNT Input File = output.dat Output File = output.root event_loop = 0 event_loop = 1000 event_loop = 2000 event_loop = 3000 event_loop = 4000 event_loop = 5000 event_loop = 6000 event_loop = 7000 event_loop = 8000 event_loop = 9000 event num = 10000 F!!!!!!!!!!!!!!!!!!!
このような出力になれば成功。
PyROOTを使った方法
PyROOTはC++で書いたものよりも浸透していないので記事が少ない。
特に同じことをするためのコードを比較するような記事が少ないので是非確認してほしい。
作成の流れ
- データの準備
- コードの作成
- 実行
データ準備
C++のやり方と同じ方法で行う
コードの作成
今回は「mkNT.py」という名前で作成する。
from ROOT import TTree , std , TH1F, TFile import numpy as np kNameInFile = "output.dat" kNameOutFile = "output.root" print("Input File = "+kNameInFile) print("Output File = "+kNameOutFile) # define value ieve = np.empty((1), dtype="int32") # この書き方でないとバグる adc = np.empty((1), dtype="int32") # この書き方でないとバグる tdc = np.zeros((3,), dtype="int32") # この書き方でないとバグる rand = np.zeros((2,3), dtype="float") # この書き方でないとバグる # open root rawtree = TTree("raw","raw_tree") rawtree.Branch('ieve',ieve,'ieve/I') rawtree.Branch('adc',adc,'adc/I') rawtree.Branch('tdc',tdc,'tdc[3]/I') rawtree.Branch('rand',rand,'rand[2][3]/D') # open dat file fin = open(kNameInFile,"r") # get data & wtite for line in fin: tmp = line.split() if len(tmp)==0: continue ieve[0] = int(tmp[0]) adc[0] = int(tmp[1]) tdc[0] = int(tmp[2]) tdc[1] = int(tmp[3]) tdc[2] = int(tmp[4]) rand[0][0] = float(tmp[5]) rand[0][1] = float(tmp[6]) rand[0][2] = float(tmp[7]) rand[1][0] = float(tmp[8]) rand[1][1] = float(tmp[9]) rand[1][2] = float(tmp[10]) rawtree.Fill() if ieve%1000 == 0: print("event_loop = "+str(ieve)) print("event num = "+str(ieve+1)) fin.close() # write rootfile fout = TFile(kNameOutFile,"recreate") rawtree.Write() fout.Close() # end print("F!!!!!!!!")
実行
Pythonの場合は簡単で、terminal上で以下のコマンドを入力するだけである。
[***@localhost **] $ python3 mkNT.py Input File = output.dat Output File = output.root event_loop = [0] event_loop = [1500] event_loop = [3000] event_loop = [4500] event_loop = [6000] event_loop = [7500] event_loop = [9000] event num = [10000] F!!!!!!!!
このような出力になれば成功。
確認
後は好きなように完成したrootファイルを確認すればよい。
[***@localhost **] $ root output.root root [] .ls root [] raw->Print() root [] raw->Draw("neve") root [] raw->Draw("adc") root [] raw->Draw("tdc[0]") root [] raw->Draw("rand[0][0]") root [] raw->Draw("adc:tdc[0]") root [] raw->Draw("adc:tdc[0]-tdc[1]-tdc[2]")