OpenCV野良ビルド時にCMakeが指定したPythonのライブラリをうまく見つけてくれない時は

OpenCVをPythonサポート込みでビルドしたいことがあります。
Python側へインタフェースを露出するためのヘッダなどが必要なので、いくつかのPython関連パッケージを入れれば、あとはシンプルにCMakeを実行すればよいことがほとんどです。
(そのやり方はネットにたくさんまとまっているので他をご参照ください)

% sudo apt-get install python2.7-dev python3.4-dev #などなど。
% cd /path/to/opencv/source/root
% mkdir build; cd build
% cmake -DBUILD_opencv_python2=ON -DBUILD_opencv_python3=ON ..

一方で、rootがないなどの状況でpython2.7-devなどのパッケージがシステムにない場合は、例えばpyenvを使って一時的にpythonをユーザ環境に入れそのパスを参照させることで、Python対応こみでビルドすることが可能です。
(ビルドがおわったら一時的に入れたPython環境は消してOKです)

% pyenv install miniconda2-latest
% pyenv install miniconda3-latest
% cmake -DCMAKE_BUILD_TYPE=RELEASE -DCMAKE_INSTALL_PREFIX=$HOME \
        -DBUILD_opencv_python2=ON \
        -DPYTHON2_EXECUTABLE=`pyenv local miniconda2-latest; pyenv which python` \
        -DPYTHON2_INCLUDE_DIR=`pyenv local miniconda2-latest; python -c 'from distutils.sysconfig import get_python_inc; print(get_python_inc())'` \
        -DPYTHON2_NUMPY_INCLUDE_DIRS=`pyenv local miniconda2-latest; python -c 'import numpy; print(numpy.get_include())'` \
        -DPYTHON2_LIBRARIES=`find $PYENV_ROOT/versions/miniconda2-latest/lib -name 'libpython*.so'` \
        -DBUILD_opencv_python3=ON \
        -DPYTHON3_EXECUTABLE=`pyenv local miniconda3-latest; pyenv which python` \
        -DPYTHON3_INCLUDE_DIR=`pyenv local miniconda3-latest; python -c 'from distutils.sysconfig import get_python_inc; print(get_python_inc())'` \
        -DPYTHON3_NUMPY_INCLUDE_DIRS=`pyenv local miniconda3-latest; python -c 'import numpy; print(numpy.get_include())'` \
        -DPYTHON3_LIBRARIES=`find $PYENV_ROOT/versions/miniconda3-latest/lib -name 'libpython*.so'` \
        ..

このとき、CMakeを走らせたときの序盤にこんなメッセージが出たり(PythonLibsを見つけられてなかったり、意図したのと違うものを見つけに行ってる)、

 -- Found PythonInterp: /home/xxxx/.pyenv/versions/miniconda2-latest/bin/python (found suitable version "2.7.14", minimum required is "2.7")
 -- Found PythonLibs: /usr/lib/x86_64-linux-gnu/libpython2.7.so (found suitable exact version "2.7.14")
 -- Found PythonInterp: /home/xxxx/.pyenv/versions/miniconda3-latest/bin/python (found suitable version "3.6.3", minimum required is "3.4")
 -- Could NOT find PythonLibs (missing:  PYTHON_LIBRARIES PYTHON_INCLUDE_DIRS) (found suitable exact version "3.6.3")

CMakeの最後の結果表示のときにこんなメッセージが出たり(LibrariesがNO)、

 --   Python 2:
 --     Interpreter:                 /home/xxxx/.pyenv/versions/miniconda2-latest/bin/python (ver 2.7.14)
 --     Libraries:                   NO
 --     numpy:                       /home/xxxx/.pyenv/versions/miniconda2-latest/lib/python2.7/site-packages/numpy/core/include (ver 1.14.0)
 --     packages path:               lib/python2.7/site-packages
 --
 --   Python 3:
 --     Interpreter:                 /home/xxxx/.pyenv/versions/miniconda3-latest/bin/python (ver 3.6.3)
 --     Libraries:                   NO
 --     numpy:                       /home/xxxx/.pyenv/versions/miniconda3-latest/lib/python3.6/site-packages/numpy/core/include (ver 1.14.0)
 --     packages path:               lib/python3.6/site-packages

