にせねこメモ

はてなダイアリーがUTF-8じゃないので移ってきました。

sshでログインした先で、ログアウトしてもコマンドの実行が継続されるようにする: screenコマンド

sshでログインしている先のLinuxで、終了まで長い時間がかかるDNNの学習などの処理を実行し、後はログアウトして終了を待つ、ということがしたかったので、どうすればいいのか調べたメモ。


バックグラウンド実行しただけではログアウトすると終了してしまう。
nohupを使用しても、ログアウト時に終了されてしまう。

screenコマンド

どうやらscreenコマンドを使用するといいらしい。
screenは仮想的な端末を作成することができるコマンドで、作成した仮想端末は必要に応じて付け替えて使え、さらにログアウトしても保持されるらしい。
詳しい使い方は以下のサイトを参照。
qiita.com
asayamakk.hatenablog.com

suでユーザを切り替えた場合

ただし、screenコマンドはsuでユーザを切り替えている場合、ターミナルが開けないとエラーを吐く。
ログインしたユーザに対し擬似ターミナルが作成されているため、ユーザを切り替えた先ではターミナルが無く、scriptコマンドを実行して擬似ターミナルを無理やり作成しないといけないとのこと。


あるいは、suによってユーザを切り替えるのではなく、初めからそのユーザでログインすればこの問題は起こらない。

sshで接続した先でmatplotlibなどがエラーを吐く

qiita.com

ssh接続した先でpythonからmatplotlibを扱うと$DISPLAY環境変数がないよって怒られる

_tkinter.TclError: no display name and no $DISPLAY environment variable

なので、

env DISPLAY=:0 python hoge.py

みたいにして実行するといいらしい。

現在時刻のglobal date and time stringを生成する

HTML5では、時間を指定するための<time>要素があり、また<del>要素などではdatetime属性によって時間を指定できる。これは編集履歴を残すのに都合がよい。

ここに指定するのは、有効なglobal date and time stringでなければならない。

例えば、

2017-03-15T20:53:45+09:00

とすると、2017年3月15日の20時53分45秒、タイムゾーン+09:00(=日本時間)ということになる。


ときどき現在時刻がこの形で欲しくなるので、このdatetimeに指定するための文字列を自動生成するようなものを作っておく:

UTC版:
タイムゾーン版:

ScanSnap S1300iで自炊を試す

ScanSnap S1300iを買って手元の書類とかをスキャンしてたのだけれど、本も断裁すればスキャンできるなあというので、NHKラジオ講座のテキストを捨てる前にスキャンしてみることにした。


これをスキャンする。
f:id:nixeneko:20170308230708p:plain


まずカッターマット、カッター、定規を用意し、
f:id:nixeneko:20170308230920p:plain

背から2 mmくらいのところに定規を当てて固定し、カッターで何度もなぞりながら切っていく。
f:id:nixeneko:20170308231055p:plain

背から1 mm程度だと接着している糊だけ落とす感じで、紙は部分的にくっついていて、ばらばらにはならない。2mm切断するとページの大部分がバラバラになるので、2 mm位が適切だろうと思う。


f:id:nixeneko:20170308231545p:plain
糊が残っていて紙同士がくっついている場合があるので、ばらばらになっていることを確認しつつ、くっついているところがあればはがしていく。
特に、表紙の隣のページはしっかりくっついているのではがさないといけない。はがさないでScanSnapに投入した場合、紙送りに失敗する。


f:id:nixeneko:20170308232005p:plain
断裁した本をセットする。S1300iは一度にセットできるのが10枚程度ということになっているが、20枚くらいセットしても大抵はちゃんと紙送りしてくれる。紙の状態が悪いと重送が発生するので気を付けないといけないが。
一度に全部をセットできないので、スキャンが進むにつれて原稿を注ぎ足し注ぎ足ししていくか、あるいは何回かに分けてスキャンしたものをAcrobat Proなどで一枚のPDFに結合する必要がある。


断裁~スキャンにかかる時間は一冊当たり15分ほど。
本格的に自炊するのであれば、2万円ほど上乗せして、スキャン速度も速く一度にセットできる枚数も多い上位機を購入すべきだと思う。カッターで切れるのはこのくらいの厚さが限度だと思うので、厚い本をスキャンするつもりであれば断裁機を買わなければならなさそう。

8mmフィルムの白リーダを買う

現像した8mmフィルムの最初についてる白いリーダ部分が映写機の不調なオートローディングに巻き込まれズタズタになってしまったので、代わりの白リーダを探していた。欲しいのはシングル8用であるが、スーパー8用のものも穴の形や幅が同じなので利用できる。

