nlinum-mode で Emacs の行番号表示を軽くする

Emacs では標準添付の linum-mode でバッファの左側に行番号を表示することができます。
しかし、この linum-mode は非常に重いため、行数の多いバッファではとても使いものになりません。
({Emacs}linum-mode を軽くする で紹介されている設定を行えば多少軽くなります)
もしもバッファの左側に行番号を表示したい場合は、linum-mode を軽量化した nlinum-mode を使うことをおすすめです。

nlinum-mode のインストールと設定

nlium-mode のパッケージは Melpa からインストールできます。

M-x package-refresh-contents RET
M-x package-install RET nlinum RET

設定方法は linum-mode とほぼ同じです。

;; バッファの左側に行番号を表示する
(global-nlinum-mode t)
;; 5 桁分の表示領域を確保する
(setq nlinum-format "%5d ")

nlinum.png

Figure 1: org-mode のファイルは行数が多くなりがちですが、nlinum-mode なら問題ありません

個人的な Python 用の Emacs の設定

本も書き終わって一段落ということで、個人的な Emacs の Python 開発環境についてまとめます。
環境は Ubuntu15.04 64bit、Emacs は 24.5 です。

Python のインストール

Python のインストールには Anaconda を使うのが楽です。
最小のセットだけでいいなら、代わりに Miniconda を使います。

Anaconda は 公式ページ からインストーラをダウンロードしてインストールします。

以下のようなコマンドで仮想環境を作っておきます。

$ conda create -n py35 python=3.5 anaconda

次に、作った環境を有効化し、

$ source activate py35

以下のパッケージを追加でインストールしておきます。

$ pip install flake8 importmagic yapf autopep8 ipdb

yapfatuopep8 はコードを PEP8 に準拠するように自動整形してくれるモジュールです。
ypaf の方がきれいにコードを整形するので、autopep8 はインストールしなくてもいいです。

importmagic はコードから必要なモジュールを判別し、import 文を追加・整理してくれます。
個人的には使いこなせていません…

ipdb モジュールは IPython でデバッグする際に使っています。
これでブレークポイントなどを設定することができます。

Emacs の設定

自分の Emacs の設定から、特に Python に関係あるところを抜粋します。

Elpy

Python 用の拡張には Elpy を使っています。
他の拡張と比較したことはありませんが、使用感は良好です。

インストールと基本設定

Elpy は Melpa からインストールできます。

M-x package-refresh-contents RET
M-x package-install RET elpy RET

Elpy を使うために、init.el には次のように記述しています。

;;; Elpy を有効化
(elpy-enable)
;;; 使用する Anaconda の仮想環境を設定
(defvar venv-default "~/anaconda3/envs/py35")
;;; virtualenv を使っているなら次のようなパス
;; (defvar venv-default "~/.virtualenvs/hoge")
;;; デフォルト環境を有効化
(pyvenv-activate venv-default)
;;; REPL 環境に IPython を使う
(elpy-use-ipython)
;;; 自動補完のバックエンドとして Rope か Jedi を選択
(setq elpy-rpc-backend "jedi")

Elpy の設定は M-x elpy-config で確認できます。
インストールし忘れたモジュールがないかなども確認できます。

基本的な使い方

Elpy の 公式ドキュメント からいくつか基本的な使い方について抜粋します

.py 拡張子のファイルを開けば、自動的にマイナーモードで Elpy が有効になります。

C-c C-c (elpy-shell-send-region-or-buffer) でバッファ(またはリージョン) のコードが IPython で実行されます。
C-<RET> (elpy-shell-send-current-statement) でカーソル位置のステートメントを評価します。

C-c C-d (elpy-doc) でカーソル位置のシンボル(が指すオブジェクト) のドキュメンテーション文字列が別ウィンドウに表示されます。
q や C-g でバッファを閉じられます。

また、M-. (elpy-goto-definition) でカーソル位置のオブジェクトの定義箇所にジャンプします。

Elpy はデフォルトでは company-mode での自動補完が有効になります。
コードの入力途中で自動で候補が表示されますが、M-C-i(M-<TAB>)で手動で候補を表示させることもできます。
M-n や M-p で候補を選び、C-m で決定します。
候補の選択中に f1 か C-d で候補のオブジェクトのドキュメンテーション文字列が別ウィンドウに表示されます。
また、C-w で候補のオブジェクトの定義箇所が表示されます。
company-mode の設定などについては Qiita の記事 emacs の補完用パッケージ company-mode などが参考になります。