正しく指定したはずのライブラリのパスをCMakeがどうも認識してくれない様子のときは、CMakeのバージョンを疑ってみてください

% cmake --version
cmake version 2.8.12.2

2.8系では、うまくPythonのライブラリをみつけてくることができないようです。
OpenCVの提供するCMakeLists.txtのcmake_minimum_requiredは(Linuxであれば)2.8になっているので、特に怒られることなく進んでしまう、というのが罠でした(今回取り上げたかなり限定的なシチュエーション以外ではそれで問題なく動くためです)。

特にUbuntu14.04をまだ使っていたりした場合は、標準でapt-getしたものは2.8までになります。
野良ビルドするなり、PPAにするなり、新しいUbuntuに乗り換えるなりするといいです。

自分用メモ。

tmuxのセッション作成時に名前付けを強制するzshrc

魚を飼う時、繁殖をさせやすいのはグッピーやアカヒレなどだそうです。数匹のつがいがいればすぐに数百匹まで増えてしまうんだとか。

さて、tmuxヘビーユーザーなんですがセッションが乱立しがちで、外からsshして既存セッションをattachするときにどれがどれかわからないことが個人的にはよくあります。
セッション内の任意のウィンドウもしくはペインでtmux rename-sessionをすることでセッション全体に名前をつけることができ、attachするときこの名前で参照することができて便利です。
これを、セッション作成時に自動で聞くようにしてみました。

やりたいこと

  • tmuxでセッションを作ったあと最初のウィンドウが開かれる時、そのセッションに名前をつけるのを強制したい
  • 何も入力しないことも許容する。その場合は名前付けしない

やりたくないこと

  • 名前付けしなかった場合、セッション内で新たなウィンドウやペインを開く度にまた聞かれたくない

やってることは単純で、zshが起動した時それがtmuxセッション内でかつセッション名がデフォルト(数字のみ)のままである場合、名前の入力を求めtmux rename-sessionコマンドを呼ぶだけです。
何も入力しない場合はセッション名はデフォルトのまま放置しますが、そのままだとセッション内で新たなshellを開く度にプロンプトが出て鬱陶しいので、それが出ないようtmuxのsession-wideな環境変数を使いマークしています。シェル環境変数にマークした場合引き継がれないのでうまくいきません。

tmux 2.2(Mac)と2.1(Ubuntu)で確認しています。

てきとうに書いたのでもっとCOOLなやり方もあると思いますが、ひとまずこんなかんじで。

Firefox QuantumでTree Style Tabを使う時タブバーを消したかった

マッコウクジラは鯨の中でも特に深海に特化した進化をしていて、海面で息継ぎをしてから3000メートルを一気に潜ってしまうそうです。頭部にびっしり詰まっている脳油を海水と血液で冷やしたりし温めたりて比重を変えることで潜ったり浮いたりする様は、潜水艦よりも高度とさえ言えるのかもしれない。

さて、最近爆速になって登場したFirefox Quantumを使っているのですが、WebExtension版のTree Style Tabを使っていても画面上の方にタブバーが一緒に出てきてしまって邪魔でした。

基本的には
Firefox Quantum(57以上)で上部のタブバーを消す – Qiita
の通りなのですが、それだけだとなぜか動かなかったので、もう少し調べた結果出てきたこちら
Firefox Quantum (ver >= 57) – How Can I Hide the Horizontal Tab Bar with TreeStyle Tabs? – Super User
を適用すると動きました。

合わせると、新規作成するuserChrome.cssには次のような内容を書けばOKです。

@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul");
#tabbrowser-tabs {
  visibility: collapse !important;
}
#sidebar-header {
  visibility: collapse;
}

Macだとちょっとだけウィンドウのタイトルバー?がおかしいですが、困るものではないのでまぁいいでしょう。

完全に自分用メモ。

Dashにchainerのドキュメントを登録する

魚について調べる時、(Wikipediaもいいんですが)FishBase : A Global Information System on Fishesとかは結構分量も凄くて、英語中心ですがときどき役に立ちます。

