Pythonでwavを作成する

適当なC5のようなコードからwaveを作る。 環境は Ubuntu18.04 Python3.6.5

インストール

pretty_midi

文字列のコードからmidiの作成、fluidsynthの呼び出しまでやってくれるライブラリ。

pip install pretty_midi

pyFluidSynth

pretty_midiからfluidsynthを呼び出すときに使用している。
pritty_midiを入れたただけでは入らないので個別に入れる必要がある。
PyPIに上がっている奴はかなり古く、Python3では動かないため、githubから入れること。

pip install git+https://github.com/nwhitehead/pyfluidsynth

fluidsynth

これで楽器の音をつける。
なくても音を着けることは可能だがピョーっという感じの音になる。

sudo apt install fluidsynth

scipy

fluidsynthでできたwaveを書き出すために使う。
別に書き出さないなら不要だが確認するのに便利。

pip install scipy

コード

import pretty_midi
from scipy.io import wavfile

pm = pretty_midi.PrettyMIDI() 
violin_program = pretty_midi.instrument_name_to_program("Violin")
violin = pretty_midi.Instrument(program=violin_program)

note_number = pretty_midi.note_name_to_number("C5")
note = pretty_midi.Note(velocity=100, pitch=note_number, start=0, end=.5)
violin.notes.append(note)

pm.instruments.append(violin)

# fluidsynthでwavに変換
audio_data = pm.fluidsynth()

# wavファイル書き出し
# fluidsynthのfsが44100なので合わせる
wavfile.write("hoge.wav",44100, audio_data)

音の変更

FluidSynthはSoundFontを使用して音をつけている。
つまり、これを変更することで音の質(?)を変えられる。(なんていうんですかね…。同種の楽器でも音が違うことに対する単語を知らない。)
変更するには上記コード中のfluidsynthにsfファイルのパスを指定してあげれば良い。
上記コードのように何も指定しない場合pretty_midiが入れてきたTimGM6mb.sf2を使うらしい。

変更する場合はTimGM6mbのようなGeneral MIDIという規格にそった、GMサウンドフォントと呼ばれるものを使うのが良さそう。 サウンドフォントのリストは以下のリンクが詳しい。

サウンドフォントと SFZ ファイル | MuseScore

ちなみにFluidSynthインストール時にもサウンドフォントはインストールされている。

/usr/share/sounds/sf2/FluidR3_GM.sf2

FluidR3_GM.sf2で音を作るには以下のコードに差し替える。

audio_data = pm.fluidsynth(sf2_path='/usr/share/sounds/sf2/FluidR3_GM.sf2')

聴き比べたら普通にわかるぐらいFluidR3_GM.sf2のほうがそれっぽい音だった。

Mastodon 2.4.0に上げるときに困ったこと

Mastodon 2.4.0にアップデートするときdb:migrateができなかったのをなんとかした。*1

現象

以下みたいな感じになる。

$ docker-compose run --rm web rake db:migrate
Starting mastodon_redis_1 ... done
Starting mastodon_db_1    ... done
rake aborted!
Gem::LoadError: You have already activated rake 12.0.0, but your Gemfile requires rake 12.3.1. Prepending `bundle exec` to your command may solve this.
/mastodon/config/boot.rb:3:in `<top (required)>'
/mastodon/config/application.rb:1:in `require_relative'
/mastodon/config/application.rb:1:in `<top (required)>'
/mastodon/Rakefile:4:in `<top (required)>'
(See full trace by running task with --trace)

railsの方使えばいいんでしょとrails使うと違うエラー。

$ docker-compose run --rm web rails db:migrate
[FATAL tini (6)] exec rails failed: No such file or directory

解決

以下みたいにコマンドを打つ

$docker-compose run --rm web ./bin/rails db:migrate

ついでにprecompileも。

$ docker-compose run --rm web ./bin/rails assets:precompile

宣伝

ドールMastodonやってます。
mastodoll.net

*1:ドッカーって奴つかうとこういうの無くなるんじゃなかったんですか!!!!

Juliaで散布図行列を表示する

Julia v0.6.2 + StatPlots.jlで散布図行列を表示する。

using CSV
d = CSV.read("data-attendance-1.txt")

using StatPlots
@df d corrplot([:A :Score :Y])

png("corrplot")

以下の画像が得られる。

f:id:YuK_Ota:20180510003420p:plain