一応、レトロ通販でも扱っているのだが、420円/mとかなり高価である。



情報をいただいたところ、海外のサイトで通販しているらしい。50 ftで5.00 USDとお安い。ただし国際発送はFedEx使うらしく、60 USD程度はかかるっぽかった。これでは明らかにレトロ通販で買う方が安いのでよろしくない。


という訳でeBayで探すことにした。“8mm film leader”などと検索するとそこそこ出てくる。super 8用のものを選ぶ(regular 8…ダブル8用のものは穴の形が違うので使えないので注意する)。
送料も表示されるので、安そうなところを選んで購入したら24 USD、三千円以下で購入することができた。あとは発送され届くのを待つのみ。

クレジットカードで決済しようとしたら“The card you entered cannot be used for this payment. Please enter a different credit or debit card number.”とエラーがでてうまく決済できなかった。調べたらすでにPaypalアカウントに登録しているクレジットカードでは使えないという情報があり、Paypalを使って決済を行ったらうまくいった。あるいは住所の入力ミスかもしれないが(順番が違った)。


eBayで購入したお店は独自のWebショップを持ってて、そっちでも買えるらしい。安いかどうかは確認していないけれど、いろいろな商品がある模様。リンクを貼っておく。
filmforevermpe.com


f:id:nixeneko:20170306224541p:plain
一週間ほどで到着した。配送はUSPSの国際郵便。数個一緒に配送しても送料は変らなそうなので、多めに買っておいて必要な人で分けるとかするといいのかもしれない。

f:id:nixeneko:20170306224819p:plain

好きな形にボケるレンズ

f:id:nixeneko:20170225235837p:plain
一眼レフカメラのボケの形を様々に変えて遊んでみたいという話です。

はじめに

一眼レフカメラなどの大きな受光面(センサー)をもつカメラでは、ピントの合う範囲*1が狭く、ピントから外れたところは大きくボケます。
写真ではそのボケがしばしば効果的に使われていて、特にポートレートで人物を浮き立たせるためなど多用されます。

このボケですが、絞りの形*2に沿ってボケます。
絞りは、レンズ内をカメラのレンズを通って入ってくる光の量を制御するためのもので、光の通る穴の広さを変えることでこれを実現しています。絞りを「絞って」光の通る穴を狭くすると、それに従ってボケも小さくなります。

さて、ボケというと丸いイメージがあります。絞りの形に沿ってボケるということですが、絞りの形を好きな形にしたら、その形にボケるのでしょうか?
実際に試してみます。

レンズの絞りを取り換えることはできないので、擬似的に穴をあけた黒画用紙をレンズ前面に置くことで光の通り道を制御します。

用意するもの

  • 一眼レフカメラなどセンササイズの大きいカメラ
  • 単焦点レンズなど明るい(開放F値の小さい)レンズ
  • 黒画用紙
  • カッター
  • レンズプロテクターあるいはテープ(固定用)

手順

黒画用紙をレンズ前面にはまるように丸く切り、好きな形の穴を切り抜きます。うまく出ない可能性があるので、あまり穴が端の方まで来ないようにした方が良さそうです。
f:id:nixeneko:20170224011417p:plain


レンズ前面のフィルタを取り付けるところにはめ、レンズプロテクターを上から取り付けて挟んで固定します。これはテープで貼りつけて固定するのでも構いません。
f:id:nixeneko:20170224011639p:plain
完成。

撮影

絞りを開放にして撮影します。


一点で光っているものだと、ピントが外れた時のボケがわかりやすいです。
光沢のある物体のハイライトだとか、イルミネーションの電飾だとか。街灯とかを遠くから撮影してもきれいです。

今の時期イルミネーションもあまりないので、適当に撮影したものを載せます。あまりいい例ではないですが……。
f:id:nixeneko:20170223234407p:plain
ちゃんと背景のあかるい部分が星形にボケてますね。


ケーキの蝋燭を動画に撮ってみました。ピントリングを回してピントを動かしています。


蝋燭の炎は画面上で結構な面積あるので、ボケた結果も縦長でややいびつな形になってますね。


手元にあったガチャガチャのフィギュアを撮ってみました……といってもここで見たいのは繋がってる鎖の方ですが。
f:id:nixeneko:20170224010749p:plain
鎖の部分のハイライトが星形にボケています。面白いじゃない!


適当な夜の町の写真です。
f:id:nixeneko:20170225235837p:plain
やはり夜景を撮ると良いですね。街灯がきれいな形にボケてくれます。