さて、Macを3年ぐらい使ってきてて恥ずかしながらわりと最近までドキュメントのインクリメンタルサーチができるDashを知らなかったんですけども、ちょっと前から使うようになりました。仕事や趣味でChainerを使うんですが、ChainerのドキュメントはDashで提供されてないので、自分でドキュメントをDash用に変換する必要があります。

とは言えChainerはSphinxでドキュメントが書かれているので、doc2dashというpipを使えば一発でできます。

なのですごい簡単なんですが、環境を新しくする度にやり方を調べてやってる気がするので、メモ。
別にchainer限定ではなくて他の何にでも当てはまる一般的な話なんですが、あえてchainer specificな話題にしてみました。

# 準備。doc2dashを入れる。
% pip install doc2dash

# Cloneしてくる
% git clone https://github.com/pfnet/chainer.git --branch v2.0.0
% cd chainer/docs

# Optional: アイコンに使う画像をダウンロードしてくる。ここではTwitterから。
% wget https://pbs.twimg.com/profile_images/606654945438203905/D7LygzpN_400x400.png -O chainer_logo.png

# ドキュメントをビルドし、dash形式に変換
% make html
% doc2dash build/html -n chainer2 -i chainer_logo.png
# % doc2dash build/html -n chainer2   #アイコンが不要な場合

これを実行すると、chainer2.docsetというディレクトリが生成されます。Sphinx等はもちろん入っている必要があるので、怒られた場合は指示に従って入れてください。
Dashをインストール済みのMacでFinderにてこのディレクトリをダブルクリックすると、検索できるドキュメントとして追加されます。

ぼくの場合手元のMacだと、2017/7/3現在でのmasterのときsphinxのビルド(上記のmake html)がこんなかんじで失敗することがあったので、Linux環境でmakeしました。また、いきなりmake htmlするとエラーで死ぬんですがmake dirhtmlしてからmake htmlすると通ることも度々ありました。ちょっと謎。

% make dirhtml
...
...
reading sources... [ 76%] reference/generated/chainer.links.StatelessLSTM
reading sources... [ 76%] reference/generated/chainer.links.VGG16Layers
reading sources... [ 76%] reference/generated/chainer.links.caffe.CaffeFunction
reading sources... [ 77%] reference/generated/chainer.links.model.vision.googlenet.prepare
reading sources... [ 77%] reference/generated/chainer.links.model.vision.resnet.ResNetLayers
reading sources... [ 77%] reference/generated/chainer.links.model.vision.resnet.prepare
reading sources... [ 77%] reference/generated/chainer.links.model.vision.vgg.prepare
reading sources... [ 78%] reference/generated/chainer.optimizers.AdaDelta
/Users/hoge/Work/chainer/chainer/docs/source/reference/check.rst:30: WARNING: failed to import chainer.gradient_check.check_backward
/Users/hoge/Work/chainer/chainer/docs/source/reference/check.rst:30: WARNING: failed to import chainer.gradient_check.numerical_grad
/Users/hoge/Work/chainer/chainer/docs/source/reference/check.rst:30: WARNING: toctree references unknown document 'reference/generated/chainer.gradient_check.check_backward'
/Users/hoge/Work/chainer/chainer/docs/source/reference/check.rst:30: WARNING: toctree references unknown document 'reference/generated/chainer.gradient_check.numerical_grad'
/Users/hoge/Work/chainer/chainer/docs/source/reference/check.rst:43: WARNING: failed to import chainer.testing.assert_allclose
/Users/hoge/Work/chainer/chainer/docs/source/reference/check.rst:43: WARNING: toctree references unknown document 'reference/generated/chainer.testing.assert_allclose'
/Users/hoge/Work/chainer/chainer/docs/source/reference/check.rst:53: WARNING: failed to import chainer.testing.unary_math_function_unittest
/Users/hoge/Work/chainer/chainer/docs/source/reference/check.rst:53: WARNING: toctree references unknown document 'reference/generated/chainer.testing.unary_math_function_unittest'
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.Chain.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.ChainList.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.Link.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/Work/chainer/chainer/docs/source/reference/core/optimizer.rst:4: WARNING: failed to import chainer.Hyperparameter
/Users/hoge/Work/chainer/chainer/docs/source/reference/core/optimizer.rst:4: WARNING: toctree references unknown document 'reference/core/generated/chainer.Hyperparameter'
WARNING: /Users/hoge/Work/chainer/chainer/docs/source/reference/datasets.rst:57: (WARNING/2) autodoc: failed to import class 'ConcatenatedDataset' from module 'chainer.datasets'; the following exception was raised:
Traceback (most recent call last):
  File "/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/sphinx/util/inspect.py", line 169, in safe_getattr
    return getattr(obj, name, *defargs)
