キーワード付き引数におけるpandas DataFrameの扱い

pandasのDataFrameをキーワード付き引数として渡したいときについてです。タプルやリストは

def func(tup = None, li = None):
    if(tup != None):
        print(tup)
    if(li != None):
        print(li)

のような関数を定義してもエラーは出ません。しかし、

def func2(df = None):
    if(df != None):
        print(df)

として引数としてpandasのDataFrameを渡してやると下記のようなエラーが出ます。(ちなみにfunc2にタプルやリストを渡してもエラーは出ません)

TypeError: Could not compare [None] with block values

いつもながらgoogle先生に聞いてみると英語情報ですが同じ質問をしている方がおられました。

stackoverflow.com

要約すると比較演算子

!=

じゃなくて

is not

を使えと書かれてます。

詳しい説明の方も読もうかと思ったのですが、あんまり良くわからなかったので分かる方はぜひ読んでみてください。

PyQtのタブ

PyQtにおいてどのタブがアクティブであるかを判断するにはタブのメソッドであるcurrentIndexを見るとわかります。タブに追加した順に0から整数が割り振られます。その数字によって選択されているタブが分かります。

日本語での情報がなかったので書いてみました。英語の情報はStack Overflowに載っているので、URLを載せておきます。

stackoverflow.com

短いですがこの辺で。

limitlessledその3

PythonGUIプログラミングをするときはだいたいPyQtを使っています。あまり使い慣れていないということもありまして一つのGUIプログラムを作るのに非常に時間がかかっていたのですが、この前いじっているときにようやっとコツを掴んだというか理解したのである程度のものは作れるようになりました。

そこで前々から作ろうと思っていたlimitlessledのタイマーを作ったので公開してみようと思います。

まず、自分の環境についてですが

  • macOS Sierra 10.12.3
  • anaconda3-4.1.0

です。どこまで環境を書けばいいのかわからないのですが、もう少し詳しく書くと、まずmacにhomebrewを入れて、その後pyenvを入れました。pyenvからanacondaを入れました。anacondaにはPyQtが標準で入ってたはずですが、入っていなければ

conda install pyqt4

とかでインストールできると思います。なので、あとはlimitlessledのPythonライブラリであるledcontrollerのインストールのみで自分のプログラムは起動できるはずです。ledcontrollerのインストールは上記のように

conda install ledcontroller

でいけるはずです。

あとanacondaのPATHなんかは通しておいてください。

実際のプログラムは以下になります。

# -*- coding: utf-8 -*-


import sys
import PyQt4.QtGui as gui
import PyQt4.QtCore as core
import ledcontroller as led
import time
import threading as th

IP = 'xxx.xxx.xx.xx'
LED = led.LedController(IP, group_1='white', group_2='white', group_3='white', group_4='white')