おまけ

ところで、細かい模様でも再現できるのでしょうか。試しにこんなものを作ってみました。
f:id:nixeneko:20170224013338p:plain


撮影テストしてみるとこんな感じになりました。
f:id:nixeneko:20170224013924p:plain
光が小さい点一つのみでかつ画面中央に来るようにうまいこと調整すると、やや滲んでますがこれくらいは出ます。しかし条件が良くないとぼやけたり重なってよく分からない感じになります。


動画です。LEDのライトは割ときれいな形にぼけてくれます。
中央から外れるとすぐ潰れてしまいますが。

まとめ

  • ピントが合ってる面の前後でボケの向きが反転する
    • ピントが合ってる面より後ろ側だと穴をくり抜いた黒画用紙レンズに嵌めた方向にボケて、ピントが合ってる面より手前側だとレンズに嵌めた向きとひっくり返ってボケるようです。
  • 写真の中心はともかく、画面端のほうはボケが一部欠ける
    • くり抜いた紙をレンズ前面にくっつけてるだけなのである程度仕方ない気がします。

追記(2017-08-02)

絞りの形変えられるレンズ製品もあります。
New Petzval 85 Lens
vimeo.com

参考

実際の世界の一点光がボケて広がる、その広がりを錯乱円 circle of confusion といいます。円なのは絞りが大抵は円やそれに近い形をしてるからでしょうか。
画像処理の流儀 - 焦点深度、被写体深度、絞りとの関係
Circle of confusion - Wikipedia

*1:被写界深度 Depth of Field, DoF、という。

*2:絞りによってつくられる穴の形

PythonでJIS X 0208コードに対応するUnicode値を求める

あるデータセットで、文字情報がJIS X 0208のコードで与えられていたのだが、使い勝手がよくないのでUnicode値に変換しようとした。

やり方

Unicodeコンソーシアムが、JIS X 0208のコードからUnicode値へ変換する変換表を公開している。

今回はこれを使う。ただし、この変換表はobsoleteとなっているので、代りにUnihan Databaseを利用した方が良いのかもしれない。

JIS0208.TXTに曰く、対応表のフォーマットは

#	Format:  Four tab-separated columns
#		 Column #1 is the shift-JIS code (in hex)
#		 Column #2 is the JIS X 0208 code (in hex as 0xXXXX)
#		 Column #3 is the Unicode (in hex as 0xXXXX)
#		 Column #4 the Unicode name (follows a comment sign, '#')

となっているようで、#で始まっている行はコメントとなっているようだ。

コード

"JIS0208.TXT"と同じディレクトリで実行する。

# coding: utf-8

shift_jis = []
jisx0208 = []
unicode = []
with open("JIS0208.TXT", "r") as f:
    for line in f:
        if line[0] == "#":
            pass
        else:
            sjis, jisx, unic, _ = line.strip().split("\t")
            shift_jis.append(int(sjis,16))
            jisx0208.append( int(jisx,16))
            unicode.append(  int(unic,16))

def jis2uni(n):
    return unicode[jisx0208.index(n)]
    
if __name__ == '__main__':
    print("{:x}".format(jis2uni(0x2422)))

jis2uni()関数にJIX X 0208のコードを与えると対応するUnicode値が返ってくるというもの。なおPython 3系なら、Unicode値をchr()で文字(列)に変換できる。

OpenTypeフォントで万年カレンダーをつくる

はじめに

カレンダーの一つの月の日付の並びには、各曜日始まりの7種×日数の種類(28, 29, 30, 31日)の4種で合計28種ある。祝日などを考えなければ28種を使いまわすことで任意の年月に対応できる。

そんな発想で作られた、使いまわしできるカレンダーを万年カレンダーという(日数の違いにまで対応してるとは限らないが)。
という訳で、せっかくなのでこの万年カレンダーOpenTypeフォントで実装してみる。

2016-01とか2016/01とか書くと2016年1月のカレンダーが表示されるようにしたい。

完成品

f:id:nixeneko:20170211002007p:plain

Webフォントによる表示

2017/02

Javascriptでカウントアップさせてみる:

2000/01

たのしい!

ダウンロード

ソースコード

GitHubに挙げたのでそちらを参照。
github.com

  • Acalendar.ttf: フォントデータ
  • Acalendar.sfd: Fontforgeファイル (GSUB, GPOSの設定なし)
  • calendar.fea: GSUB, GPOSの定義

仕様・制限