AttributeError: module 'chainer.datasets' has no attribute 'ConcatenatedDataset'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/sphinx/ext/autodoc.py", line 664, in import_object
    obj = self.get_attr(obj, part)
  File "/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/sphinx/ext/autodoc.py", line 554, in get_attr
    return safe_getattr(obj, name, *defargs)
  File "/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/sphinx/util/inspect.py", line 185, in safe_getattr
    raise AttributeError(name)
AttributeError: ConcatenatedDataset
/Users/hoge/Work/chainer/chainer/docs/source/reference/functions.rst:30: WARNING: failed to import chainer.functions.tree_lstm
/Users/hoge/Work/chainer/chainer/docs/source/reference/functions.rst:30: WARNING: toctree references unknown document 'reference/generated/chainer.functions.tree_lstm'
/Users/hoge/Work/chainer/chainer/docs/source/reference/functions.rst:216: WARNING: failed to import chainer.functions.layer_normalization
/Users/hoge/Work/chainer/chainer/docs/source/reference/functions.rst:216: WARNING: toctree references unknown document 'reference/generated/chainer.functions.layer_normalization'
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.BatchNormalization.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Bias.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Bilinear.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.BinaryHierarchicalSoftmax.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.BlackOut.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.CRF1d.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Classifier.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Convolution2D.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.ConvolutionND.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Deconvolution2D.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.DeconvolutionND.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.DepthwiseConvolution2D.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.DilatedConvolution2D.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.EmbedID.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.GRU.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.GoogLeNet.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Highway.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Inception.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.InceptionBN.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.LSTM.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.LayerNormalization.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Linear.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.MLPConvolution2D.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Maxout.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.NStepBiGRU.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.NStepBiLSTM.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.NStepBiRNNReLU.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.NStepBiRNNTanh.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.NStepGRU.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.NStepLSTM.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.NStepRNNReLU.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.NStepRNNTanh.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.NegativeSampling.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.PReLU.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.ResNet101Layers.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.ResNet152Layers.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.ResNet50Layers.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.Scale.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.SimplifiedDropconnect.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.StatefulGRU.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.StatefulPeepholeLSTM.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.StatelessLSTM.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.VGG16Layers.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.caffe.CaffeFunction.init_scope:19: WARNING: Unexpected indentation.
/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/link.py:docstring of chainer.links.model.vision.resnet.ResNetLayers.init_scope:19: WARNING: Unexpected indentation.
Exception occurred:
  File "/Users/hoge/.pyenv/versions/3.6.1/lib/python3.6/site-packages/chainer/optimizer.py", line 598, in __get__
    return getattr(obj.hyperparam, self._attr_name)
AttributeError: 'NoneType' object has no attribute 'hyperparam'
The full traceback has been saved in /var/folders/y1/tp8l6j7n67bgbz8tpm0_05b40000gn/T/sphinx-err-6hlmrj53.log, if you want to report the issue to the developers.
Please also report this if it was a user error, so that a better error message can be provided next time.
A bug report can be filed in the tracker at <https://github.com/sphinx-doc/sphinx/issues>. Thanks!
make: *** [dirhtml] Error 1

また、DashのWindows/Linux版であるZealを使っている場合、上記の手順でビルドしてできたchainer2.docsetディレクトリを、Zealのdocsetsディレクトリに入れることでZealに見えるようになります。

% mv chainer2.docset ~/.local/share/Zeal/Zeal/docsets/