class UI(gui.QMainWindow):
    def __init__(self):
        super().__init__()
        self.cancel = False
        self.progress = 0
    
    def initUI(self):
        exitGUI = gui.QApplication.style().standardIcon(gui.QStyle.SP_TitleBarCloseButton)
        exitAction = gui.QAction(exitGUI, 'Quit Milight', self)
        exitAction.setShortcut('Ctrl+Q')
        exitAction.setStatusTip('Exit application')
        exitAction.triggered.connect(gui.qApp.quit)
        
        menubar = self.menuBar()
        fileMenu = menubar.addMenu('Milight')
        fileMenu.addAction(exitAction)
        menubar.setNativeMenuBar(False)
        
        #group_box1
        #hbox1
        tim = gui.QComboBox(parent = self)
        tim.activated[str].connect(self._activate)
        times = ['30', '60', '90', '120']
        tim.addItems(times)
        cancel = gui.QPushButton('cancel', parent = self)

        hbox1 = gui.QHBoxLayout()       
        hbox1.addWidget(tim)
        hbox1.addStretch(1)
        hbox1.addWidget(cancel)
        
        #hbox2
        self.pbar = gui.QProgressBar(parent = self)
        self.percentage = gui.QLabel('0%', parent = self)
        
        def stop_progress():
            self.cancel = True
        cancel.clicked.connect(stop_progress)
        
        hbox2 = gui.QHBoxLayout()
        hbox2.addWidget(self.pbar)
        hbox2.addWidget(self.percentage)        
        
        vbox1 = gui.QVBoxLayout()
        vbox1.addLayout(hbox1)
        vbox1.addLayout(hbox2)

        group_box1 = gui.QGroupBox('Timer', parent = self)
        group_box1.setLayout(vbox1)
        
        #group_box2
        warm = gui.QPushButton('Warm')
        warm.clicked.connect(LED.warmer)
        cool = gui.QPushButton('Cool')
        cool.clicked.connect(LED.cooler)

        
        hbox3 = gui.QHBoxLayout()
        hbox3.addWidget(warm)
        hbox3.addWidget(cool)

        
        group_box2 = gui.QGroupBox('Cool and Warm')
        group_box2.setLayout(hbox3)
        
        on = gui.QPushButton('ON', parent = self)
        on.clicked.connect(LED.on)
        off = gui.QPushButton('OFF', parent = self)
        off.clicked.connect(LED.off)
        
        hbox4 = gui.QHBoxLayout()
        hbox4.addStretch(1)
        hbox4.addWidget(on)
        hbox4.addWidget(off)
        
        Gbox = gui.QVBoxLayout()
        Gbox.addWidget(group_box1)
        Gbox.addWidget(group_box2)
        Gbox.addLayout(hbox4)
        
        w = gui.QWidget(parent = self)
        w.setLayout(Gbox)
        self.setCentralWidget(w)
        
        self.setGeometry(100, 150, 250, 250)
        self.setWindowTitle('Milight')
        self.show()
    
    def _activate(self, text):
        print(time.ctime())
        minutes = int(text)
        self.cancel = False
        
        thread1 = th.Thread(target=self._ti, args =(minutes,))
        thread1.start()
    
    def _ti(self, minutes):
        for i in range(minutes*60):
            if(self.cancel):
                break;
            self.progress = (i+1)/(minutes*60)*100
            time.sleep(1)
            self.pbar.setValue(self.progress)
            self.percentage.setText('{}%'.format(round(self.progress)))
        if(not self.cancel):
            LED.off()
        self.pbar.setValue(0)
        self.percentage.setText('0%')
            
        


def main():
    app = gui.QApplication(sys.argv)
    ui = UI()
    ui.initUI()
    sys.exit(app.exec_())

if __name__ == '__main__':
    main()

IPと書かれているところはlimitlessledのwi-fiブリッジのIPアドレスを入力してください。自分は固定IPを振っています。あと新しくlimitlessled dual whiteを購入してそちらを使っているので一番最初の

LED = led.LedController(IP, group_1='white', group_2='white', group_3='white', group_4='white')

のところで

group_x = 'white'

としています。この前で使っていたRGBWの方はこのような引数を与える必要はなかったのですがdual whiteでは必要になるようです。 環境さえ整えばmacじゃなくてもlinuxwindowsとかでも動くんじゃないかなと思います。 あと不具合というほどのことでもないのですが、自分の環境ではこのプログラムを起動して最前面にしておかないとTimerが動いてくれない時があります。

初めてまともなGUIを自分で組めました。わりと達成感がありますね。これからも色々作っていけたらいいなと思います。

起動したときのスクショは以下のようになります。

f:id:jinpei0908:20170218094932p:plain

grapher

先日grapherを使ってみたらあれすごいですね~

re(), im()とかで実数部とか虚数部だけを取り出したりできるみたいですね。 いまのところそれぐらいしかすごいところを見つけてられてないのですが。

いまいち名前が知られてないのか、ドキュメント的なものもあまりないので自分で使い方を見つけていくしかないのかもしれません。csvファイルを読み込んでプロットとかできるみたいですが、あんまやり方がわかってないんですよね。普通に使えるようにしたら結構便利だとおもうんですが。