相関を楕円で出す奴が好きとか色々あると思うので、結局自分で作ることになるんですかね。

すべてのものを直立にする

Juliaでヒストグラムを描く。

環境はJulia v0.6.2
入力データはCSVとする。

using CSV
d = CSV.read("data-attendance-1.txt")
# Scoreというラベルのデータをプロットする。
score = convert(Array{Int64}, d[:Score])

using StatsBase
# nbinsで棒の数、第三引数でstart:step:maxでエッジの指定ができる。
h = fit(Histgram, c)

using Plots
gr()
bar(h.edges[1][2:end], h.weights)

概形みたいだけとかならExcelとかのほうが良さそう。

StanとJuliaでベイズ統計モデリング

確率的プログラミング言語を学ぶ機運を感じたので勉強している。
以下の本を元に勉強しているが、写経するのも面白くないのでJuliaでやっていく。
環境はUbuntu16.04、Julia0.6.2。

インストール

Stan.jlはCmdStanを呼び出すため、CmdStanとStan.jlの両方のインストールが必要である。
Stan.jlのインストール時にいい感じにやってくれんかなと思ったけどそんなことはないし、やられたらそれはそれでうざい。

CmdStanのインストール

aptとかにもないので公式ページから落としてくる必要がある。
Stan - CmdStan

私は~/bin以下に解凍した。
次に.zshrcに以下を追記。

export CMDSTAN_HOME=/home/youraccount/bin/cmdstan-2.17.1

いつも通りsource .zshrcして完了。

Stan.jlのインストール

CmdStanが設定されていればPkg.addするだけである。

Pkg.add("Stan.jl")

Juliaのlm関数で推定

上記書籍でも一旦、Rのlmを使用して回帰させているので、こちらも一旦それに習う。
GLM.jlを使用し同じことを行う。

using CSV
using GLM
using DataFrames

data = CSV.read("data-salary.txt")
profit = lm(@formula(Y ~ X), data)
new_x = DataFrame(X=23:60)
                                                                                      
@show predict(profit, new_x) 

ちなみに予測区間を出すにはpredict(profit, new_x, :confint)とやれば良さそうにREADMEには書いてあるが、
DataFrameからMatrixの変換はStatsModelsで実装されており、StatsModels側の実装がSymbolを受け取るようなI/F
ではないため、できない。READMEにはかいてあるのに。
issueをみると1年くらい前に治そうとしている形跡はある。
私も直してやろうかと思ったらそもそもテストが落ちているので、まずそこを直そうとなり、これがそもそもこの仕様やめね?という話に飛び火してつらみを出してる。
巷でJulia最高と言っている人間はこういう辛い面を全く言わないので多分違うJuliaを使っている気がする。

Stanで実装、Juliaからの実行方法

上記書籍のmodule4-5.stanを写経する。
下からダウンロードしても良い。
RStanBook/model4-5.stan at master · MatsuuraKentaro/RStanBook · GitHub

後はStan.jlからモデルを呼び出す。

using CSV
using Stan
d = CSV.read("data-salary.txt")
data = [Dict("N"=>size(d, 1), "X"=>d[:X], "Y"=>d[:Y])]
f = open("model4-5.stan", "r")
model = readstring(f)
close(f)
stanmodel = Stanmodel(model = model, random=Stan.Random(1234))
rc, sim = stan(stanmodel, data)

実行結果であるsimはMambaというMCMCのライブラリで扱われるデータ型になる。

実行結果を見る。

using Mamba
describe(sim)

最後にグラフに表示する。
MambaはGadflyでグラフ表示することを意識して作っているが、
Plots(GRBackend)が好き(というかそれ以外であまり上手く行ったことがない)なため、これで描画する。
今回もGadflyで描画しようとしてクラッシュしたので逃げたとも言う。

Traceを表示する。
といっても表示要素が多いためどれを表示したいかを選ぶ。

sim.names

表示させたいものが決まったらグラフに出す。

using Plots
gr()

nrows, nvars, nchains = size(sim.value)
i = 9 # bを表示
Plots.plot(1:nrows, sim.value[:, i, :], title=sim.name[i])

bが21付近をうろうろしているグラフが得られ、1年ごとに21万も昇給するわけねぇだろという気持ちになったので終わります。

Mastodonインスタンス立ち上げ後にやること