(docsetsディレクトリの場所は環境によって異なる可能性があります。optionsで確認できます)

✌(‘ω’✌ )三✌(‘ω’)✌三( ✌’ω’)✌たのしい!

なお、後になってDash-User-ContributionにChainerがあることを知った…
https://github.com/Kapeli/Dash-User-Contributions/tree/master/docsets/Chainer
常に自分の責任で最新に追従させたいわけじゃなければ、これで十分。メンテナのmitmulさんは同僚ですw

tqdmをムリヤリprocess safeっぽくするdirty hack

生物界で最大の目(光を検知する器官)を持っているのはダイオウイカおよびダイオウホウズキイカと言われ、その大きさは30〜35cmほどにもなるのだそうです。

さて、世界70億人のPythonプログラマが手放せないのが、tqdmというプログレスバーを簡単に表示できるようにしてくれるライブラリです。
しかしながらtqdmは(当然と言えば当然ですが)複数のプロセスから1つのプログレスバーを管理することができるような設計にはなっていません。
たとえば高速化のためにmultiprocessingを用いて並列処理をしながらプログレスバーを出したいとき、tqdmはそのままでは使えないことになります。

例えば、下記のようなコードで単にtqdmのインスタンスを子プロセスに渡して中でupdateをすると…

import tqdm
import multiprocessing

def worker(pbar):
    pbar.update()

ar = [i for i in range(100)]
with tqdm.tqdm(ar) as pbar:
    jobs = []
    for t in ar:
        job = multiprocessing.Process(target=worker, args=(pbar,))
        job.start()
        jobs.append(job)
    for job in jobs:
        job.join()

実行結果はこんな感じ。

% python usage.py
  1%|▉                                                                                                 | 1/100 [00:00<00:25,  3.89it/s]

こんなふうに、100%まで行ってくれません。
端的に説明すると、100個forkされた内部カウント0の状態をそれぞれ+1するのが100回走るだけ、だからです。

じゃあ内部カウントが常によろしく増えるために、内部カウントを無視して共有メモリで常に正しくカウントしてればいいよね、っていう単純な発想による汚いハックをしてみました。

Continue reading

大量のサーバに同じファイル(でかい)を効率的にコピーする

インド洋では、夏頃にイワシの大群が押し寄せるサーディンラン現象というのがあるのだそうです。その個体数、にわかには信じがたいですが億のオーダーにもなるとのことです。すげーな!

さて、あるサーバ1台が数百GBにもなる巨大なファイル(群)を持っているとします。
このファイル群を、そのサーバに接続された他の複数(大量)のサーバのローカルディスクにコピーしたいです。
以後これを便宜的にbcast cpと呼ぶことにします。

rsyncを1台ずつ回すのが頭悪い方法なのは明らか。当然NFSなどを立てて共有するというのも本質的にはそれと同じ。
同僚のiwiwiさんがちょうど集団通信アルゴリズムの話をしていたのを聞いて、それを活用して効率的にファイルをバラまくようなアドホックなスクリプトを書いて、ときどき使えそうなのでまとめておきました。

「やってみた」ぐらいの話なのでガチ勢の方たちにはƱ”-ʓ飲んで寝ていてほしいです。

Continue reading

pythonでlistを(なるべく)均等分割するスニペット

魚類というのは世界で20000種が報告されているんだそうですが、もちろん実際にはこれより遥かに多くの種が存在すると思われているそうです。食べられる魚だけでも一体何種いるんでしょう。

さて、Pythonでリストをあるk個のリストへなるべく均等に分割したい…というようなことが頻繁ではないけどたまーに欲しくなって、その都度何分かかけて書いてる(でときどきバグ作り込む)気がするのでスニペットとしてメモ。

やりたいこと。

 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

…というような長さ12の配列を5分割する。

[ [0, 1], [2, 3], [4, 5, 6], [7, 8], [9, 10, 11] ]

何のことはありません。