grapherというタイトルの割に全く何も書いてないですね。 たまには短い文章も、ということで。

マルチスレッド

いつもながらPythonのことを。

limitlessled用のプログラムをPythonで組んだ(ここらへんのくだり)のですが、微妙に使いづらくあまり使っていません。というのもタイマーで何分後にオフみたいな設定をtime.sleep()で実装しているので、実際sleepしている間他の操作を受け付けなくなるんですよね。自分だけしか使わないのでそれでもいいのですが、できれば他の操作を受け付けるとかキャンセルボタンでタイマーをキャンセルするとかできると便利だな−と思ってました。

マルチスレッド機能が使えれば待ち時間も他の操作を受け付けることができるなと思い出して色々調べていたのですが、なかなか理解できません……

プログラム自体はPyQtを使っているのでQThreadを使おうかと思ってみても、日本語のチュートリアルが少ない…… そもそもPythonを始めたきっかけのマイナビニュースのサイトを見るとthreadingライブラリを使っているので、こっちを使ってみるべきなんですかね。

イマイチPyQtにもなれていないので、更に新しいことをやろうとするとつまづきが多くて戸惑ってしまいますね。

久しぶりに書いた割になんの進歩もしていないのですが、こんな感じですかね。

あと全然関係ないですが、raspberry pi 3を買おうと思ってます。一応Airでもfedoraが使えるようにはしてあるんですが、Linux専用機があったほうがLinuxは使うなと思いまして。しかも電子工作みたいなこともできるらしく、ちょっとしたロボットとか作ってみたいなーと思ってます。そこまで行くのにどんだけ勉強せなならんのかという感じですが。official starter kitがほしいんですよね−。薄型の有線キーボードなかなか売ってないので…あと統一感があっていいなと思います。rs onlineで買おうと思ったら個人相手にやってないそうなので、海外でもcana kitの方で買いますかね。

ではではこのへんで。

いつもながら適当なことをつらつらと

新年明けたのに何も書かないのもなあと思ったので書いてみます。

プログラミングの継承について

去年の暮れにあるプログラムを3つほどPythonで書いてたんですが、3つとも初っ端の書き出しの部分が同じ処理をしているんですよね。まあ、コピペすればいいだけの話なんですが、見栄えがよろしくないというのと保守性が悪い(だれかにソースコードを見てもらう必要がないので、これに関しては気にしてはないのですが)ということからどうにかならんかなと思ってました。そこで継承したらいいんじゃね?と思いつきまして、実際書いてみたら、まープログラムの見通しがよくなりましたね。今まで、継承って何のためにあんのかな―とか、GUIプログラミングしないなら使わんかとか思ってましたが、使ってみるといいもんですね。必要性を感じていなければ理解できない、と昔から自分は思っているんですが、まさにその通りだなと思いました。これからも継承使っていきたいですね。そこまで同じ処理をさせるプログラムを組むことがあるかどうかは疑問ですが。

C/C++コンパイルについて

今までCの文法とかはそこそこ学んできていたんですが、コンパイルとかは最低限のことしかしてきませんでした。まあ、コンパイルできればいいかみたいなことですね。ただ、Cのソースコードを実行するにもいくつか方法があるようです。