なんとなくDockerでMastodonインスタンスを作れるが、まだやるべきことがあります。
デイリー、ウイークリー、マンスリーでやるべきタスクがあるのでこれをcronに登録する必要があります。
ユーザーがいる場合、サービスが止まらないか気にする必要があるので予めやっておくほうが良いです。

mastodon:dailyのcron設定

mastodon:dailyというコマンドがここでやれと言われているコマンドをまとめてやってくれています。
documentation/Maintenance-Tasks.md at master · tootsuite/documentation · GitHub
dailyで実行するものなのでcronに登録しましょう。

@daily cd /your/gitcloned/mastodon && /usr/local/bin/docker-compose run --rm web rake mastodon:daily | logger -t mastodon -p local0.info

mastodon:media:remove_remoteのcron設定

1週間以上前の添付ファイルのキャッシュを消します。

@weekly cd /your/gitcloned/mastodon && /usr/local/bin/docker-compose run --rm web rake mastodon:media:remove_remote 2>&1 | logger -t mastodon -p local0.info

docker-composeへのパスは絶対パスで指定しておくか、cron実行時のPATHを確認したうえで指定してください。
cron実行時とsshのときのPATHは異なる場合が有ります。

Let's Encryptの証明書の更新のcron設定

Let's Encryptの証明書の期限は90日です。
公式で60日での更新を奨めています。
FAQ - Let's Encrypt - Free SSL/TLS Certificates
monthlyで更新しましょう。
以下は最初にwebrootでやった場合です。standaloneの場合は一度nginxを止める必要があると思います。

@monthly /your/gitcloned/letsencryption/certbot-auto renew && /bin/systemctl reload nginx

一度手元でdry-runで実際に動作するのか試しておいたほうが良いです。

certbot-auto renew --dry-run

私の環境だとはnginxのconfが雑だったため動きませんでした。
大体下のリンクからパクったconfですが、rootの場所を設定していませんでした。
documentation/Production-guide.md at master · tootsuite/documentation · GitHub
nginxのインストール->証明書取得->mastodonインストールの順で作業してるとなんとなくうまく行ってしまうポイントなのでアレ。


ちなみに立ち上げたインスタンスです。
mastodoll.net

JuliaImagesで画像の平行移動をする

Julia v0.5.1 + JuliaImages/ImageTransformations.jl v0.2.2で画像の平行移動を行う。

using Images 
using CoordinateTransformations

img = Gray{Float64}[                                                                                                                                                          
 0.0 0.0 0.0 0.0 0.0;
 0.0 0.5 0.5 0.5 0.0;
 0.0 0.5 1.0 0.5 0.0; 
 0.0 0.5 0.5 0.5 0.0;
 0.0 0.0 0.0 0.0 0.0;]

tfm = recenter(Translation(2,0), center(img_pyramid))
translated_img = warp(img, tfm)

このとき、以下のように表示され、なんか移動してなくね?となる。

 3:7×1:5 OffsetArray{Gray{Float64},2}:
 Gray{Float64}(0.0)  Gray{Float64}(0.0)  Gray{Float64}(0.0)  Gray{Float64}(0.0)  Gray{Float64}(0.0)
 Gray{Float64}(0.0)  Gray{Float64}(0.5)  Gray{Float64}(0.5)  Gray{Float64}(0.5)  Gray{Float64}(0.0)
 Gray{Float64}(0.0)  Gray{Float64}(0.5)  Gray{Float64}(1.0)  Gray{Float64}(0.5)  Gray{Float64}(0.0)
 Gray{Float64}(0.0)  Gray{Float64}(0.5)  Gray{Float64}(0.5)  Gray{Float64}(0.5)  Gray{Float64}(0.0)
 Gray{Float64}(0.0)  Gray{Float64}(0.0)  Gray{Float64}(0.0)  Gray{Float64}(0.0)  Gray{Float64}(0.0)

だが、この行列はOffsetArrayで表現されており、これでちゃんと平行移動している。
1行目の型情報にオフセットの情報が書いてあり、この値域の情報だけが下に表示されている。
ちなみにtranslated_img[1, 1]でアクセスするとBoundsErrorになるのでindicesなりで座標の値域をとってからアクセスする必要がある。


私がOffsetArrayに気付かず、テストコードやサンプルも回転移動のものしかないため少し詰まったのでメモ。
関係ないが、スーパーpre記法がjuliaに対応していた。
はてなブログ最高。