OpenType機能の'liga', 'mkmk'を有効にして表示する。
“2017/02”, “12345/6” などといった、

(年)/(月)

の形に対応している。

  • 年は正数にしか対応していない*1
  • 6桁以上の年数はOpenTypeの'mkmk'フィーチャを有効にできる環境でないとうまく年が表示できない。
  • 年が15桁以上だと月の表示と被る可能性がある。
  • 月は2桁または1桁に対応している。
  • スラッシュはハイフンでもよい。

正規表現で表すと

\d+[-/]\d{1,2}

となる。

方針

togetter.com
ここで色々検討されているが、カレンダーが28種類のなかからどれを使うかは、

  • その年の元日の曜日は何か
  • その年は閏年かどうか
  • 何月か

によって決まる。
元日の曜日は400年ごとに同じ並びが繰り返され、次のような計算式で計算できるっぽい。(なお、日曜のoffset=3は間違い)

閏年かどうかは、西暦の年の数字が

  • 400で割り切れるときは閏年
  • 400で割り切れない、かつ、100で割り切れるときは閏年ではない
  • 400で割り切れない、かつ、100で割り切れない、かつ、4で割り切れるときは閏年
  • それ以外は(4で割り切れないとき)は閏年ではない

という風に判定でき、

  1. 4で割り切れる
  2. 100で割り切れる
  3. 400で割り切れる

かどうかの3つを組み合わせて判定できる。


OpenTypeのGSUBによる置換を使って剰余等の計算を真面目に行ってもいいのだろうが、非常に面倒臭そうだし、状態の数が結構な数になってしまいそうなので、今回は西暦の年を400で割った余りについて、400通りの置換を定義することで行う。3桁未満にも対応できるように実際には置換の数はもっと増える(というか、499個)。

実装

グリフの用意

実装してみる。
アウトラインとしてM+ Fontsの mplus-1p-medium.ttf をベースにした。

まずは始まる曜日の違い(7種)と月の日数の違い(4種)で28種類のカレンダーを用意する。
最初にグリフの用意。
日曜始まりでカレンダーを用意した。
始まる曜日と日数で、グリフ名を

cal_mon_28

など、

cal_(曜日)_(日数)

とした。

GSUBの実装

詳しくは、GitHubに上げた calendar.fea を参照されたい。


最初に年について400の剰余を計算する。
これは要するに、百の位以上の桁について4の剰余を計算すればよい。

4の剰余を表すための状態の数だけ状態に対応する数字のグリフを作成する。

数字 0 1 2 3 4 5 6 7 8 9
0 mod 4 00 10 20 30 40 50 60 70 80 90
1 mod 4 01 11 21 31 41 51 61 71 81 91
2 mod 4 02 12 22 32 42 52 62 72 82 92
3 mod 4 03 13 23 33 43 53 63 73 83 93

実際には zero_0mod4, one_0mod4, …, nine_0mod4, …, zero_3mod4, …, nine_3mod4 などという名前のグリフを用意した。


数字の並びについて、まず前に数字が続かないもの、つまり数字の最初の桁について置換をおこなう。3桁の数字の最初の文字について次のように置換をおこなう。

元の数字 0 1 2 3 4 5 6 7 8 9
置換先 00 11 22 33 40 51 62 73 80 91

これは lookup check_first_fig_mod4 で行っている。


次に、4の剰余の状態を持った数字の次に来る3つの数字のうちの1番目の数字について置換を行う。
つまり、
mod4の数字 普通の数字 普通の数字 普通の数字
という並びの時に太字にした“普通の数字”を対応するmod4の数字に置換する。

元の数字 0 1 2 3 4 5 6 7 8 9
前が剰余0か2の時の置換先 00 11 22 33 40 51 62 73 80 91
前が剰余1か3の時の置換先 02 13 20 31 42 53 60 71 82 93

これは lookup check_mod4 で行った。
これで年の400の剰余が求まった。


さて、次に、年の始まりの曜日と閏年かどうかの14状態を判定する。これは、その14状態に対応するスラッシュ“/”のグリフを用意し、年と月の間のスラッシュ“/”(あるいはハイフンでもいい)に対し置換を行うこととする。これはスラッシュの前3桁の数字について400通り(数字が2桁、1桁しかない場合を加えて499通り)の置換をずらずら列挙することになる。うっ頭が…。
これは lookup check_firstday_and_leapyear で実装した。気合、といった感じ。
状態をもつスラッシュのグリフ名は

slash_mon_leap
slash_tue_comm