C-c C-e (elpy-multiedit-python-symbol-at-point) でカーソル上のシンボルについて、複数ファイルに渡って同時に編集することができます。
M-x elpy-refactor-commit で変更を反映させます。
なお、バッファ内だけのシンボルの同時編集の場合には multiple-cursors を使用しています。

Flycheck

Elpy では構文、コーディングスタイルのチェックには Flymake か Flycheck を使用します。
デフォルトでは Flymake が使われますが、Flycheck を使用する場合は次のように設定しておきます。
(Flycheck を使用するなら Melpa からインストールしておきます。)

(when (require 'flycheck nil t)
  (remove-hook 'elpy-modules 'elpy-module-flymake)
  (add-hook 'elpy-mode-hook 'flycheck-mode))

個人的に Flycheck のキーバインドは次のようにしています。
(helm-flychecksmartrep も Melpa からインストールしておきます。)

(define-key elpy-mode-map (kbd "C-c C-v") 'helm-flycheck)
(require 'smartrep)   
(smartrep-define-key elpy-mode-map "C-c"
  '(("C-n" . flycheck-next-error)
    ("C-p" . flycheck-previous-error)))

C-c C-n (flycheck-next-error) や C-c C-p (flycheck-previous-error) でエラー箇所にカーソルが移動します。
smatrep のおかげで C-n や C-p で連続でジャンプできて便利です。

コードの自動整形

C-c C-r f (M-x elpy-format-code) でバッファ(またはリージョン) のコードを yapf を使って自動整形できます。
また、M-x elpy-autopep8-fix-code で同様に autopep8 によってコードを自動整形できます。
以下のように、yapf の方がきれいに整形されます。

  • 元のコード
x = {  'a':37,'b':42,

'c':927}

y = 'hello ''world'
class foo  (     object  ):
  def f    (self   ):
    return       37*-+2
def f  (   a ) :
  return      37+-+a[42-x :  y**3]
  • yapf で自動整形したコード
x = {'a': 37, 'b': 42, 'c': 927}

y = 'hello ' 'world'


class foo(object):
    def f(self):
	return 37 * -+2


def f(a):
    return 37 + -+a[42 - x:y**3]
  • autopep8 で自動整形したコード
x = {'a': 37, 'b': 42,

     'c': 927}

y = 'hello ''world'


class foo  (object):

    def f(self):
	return 37 * -+2


def f(a):
    return 37 + -+a[42 - x:  y**3]

個人的には使っていませんが、保存と同時にコードを整形したい場合は、Melpa から py-yapf か py-autopep8 を使用します。
例えば py-yapf を Melpa からインストールし、init.el に次の設定をしておきます。

(add-hook 'elpy-mode-hook 'py-yapf-enable-on-save)

インデントのハイライト

highlight-indentation でインデント(字下げ)をハイライトさせています。
ただ、全部のインデントがハイライトされていると見辛いので、カーソル位置のブロックのインデントだけ見えるようにしています。

(set-face-background 'highlight-indentation-face "#313131")
(set-face-background 'highlight-indentation-current-column-face "#777777")
(add-hook 'elpy-mode-hook 'highlight-indentation-current-column-mode)

その他

デバッグには ipdb をインポートし、ipdb を起動させたい箇所で set_trace 関数を呼び出します。

import ipdb
ipdb.set_trace()

最後に、なぜか Anaconda に含まれる curl で twittering-mode が使えなかったので、とりあえず以下のようにして対処しています。

(setq twittering-curl-program "/usr/bin/curl")

Kindle で「Python による科学技術計算 基礎編」 という本を出版しました

表題のとおり、Kindle ストアで電子書籍を出版しました。
(ブログは実に半年ぶりの更新です…)

概要

本の詳細については サポートページ をご覧ください。

タイトルどおりの本で、学生・社会人問わず Python で科学技術計算/数値計算をやりたい方のための入門書です。
MATLAB の解説本とかにあるような、科学技術計算のための Python の日本語書籍ってほとんど無いようだったので書いてみました。
いろいろと細かいことにも言及しているので、辞書的にも使えると思います。

製作環境について

Emacs の Org-mode で書いて LaTeX に出力して PDF を作成し、Kindle Textbook Creator で Kindle 形式に変換しました。
Kindle Textbook Creator は PDF の見た目どおりに Kindle 形式に変換してくれるツールで、これを使えば Kindle 電子書籍を簡単に作れちゃいます。
PDF で目次や索引などもしっかり作っておけば、それらのリンクも自動でばっちり入れてくれます。

また、ob-ipython を使って Org-mode の中で Python コードを評価して埋め込むことができますし、LuaLaTeX のおかげで PDF も作りやすくて非常に捗りました。

確認はしていないのですが、カラーのせいなのか白黒の Kindle 端末では読めないようなのでご注意ください。
文字も多いので、読書方法としてはパソコン(Kindle fo PC)か大きめのタブレット端末を推奨します。

自作リフロー装置の製作 (Raspberry Pi とオーブントースター)

最近電子工作に挑戦し始め Kicad で基板設計をやっているのですが、基板の小型化のために SMD(表面実装部品)を使いたくなりました。
上手な人は SMD でも手はんだできるみたいですが、私にはハードルが高くて断念せざるをえませんでした。
後々まとまった数の基板を作りたいとも思っていたので、リフロー装置を自作してみることにしました。
自作のリフロー装置については「ホームリフロー」とか「自作リフロー装置」で調べるとたくさん作例がでてきます。
Maker の間では基本装備みたいなものなんですね。

パーツリスト

部品は以下の物を使いました。

Table 1: パーツリスト
名称 個数 購入先
TIGER オーブントースター やきたて ぷちはこ 1 Amazon
Raspberry PI B+ 1 秋月
MAX31855 使用 K 型熱電対アンプモジュール 1 秋月
K 型熱電対プローブ 1 秋月
ユニバーサル基板 1 秋月
ソリッド・ステート・リレー(SSR)キット 25A(20A)タイプ 2 秋月
ピンヘッダ 2 × 20(40P) 1 秋月
2 x 20(40P)両端コネクタ付 IDC リボンケーブル 1 秋月
テフロン線 0.3SQ 1 マルツ
耐熱電子ワイヤー 2m × 7 色 1 秋月
その他(プラ足、M3 ねじ、カプトンテープ等) 適宜 秋月

Raspberry PI B+は以前に買って使っていなかったものがあったのを使用しました。
Pi 2 を使っても問題ないはずです。

トースターは置き場所もあまりないので小型のものにしました。
余裕があればファンが付いたものがいいかも。

SSR は定格電流が大きく、作例も多かった秋月のキットにしました。
トースターは上下にヒーターがあり、それぞれを制御できるように SSR を二つ使いましたが、一つで十分だったかもしれません。

かなり簡単な回路なのでユニバーサル基板ではなく小さめのブレッドボードでも良いと思います。

配線は耐熱温度が高いものを選びましょう。

製作

トースター

まずはトースターの背後と底面ででねじ止めされている外装を外します。
下図のようヒーターに繋がるケーブルを外し、SSR を割り込ませます。
圧着端子やラグ端子があると配線がしやすいです。
今回 SSR をスリットを利用してねじ止めしてしましたが、よく考えたら SSR の耐熱温度がわからないので SSR は外に出した方がいいかもしれません。
今の所不具合は起きていませんが劣化が早いかも。最後に外装を元に戻しておきます。
あと電源を入れるのにダイヤルを回すのも面倒なのでスイッチに置き換えたり、ベルは外してもいいかもしれません

oven_inner.png

Figure 1: オーブントースターの配線

基板

Raspberry Pi にアンプを接続します。Adafruit のメーカーページ にアンプを Raspberry Pi で使用する際のマニュアルがあります。ここ の Hardware SPI の通りに接続します。熱電対はコネクタケーズを分解しアンプに接続します。

後はフラットケーブルを Raspberry Pi に接続し、適当な GPIO に SSR を接続します。今回はヒューズとか保護回路は付けてませんが、できれば付けた方がいいです。

PCB_151006.png

Figure 2: 基板

プログラム

まずは Raspberry Pi に OS などの基本的な設定をし、Python で GPIO を操作できるようにしておきます。
次に ここ からアンプ用のライブラリをダウンロードしてインストールします。
Raspian なら Python はインストールされているはずです。
Python3 で使う場合は sudo python3 setup.py install とします。

制御プログラムは以下のようなものを作りました。
Python3 で書いてるのでターミナルから sudo python3 main.py として実行します。
測定中は目標値等を表示するようにし、測定データは csv 形式で保存するようにしています。

PID 制御のクラスは ここ から拝借しました。
本来はオーブンの熱容量とか放熱量をモデル化するといいんでしょうけど、適当に制御パラメータを設定しただけでも問題なくリフローできました。
まあ鉛入りはんだでしか試してないので問題が起きてないだけかも知れないので、問題が起きればちゃんと制御系を作ります。

ちなみに制御パラメータの設定は応答の遅い系では限界感度法等ではうまくいきにくいです。
そこでパラメータは簡単にトライアンドエラーで調整しました。
まず目標温度を 180 ℃あたりにして P だけでオーバーシュートしない程度の値を探します。
次に序々に I を上げていき偏差が小くなるようにし、最後に D を加えるのと P と I の微調整をしました。

温度プロファイルは適当に検索するといっぱい出てきます。
それらを参考にトースターの性能に合わて微調整してものを設定しました。

# coding: utf-8
import RPi.GPIO as GPIO
import time
import csv
import Adafruit_GPIO.SPI as SPI
import Adafruit_MAX31855.MAX31855 as MAX31855

GPIO.cleanup()

# SSR 操作の GPIO 設定
# 上:16, 下:18
PIN1 = 16
PIN2 = 18
GPIO.setmode(GPIO.BOARD)
GPIO.setup(PIN1, GPIO.OUT)
GPIO.setup(PIN2, GPIO.OUT)
p1 = GPIO.PWM(PIN1, 50)
p2 = GPIO.PWM(PIN2, 50)
p1.start(0.0)
p2.start(0.0)

# Raspberry Pi のハードウェア SPI 設定
SPI_PORT = 0
SPI_DEVICE = 0
sensor = MAX31855.MAX31855(spi=SPI.SpiDev(SPI_PORT, SPI_DEVICE))

# 温度プロファイル、PID 制御パラメータ設定()
# 外気温 26 ℃
sp = [[120.0, 60],
      [170.0, 110],
      [225.0, 150],
      [0.0, 210]]               # 目標値(℃), 終了時刻(s)を設定
Kp = 2.0
Ki = 0.06
Kd = 1.0

# 制御間隔(s)
delay_time = 0.1


# PID 制御のクラス
class PID:
    def __init__(self, P=2.0, I=0.0, D=1.0, Derivator=0, Integrator=0, Integrator_max=500, Integrator_min=-500):
	self.Kp = P
	self.Ki = I
	self.Kd = D
	self.Derivator = Derivator
	self.Integrator = Integrator
	self.Integrator_max = Integrator_max
	self.Integrator_min = Integrator_min
	self.set_point = 0.0
	self.error = 0.0

    def update(self, current_value):
	self.error = self.set_point - current_value

	self.P_value = self.Kp * self.error

	self.D_value = self.Kd * (self.error - self.Derivator)
	self.Derivator = self.error

	self.Integrator = self.Integrator + self.error

	if self.Integrator > self.Integrator_max:
	    self.Integrator = self.Integrator_max
	elif self.Integrator < self.Integrator_min:
	    self.Integrator = self.Integrator_min

	self.I_value = self.Integrator * self.Ki

	PID = self.P_value + self.I_value + self.D_value
	return PID

    def setPoint(self, set_point):
	self.set_point = set_point

    def setIntegrator(self, Integrator):
	self.Integrator = Integrator

    def setDerivator(self, Derivator):
	self.Derivator = Derivator

    def setKp(self, P):
	self.Kp = P

    def setKi(self, I):
	self.Ki = I

    def setKd(self, D):
	self.Kd = D

    def getPoint(self):
	return self.set_point

    def getError(self):
	return self.error

    def getIntegrator(self):
	return self.Integrator

    def getDerivator(self):
	return self.Derivator


def control(p):
    pid.setPoint(p)

    current_temp = sensor.readTempC()
    internal = sensor.readInternalC()
    mv = pid.update(current_temp)

    if mv >= 100:
	mv = 100
    elif mv <= 0:
	mv = 0

    p1.ChangeDutyCycle(mv)
    p2.ChangeDutyCycle(mv)

    print("target:", pid.getPoint())  
    print("current:", current_temp)
    print("internal:", internal)
    print("mv:", mv)

    w.writerow([time.time(), current_temp, internal, mv])

    time.sleep(delay_time)


try:
    pid = PID()
    pid.setKp(Kp)
    pid.setKi(Ki)
    pid.setKd(Kd)

    f = open('data.csv', 'w')
    w = csv.writer(f)

    t0 = time.time()
    timeout1 = t0 + sp[0][1]
    timeout2 = t0 + sp[1][1]
    timeout3 = t0 + sp[2][1]
    timeout4 = t0 + sp[3][1]

    while True:
	if time.time() < timeout1:
	    print("\nPhase1")            
	    control(sp[0][0])
	elif time.time() < timeout2:
	    print("\nPhase2")                        
	    control(sp[1][0])
	elif time.time() < timeout3:
	    print("\nPhase3")                                    
	    control(sp[2][0])
	elif time.time() < timeout4:
	    print("\nPhase4")                                    
	    control(sp[3][0])
	else:
	    break

except KeyboardInterrupt:
    print("detect key interrupt\n")


GPIO.cleanup()
f.close()
print("Program exit\n")

テスト

適当な QFN パッケージの IC と aitendo のピッチ変換基板でテストしました{電子工作}QFN パッケージのハンダ付けについて を参考にさせて頂きました。
クリームはんだはサンハヤトの SMX-H05 を使いました。
マスクがないので爪楊枝等で大雑把に盛ったため盛大にブリッジしました。
吸い取り線でブリッジを修正してみると問題なくはんだが付いていました。
IC の位置もはんだの表面張力で適切な位置に動いたようで問題ありませんでした(写真が悪くてダメですね。ちゃんとカメラ買おう。。。)

result_before_151006.png

Figure 3: はんだ付け結果(ブリッジ修正前)

result_after_151006.png

Figure 4: はんだ付け結果(ブリッジ修正後)

最後に測定データを示します。
ちゃんど温度が制御できています。
鉛入りはんだだともう少し温度が低い方が良いですね。
また、最後の加熱はもっと一気に加熱した方が良さそうです。
鉛フリーはんだでテストする時にでも調整しようと思います。

# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt

t, y, internal, mv = np.loadtxt("data.csv", unpack=True, delimiter=",")

plt.figure()
plt.plot(t-t[0], y)
plt.xlim([0, max(t-t[0])])
plt.xlabel("Time[s]")
plt.ylabel("Temperature[C]")
plt.grid()
plt.show()

reflow_result.png

Figure 5: 温度測定結果

Intel Edison のファームウェアの更新手順(Ubuntu)

Intel Edison を購入しました。さっそく Ubuntu マシン でファームウェアを更新しようとしたら嵌ったので覚え書き。

Intel Edison を手に入れたらやること(Linux の場合) に従って reboot ota を実行しても、なぜか更新が始まりませんでした。
いろいろ調べて Intel Edison で Web カメラを有効にし mjpg-streamer で映像を配信してみた にあった手順を試してみると、すんなり更新できました。

手順

まずは以下のコマンドで dfu-util をインストールしておきます。

sudo apt-get install dfu-util

次に Intel ® Edison Board Software Downloads から Yocto complete image をダウンロードします(2015 年 8 月 5 日の時点では edison-image-ww25.5-15.zip)。

そしてファイルのダウンロード先に移動して以下のコマンドを実行し、Edison とホスト PC を接続するとファームウェアが更新されます。

mkdir edison-image-ww25.5-15
cd edison-image-ww25.5-15
unzip ../edison-image-ww05-15.zip
sudo ./flashall.sh
書籍更新情報
2017-01-16
Pythonによる科学技術計算 基礎編
1.3版への更新が可能になりました。
サポートページはこちら
電子書籍
Pythonによる科学技術計算 基礎編
Kindle ストアで販売中です
Pythonによる科学技術計算 基礎編
同人誌
技術書典(2016/6/25)
Emacs/org-modeのPDF作成術
電子版をBOOTHで販売中です
Emacs/org-modeのPDF作成術
Share