def split_array(ar, n_group):
    for i_chunk in range(n_group):
        yield ar[i_chunk * len(ar) // n_group:(i_chunk + 1) * len(ar) // n_group]

Python2なら割り算のところは//でなく/でおk。

リストを受け取ればリストを返すし、rangeを受け取ればrangeを返します。

> [list(r) for r in split_array(range(12), 5)]
[ [0, 1], [2, 3], [4, 5, 6], [7, 8], [9, 10, 11] ]

1982798万番煎じぐらいだとおもう。

MacにRMagickが入らなくてつらい人へ

大型淡水魚のピラルクーはとても特徴的な大きな鱗をもち、その硬さもあって、靴べらなどに利用されることさえあるのだそうです。

さて、Mac(El Capitan)にGemでRMagickを入れようとしたとき、

% gem install rmagick

こんなエラーで死にました。

Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

    /Users/hogehoge/.rbenv/versions/2.2.0/bin/ruby -r ./siteconf20170218-46131-rbo6q5.rb extconf.rb
checking for clang... yes
checking for Magick-config... no
checking for pkg-config... yes
checking for outdated ImageMagick version (<= 6.4.9)... no
checking for Ruby version >= 1.8.5... yes
checking for stdint.h... yes
checking for sys/types.h... yes
checking for wand/MagickWand.h... no

Can't install RMagick 2.15.4. Can't find MagickWand.h.
 *** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of necessary
libraries and/or headers.  Check the mkmf.log file for more details.  You may
need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=/Users/hogehoge/.rbenv/versions/2.2.0/bin/$(RUBY_BASE_NAME)

extconf failed, exit code 1

Gem files will remain installed in /Users/hogehoge/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/gems/rmagick-2.15.4 for inspection.
Results logged to /Users/hogehoge/.rbenv/versions/2.2.0/lib/ruby/gems/2.2.0/extensions/x86_64-darwin-15/2.2.0-static/rmagick-2.15.4/gem_make.out

An error occurred while installing rmagick (2.15.4), and Bundler cannot continue.
Make sure that `gem install rmagick -v '2.15.4'` succeeds before bundling.

基本的にはこちらで書かれているような、pkg-config周りをちゃんとするようというようなのがよく引っかかります。
Mac OS X環境にrmagickをインストールする決定版 – Qiita

僕の場合はまた違う現象でした。
結論から言うと、新しいImageMagick7.xがシステムに入ってるとダメで、6.x系列を入れる必要がありました

% brew uninstall --ignore-dependencies --force imagemagick
% brew install imagemagick@6 && brew link imagemagick@6 --force
% gem install rmagick

この答えは、こちらのStackOverflowで発見しました。
ruby – RMagick installation: Can't find MagickWand.h – Stack Overflow

こういうので時間を溶かすのがいちばんつらいですね。

UbuntuでOpenCVをlibjpeg-turboつきでビルドする

都道府県別の一人あたり魚介類消費量では、青森県がトップで、以下秋田、鳥取、新潟、富山と日本海側の県が続きます。島国・沖縄が意外にも最下位です。

さて、OpenCVで画像をロードするのを速くしたくて、JPEGについてはlibjpeg-turboというのが使えることを知りました。
libjpeg-turboはlibjpegをSIMDなどによって高速化したものでAPIレベルの互換性を保っています。
条件が良ければデコードが数倍速くなるということで、これをOpenCVに組み込んでビルドする方法をメモ。

Continue reading

YouTube Data API V3とgoogle-api-ruby-client gemでYouTube動画検索

この度2017年1月1日を迎えました。神戸港開港150年であり、神戸港に建つ巨大な魚のオブジェ「フィッシュ・ダンス」が公開されて30年でもあります。神戸港には縁もゆかりもありません。

さて、自作サービス(Rails製)の裏側においてYouTubeでの動画検索をしたいと考えていて、YouTube Data API(V3)およびそれを叩くGoogle製のgoogle-api-ruby-client gemを使うことにしました。
しかしながらこのGemは2016年初頭に出た0.9によって大きな変更が入り、公式のものを含めネット上で閲覧可能なサンプルのほとんどが参考にならない状況になっています。
自分でも少し苦労したので、かんたんにメモ。

情報は2017年1月1日JST現在、Gemは0.9.20です。

Continue reading