などとした。(mon, tue, wed, thu, fri, sat, sun)×(leap, comm)


置換後、スラッシュが14の状態をもっている。閏年はl, 閏年でない年はnで示した。
スラッシュの14状態(一番左の列)に対して、後続する数字(一番上の行)によって次の表のようにカレンダーを表示する。表記したのはカレンダーに含まれる日数と開始曜日である。

01 02 03 04 05 06 07 08 09 10 11 12
日, n 31日 28水 31水 30土 31月 30木 31土 31火 30金 31日 30水 31金
月, n 31月 28木 31木 30日 31火 30金 31日 31水 30土 31月 30木 31土
火, n 31火 28金 31金 30月 31水 30土 31月 31木 30日 31火 30金 31日
水, n 31水 28土 31土 30火 31木 30日 31火 31金 30月 31水 30土 31月
木, n 31木 28日 31日 30水 31金 30月 31水 31土 30火 31木 30日 31火
金, n 31金 28月 31月 30木 31土 30火 31木 31日 30水 31金 30月 31水
土, n 31土 28火 31火 30金 31日 30水 31金 31月 30木 31土 30火 31木
日, l 31日 29水 31木 30日 31火 30金 31日 31水 30土 31月 30木 31土
月, l 31月 29木 31金 30月 31水 30土 31月 31木 30日 31火 30金 31日
火, l 31火 29金 31土 30火 31木 30日 31火 31金 30月 31水 30土 31月
水, l 31水 29土 31日 30水 31金 30月 31水 31土 30火 31木 30日 31火
木, l 31木 29日 31月 30木 31土 30火 31木 31日 30水 31金 30月 31水
金, l 31金 29月 31火 30金 31日 30水 31金 31月 30木 31土 30火 31木
土, l 31土 29火 31水 30土 31月 30木 31土 31火 30金 31日 30水 31金

14 × 12 = 168通り。一桁の数字にも対応するために126通りの置換を追加し計294通りになった。
これは lookup replace_calendar で行った。


さて、カレンダーを表示するのもいいけどせっかくなので何年何月ってのも表示させたい。
月については、事前に月を示す(JAN, FEB, などと表示される)グリフを用意しておき、グリフ幅0で、カレンダーのグリフの次にきたときに丁度いい位置に月の表示がくるように位置調整しておく。
これを、カレンダーのグリフに後続する2桁または1桁の数字に対して置換をおこなうことで、月の表示を可能にしている。
これは lookup replace_month で実装した。


最後に年の表示。数字をspacingなグリフにしてしまうと、並べるのは簡単だが、左側に空白ができてしまう。
という訳で、年の数字専用の幅0のグリフを用意しておき、GSUBで数字をそれらのグリフに置換し、その後GPOSのMarkToMark positioning (タグでいうと'mkmk')を使って位置調整することで年の数字を並べようと考えた。

さて、フォントが一応できたので動作を見てみる。

Adobe InDesign

「文字」パネルプルダウンメニューから「欧文合字」をオンにすると……
f:id:nixeneko:20170208224745p:plain
やったー!

Adobe Illustrator

イラレではどうかな?OpenTypeパネルから欧文合字を有効にして……
f:id:nixeneko:20170208225148p:plain
あれー?
'mkmk'が効いてない。
もし'mark'は効くであれば、'mkmk'じゃなくても'mark'とGSUBによる置換で代用することはできるのだけれど。


今回は、GSUBだけである程度まで動くようにしておく。事前に位置をずらした数字を用意しておいて、GSUBで順番に置換する。5桁あれば十分だろう。それより大きい桁数は'mkmk'を有効にできる環境で使うようにしてもらう。
これによって年を表す数字のグリフが5倍に増える。
このあたりは lookup replace_year_10000, lookup replace_year によってGSUB置換を実装、さらに lookup STACK_YEAR を使って6桁以上の年の数字が右に並ぶようにした。

結果

Adobe Illustrator

f:id:nixeneko:20170209182717p:plain
やったー!
もちろん年が6桁以上になるのは文字が重なってうまく表示できないのだけど(10万年後もグレゴリオ暦が使われてるのか、閏年の計算も同じなのか謎だけど)。

Adobe InDesign

f:id:nixeneko:20170209183216p:plain
もちろんInDesignでは6桁以上も'mkmk'でうまく並ぶ。 10^{13}年後も地球が存在してるのか知らんけど。ちなみに太陽の寿命が 10^{10}年位らしい。

*1:とはいえ、紀元前にグレゴリオ暦を適用してどうするのって気もする……。