以下に書くのはあくまで自分の理解です。はっきり言ってあまり調べこんだ内容ではないので正確ではないと思います。
  • ただのコンパイル
    一番主流というか、簡単というか、これがそのままコンパイルって感じですかね。ソースコードをオブジェクトファイルにします、的な。ファイルが分割されているとそれぞれコンパイルされた後、ファイル同士を結合するリンクという作業が行われるようです。

  • ビルド
    IDEを使ってコンパイルすること。IDEの中ではプロジェクトという単位でプログラムを管理しているようで、プロジェクトの中に幾つもの分割されたファイルがあるというイメージですね。ビルドはそのすべてのファイルのコンパイルとリンクを行うことをいうようです。ただのコンパイルとの違いは、ただのコンパイルは各ファイルを手動でコンパイルして、リンクして、としなければなりませんが、ビルドはIDEが全部やってくれるので、簡単です。RUNボタン押すだけで、全てやってくれるという感じでしょうか。

  • メイク
    調べてみるとどうも廃れつつある技術のようですが、概要としてはコンパイラmakefileというレシピみたいなものを渡して、自動的にコンパイルとリンクをしてもらうという感じですかね。ただのコンパイルとの違いは、ただのコンパイルは分割ファイルをそれぞれコンパイルして、最後にリンクしなければならないのですが、メイクはmakefile内の指定したファイルをすべて勝手にコンパイル・リンクしてくれるというイメージです。まあ、ビルドと似たようなもんなのかな、と思います。ビルドと似たようなものだし、makefileを書く必要があるので、メイクの方が手間のかかる印象を受けます。IDEが登場して、しかもパソコンの性能もUPしているので、あまりメイク自体は使われなくなりつつあるのかと勝手に推理してます。

まあ、だいたい3種類くらいあるようですね。と言ってもビルドもメイクもコンパイルを内包しているんですが。ソースコードコンパイルして、リンクする、という流れはすべて同じかと思われます。それをすべて手動でやるのか、ちょっと楽するのか、だいぶ楽するのかの違いなのかなあと素人考えでは思ってます。

あと試してみたのですが、gccコンパイルはいくつかの.cファイルを一気にコンパイルすると勝手にリンクまでやってくれるようで、

gcc -o foo ./*.c

とやってやると、カレントディレクトリ内のすべての.cファイルをコンパイル・リンクしてfooという実行ファイルを作ってくれます。(たぶん)これができるならメイクいらなくね?とは思うのですが、素人にはわからない違いがあるんでしょうか。

あとわりと最近知ったのですが、上の例でいうとfooという実行ファイルをダブルクリックすると起動してくれるんですね。初めて知りました。ターミナルから起動しなくていいから便利です。

ってな感じで、新年早々長々と文章を書いてみました。久しぶりすぎて文章かけないですね。ってか久しぶりじゃなくても文章って書けなくなってますね。本読まないとだめですね。ってな感じで、またいずれ。

mac mini late 2012 メモリ増設

mac mini late 2012を2年前ぐらいにヤフオクで落札してそれ以降メディアサーバー的に使っているのですが、落札当初にSSD換装をしてからと言うもの全く内部を開けていじるようなことはしてきませんでした。まあ、端的にいうとメモリの増設をしていなかったというだけの話なんですが。

実際4GBしかなくともわりと快適に動いてきてくれましたし、意外とメモリって安くならんなとか思っていたら完璧に増設することを忘れてました。2日前くらいになんとなく思い立ってアマゾンを見てみると8GBの2枚セットのメモリが1万を切っていたので、メモリ増設するか―と思い立ちまして、今日換装しました。

で、写真付きで作業を解説しようかと思ったのですが、めんどくさいのでやめました。

実際増設した後の感想をば

まあ、元からSSD換装はしていたからなのか、そんなに体感できるほど速度が速くなったとは思えないです。ただ、iTunesの終了は気持ち速くなった気がしますね。とくにメモリを消費するような作業をするためにPCでもないので、こんなもんかなとは思います。実際アクティビティモニタでメモリの消費量を見たところ、2GBしか使ってないようだったので16GBもいらんかったなと思いました。増設後にエラーもなく起動できたのはわりとありがたかったですね。速度に関してはこれから使っていくうちに実感できるのかもしれないですね。

参考と購入したメモリ:

tools4hack.santalab.me

購入したのは以下の低電圧ではなく、標準を購入しました。

Amazon CAPTCHA

プログラミングのことを書くよりぜんぜん筆が進まないのは、なんでなんでしょうね。たまにはガジェット的なことも書きますよということで。

それでは