JavaのTreesetをPythonで
「できらあ!!」
「え!!同じデータ構造をPythonで!?」
というわけでJavaのTreesetに当たるデータ構造がPythonで欲しくなったので、自分で実装してみました。
treeset.pyをコピーして使ってください。
Treesetはsetのように、重複が存在しないデータ集合ですが、setと違い、初期時にデータがソートされます。また、新しい要素が追加されるたびに、二分木探索によって適切な位置に挿入されます。
使い方は例えば、こんな感じ。
from treeset import TreeSet
# 初期化時に重複要素は消える、またソートが行われる ts = TreeSet([3,7,2,7,1,3]) print(ts) >>> [1, 2, 3, 7]
# 4を加えると、3と7の間に挿入される ts.add(4) print(ts) >>> [1, 2, 3, 4, 7]
インデックスによる取得、要素を指定してリムーブもできます。
# 三番目の要素を取得
print(ts[2])
>>> 3
# 最後の要素を取得
print(ts[2])
>>> 3
# Treesetに7があれば消去
ts.remove(7) print(ts) >>> [1, 2, 3, 4] ts.pop(2)
# インデックスをpop print(ts) >>> [1, 2, 4]
中身はシンプルでbisectモジュールを使って、適宜、中身のデータをソートしているだけです。
from treeset import TreeSet
class TreeSet(object)
def __init__(self, elements):
self._treeset = []
for element in elements:
self.add(element)
def add(self, element):
# 要素が既に存在しなければbisect.insertで適切な位置に挿入
if element in self._treeset: continue
self.add(element)
bisect.insort(self._treeset, element)
よかったらお試しください。
PythonだけでRaspberry piのGPIOピンをALT0に設定するための話
raspberry Pi2を最近いじっているのですが、GPIOピンからクロックをチップに供給したいことがありました。
そのためには、例えばGPIOピン5を通常の入出力ではなく、ALT0 (alternative function 0)に設定する必要があります。
他にもクロック出力を設定できるピンがありますが、詳しくはraspiに搭載されているARMプロセッサであるBCM2835のデータシートを参照してみてください(102pくらい)。↓
https://www.raspberrypi.org/wp-content/uploads/2012/02/BCM2835-ARM-Peripherals.pdf
結局色々調べたのですが、Pythonだけで完結できず、こちらのページ↓を参考にしてcプログラムでクロックを出力することに成功。(感謝!)
しかし、データ取得・解析にはPythonを使っていたので、できれば動いているコードはPythonだけで統一したいなあと思い、必要なライブラリを実装しました。
そのために、RPIOライブラリのカスタマイズを行います。
ただし、私が使っているのはraspberry Pi2なのですが、現在RPIOはraspberry Piに対応していない模様。raspberry Pi2でも使えるようカスタマイズされた
を改造し、ALT0への対応を行います。
■成果物
できました。フォーク元にプルリクエストを投げましたが、どうなることやら無事速攻でマージされました、感謝。
■インストール、つかいかた
raspberry Piターミナル上で
git clone https://github.com/fukatani/RPIO.git
git clone https://github.com/tylerwowen/RPIO.git
cd RPIO
python setup.py install
とうち、ここで完了と思いきや、なぜか私の環境では
dist-packagesに未解凍のファイルが置かれます(左下)。シュール。
なんででしょうね。前世の行いでしょうかね。知ってる人、教えてくださいね。
しょうがないので、手作業で解凍してやりインストール完了です。
import RPIO
RPIO.setup(5, RPIO.ALT0)
とすると、5ピンからGPCLK1(大体20MHz)がでます。嬉しいです。
ちなみにGPCLKは波形がグチャグチャでそれなりに高周波ノイズが激しいので、クロックの波形を直で突っ込むとSPIなどの波形がゆがむことがあります。最悪、通信が失敗し、かえって来たデータが信用できなくなるかもしれません。
そういう場合はクロックの後ろに抵抗(100ohmくらい?)つけてみましょう。
高周波成分が除去されて、通信が成功するようになるはずです。
なんか今ハードウェアエンジニアっぽいこといってしまった、、、
■追伸
うーん、RPIOの一部テストが通りません。フォーク元も。Pi2はピン配変わったからかしら。
raspberry Pi用のTravis CIがあったらいろいろはかどるのになー。
やる気があるひと修正してみましょう(人まかせ)。
雑記:IDE使用時にPythonで標準出力をリダイレクトした時のちょっとしたトラブルシューティング
Pythonでは標準出力(いわゆるprint関数の中に入れると文字がコンソールに出ちゃう奴)の出力先をファイルに変える(=リダイレクトする)のも簡単だ。
↑このへんを参考にしつつ
>>> import sys
>>> sys.stdout = open('out.txt', 'w')
>>> print('uwaaaaa')
と書くだけで、コンソールにuwaaaaaと表示される代わりに、out.txtと言うファイルが実行ディレクトリで作成され、その中にuwaaaaaというメッセージが書き込まれるのである。
標準出力をコンソールに戻すのも基本的には簡単でsys.stdoutにsys.__stdout__を代入してやればよい。すなわち、
>>> import sys >>> sys.stdout = open('out.txt', 'w') >>> print('uwaaaaa') >>> sys.stdout = sys.__stdout__ >>> print('yamerooooo')
と実行するとuwaaaaaはout.txtに表示されるが、yameroooはコンソールに表示されるのである。
ところが、コマンドプロンプトなどからPythonを実行していない場合、例えば、PyscripterなどのIDE上でPythonを実行していると、uwaaaaaはout.txtに表示されるが、yameroooはどこにも表示されないことに気づいた。
これについて調べてみるとどうもPyscripterではsys.__stdout__ではなく別の標準出力を最初から使っている事が原因のようだ↓
https://groups.google.com/forum/#!topic/pyscripter/rhtXtinfmGM
Pyscripter固有の解決法を施して、他の環境では動かないコードが入るのは避けたいしな、、と悩んでいたが、シンプルにsys.stdoutの初期の実体が何であれ、それを一時的に確保して後で用が済んだら戻してやればよいと言うことに気づいた。
すなわち、
>>> import sys
>>> temp_sysout = sys.stdout >>> sys.stdout = open('out.txt', 'w') >>> print('uwaaaaa') >>> sys.stdout = temp_sysout >>> print('yamerooooo')
としてやればよい。これで「yamerooooo」はコンソールに表示されるのである。勿論IDEだけでなく、コマンドプロンプトでも動作する。
Veriloggenを使ってみた、そしてVerilogメタプログラミングの新地平を見た
以前から気になっていたshtaxxx氏作Veriloggenを実際に使ってみた。
これは…熱い!
私が書いてみたコード↓
for文の中でクロック分周を繰り返しているのが肝。
生成されたverilog↓
うは!意図通りできてる!!!
for文に入れるだけで三回クロックが分周できてる!!!
これは、楽しいです。
私が考えたveriloggenのメリットとしては、
・verilogのダサい文法が回避できる(begin - endとか)
・柔軟にメタプログラミング的なことが出来る。genvarでもある程度できるが、規則的にレジスタ名を生成するようなことはできない。
・抽象レベルでの回路定義。なんかちょっとパラメータ入れたらおっきいコード吐くみたいな。
今後機能がたくさん追加されるようなので、おっかけとくことにします。