SWISS-MODEL & PyMOL
Hands-on prediction and visualization of protein structure
Please note that the prediction of protein structure is generally very difficult and depends much on the amount of data of similar proteins stored in PDB (Protein Data Bank).
Predict the structure of protein of your interest by SWISS-MODEL.
Visualize it by PyMOL.
SWISS-MODEL
Requirements: Amino acid sequence of the protein of your interest.
- Go to SWISS-MODEL and start modelling.
- Copy and paste the sequence into the window, fill in the project name and your email (optional; if you want) and start "Search For Templates".
- Then it starts searching for templates.
- Then it generates the result. It lists similar proteins that are possibly useful for predicting your protein. Choose the best (top) one and click "Build Models". Here are some explanation about the meaning of each score.
- The predicted model has been made now. You can download the pdb file.
PyMOL
Requirements: Python3, .pdb
file generated above
- You can install the
pymol
byconda
. If you haven't installedconda
yet, you can download the zipped file from here.
$ conda install -c schrodinger pymol-bundle
- Learn how to code pymol commands referring to here (Eng) or here (Jap). Here are some example scripts I made, which may be helpful to understand how it works.
1_visualize_model.py
which visualizes the model and hightlight some regions and residues of interest by different colors.
$ python3 1_visualize_model.py model VMAT1 130 136 180 30 -100
import time import re import pymol import sys # sys.argv[1]: the name of the input model (pdb file) # sys.argv[2]: the name of output figure (png) # sys.argv[3]: the location of a residue interested # sys.argv[4]: the location of a residue interested # sys.argv[5]: the angle of x # sys.argv[6]: the angle of y # sys.argv[7]: the angle of z # python3 1_visualize_model.py model VMAT1 130 136 180 30 -100 pymol_argv = ['pymol', '-qc'] pdb_file = '%s.pdb' % sys.argv[1] #input pdb file out_png = '%s.png' % sys.argv[2] #output figure name ## Launch pymol pymol.finish_launching() pymol.cmd.load(pdb_file) pymol.cmd.enable(pdb_file) ## Some visual settings of protein structure pymol.cmd.show('cartoon') #shown by cartoon pymol.cmd.do('bg_color white') #make the background color transparent pymol.cmd.do('set ray_shadow, off') #remove shadow pymol.cmd.do('select tm1, (resi 19:48)') #select the region of interest and set its name as tm1 pymol.cmd.do('color skyblue, tm1') #change the color of tm1 to skyblue. You can check available colors here: https://pymolwiki.org/index.php/Color_Values pymol.cmd.do('select tm2, (resi 136:163)') #select the second region of interest and set its name as tm2 pymol.cmd.do('color paleyellow, tm2') #change the color of tm2 to paleyellow pymol.cmd.do('color white, not tm1 and not tm2') #change color of the other regions to white pymol.cmd.do('color red, resi %i' % int(sys.argv[3])) #change the color of residue of interest set above pymol.cmd.do('color red, resi %i' % int(sys.argv[4])) #change the color of another residue of interest set above pymol.cmd.do('turn x, %i' % int(sys.argv[5])) #set the x angle pymol.cmd.do('turn y, %i' % int(sys.argv[6])) #set the y angle pymol.cmd.do('turn z, %i' % int(sys.argv[7])) #set the z angle time.sleep(5) pymol.cmd.do('ray 2000, 2000') #set the resolution. When using png as output, I recommend to set as much resolution as possible, though it takes a while. pymol.cmd.png(out_png) pymol.cmd.refresh() pymol.cmd.quit()
2_zoomin.py
which zooms in the residues of interest (and mutates the residue if desired) and shows its side chain by sticks.
$ python3 2_zoomin.py model VMAT1_130Glu 130 GLU 180 30 -100
import time import re import pymol import sys # sys.argv[1]: name of the model (pdb file) # sys.argv[2]: the name of output figure (png) # sys.argv[3]: the location of a residue interested # sys.argv[4]: the residue to be mutated (must be capital letters) # sys.argv[5]: the angle of x # sys.argv[6]: the angle of y # sys.argv[7]: the angle of z # python3 2_zoomin.py model VMAT1_130Glu 130 GLU 180 30 -100 pymol_argv = ['pymol', '-qc'] pdb_file = '%s.pdb' % sys.argv[1] #input pdb file out_png = '%s.png' % sys.argv[2] #output figure name ## Launch pymol pymol.finish_launching() pymol.cmd.load(pdb_file) pymol.cmd.enable(pdb_file) ## Some visual settings of protein structure pymol.cmd.show('cartoon') #shown by cartoon pymol.cmd.do('bg_color white') #make the background color transparent pymol.cmd.do('set ray_shadow, off') #remove shadow pymol.cmd.do('set cartoon_color, white') # let's mutate residue 130 to GLU pymol.cmd.wizard("mutagenesis") pymol.cmd.refresh_wizard() pymol.cmd.get_wizard().do_select('%s/' % str(sys.argv[3])) pymol.cmd.get_wizard().set_mode('%s' % str(sys.argv[4])) pymol.cmd.get_wizard().apply() pymol.cmd.set_wizard() pymol.cmd.do('set stick_radius = 0.15') pymol.cmd.do('set sphere_scale = 0.15') pymol.cmd.do('select ri, byres (resi %s around 4)' % str(sys.argv[3])) #set the region of interest (here it covers 4 amino acids around the residue of interest) pymol.cmd.do('show stick, resi %s' % str(sys.argv[3])) #show stick pymol.cmd.do('set cartoon_transparency, 0.4') #set the cartoon transparent pymol.cmd.do('zoom ri') #zoom in around the residue of interest pymol.cmd.do('turn x, %i' % int(sys.argv[5])) pymol.cmd.do('turn y, %i' % int(sys.argv[6])) pymol.cmd.do('turn z, %i' % int(sys.argv[7])) ## Generate output time.sleep(5) pymol.cmd.do('ray 2000, 2000') pymol.cmd.png(out_png) ## Finish pymol pymol.cmd.refresh() pymol.cmd.quit()
ripgrep-allでどこかに保存した論文を探す
初めてblogっぽいことを書いてみる。
最近TL上でたまに流れてきて気になってはいたものの、podcastなるものにあまり馴染みがなく敬遠していたが、テーマにそそられて思い切って聞いてみた。 researchat.fm
2時間とめちゃくちゃ長いが、人の声に飢えているのか、作業しながらつい全部聞いてしまった。うるさい先輩たちが話しているような感じ(ごめんなさい)なんだけど、結構タメになる。3人が話しているだけで2時間のコンテンツとして成り立たせるなんてすごい。
この放送の中で、「 論文管理どうしてる?」という話題があり、「ぶっちゃけ無理っすね、必要な時に都度探します」という話になっていて(その時に言っていた「論文それ自体よりも、以前にそれを読むことにした過程を覚えていればたどり着ける」というのもなるほどと思った)、へぇそういうものか、と思ったのだけど(自分は基本Mendeleyで管理している)、そこで一人の方が言及していた ripgrep-all
なるものに惹かれ、早速導入してみた。ので、本稿はその記録です。一般的な論文の探し方や読み方などの詳細は上のpodcastをお聞きください。
brew
で超簡単にインストールできたので特に説明することもない。PDFを検索するのにpoppler
というのも必要だったのでそれも合わせてインストールした。
$ brew install rga $ brew install poppler
論文ディレクトリを対象に適当にcollective behaviorという文字列を含む論文を探してみた。
速い。
さらにfzf
(fuzzy-finder)と組み合わせると、より効率的に探せる。
# fzfのインストール $ git clone --depth 1 https://github.com/junegunn/fzf.git ~/.fzf $ ~/.fzf/install # rgaと組み合わせる $ rga "collective behavior" ~/Dropbox/研究室/論文/2020.5/*.pdf | fzf
というかfuzzy-finder便利だなこれ。ripgrep-allよりも、こっちの方が気になってきた。上の作業だけならspotlightとそこまで変わらない気がするので、もう少しここら辺の使い方を洗練させたい。
Juliaのファイル操作
書き込み
#書き込み(上書き) julia> iow = open("text.txt","w") julia> write(iow,"Hello world") julia> close(iow) #書き込み(追記) julia> ioa = open("text.txt","a") julia> write(ioa,"Append world") julia> close(ioa)
do
ブロックを使えば自動的に閉じられるのでclose
は必要ない.
open("mytext.txt","w") do iow write(iow,"Hello world") end
読み込み
do
ブロックの外側で宣言した変数を改変したいときは、global
スコープを使う必要がある.
julia> val = "aa" "aa" julia> val2 = "aa" "aa" julia> open("test.txt","r") do ior text = read(ior,String) text = replace(text,"\n" => "") #改行コードの除去 global val = text val2 = text end "Hello worldAppend world" julia> println(val) Hello worldAppend world julia> println(val2) aa
readlines
関数
各行を文字列の配列にして返す.
julia> open("test.txt","r") do ior lines = readlines(ior) println(lines) end ["Hello world", "Append world"]
keep
オプションをtrue
にすると改行コードは保たれる.
julia> open("test.txt","r") do ior lines = readlines(ior,keep=true) println(lines) end ["Hello world\n", "Append world"]
eachline
関数
ファイルを指定するだけ.
julia> for line in eachline("test.txt") println(line) end Hello world Append world
パス取得
pwd()
やhomedir()
がある.
julia> pwd() "/Users/dxsato/Desktop/Julia/" julia> homedir() "/Users/dxsato"
ディレクトリ操作
mkdir()
で新たなディレクトリを作成可能.
julia> mkdir("test")
readdir()
でディレクトリの中身を取得.
julia> readdir("test") 0-element Array{String,1}
mkdir()
は存在しないディレクトリの内側にさらに新たなディレクトリを作成することはできないが、mkpath()
なら一気に作成可能.
mkpath("dir1/dir1_1")
cd()
で移動可能.
julia> cd("test")
for
とwalkdir()
を合わせると再帰的なディレクトリ情報の取得が可能.
julia> for (path, arr_dir, arr_file) in walkdir(pwd()) println(path) [println(dir) for dir in arr_dir] [println(file) for file in arr_file] end /Users/dxsato/Desktop/Julia/test/ dir1 test dummy_SNPs.txt dummy_microarray.txt test.txt text.txt 問題.pdf /Users/dxsato/Desktop/Julia/test/dir1 dir1_1 /Users/dxsato/Desktop/Julia/test/dir1/dir1_1 /Users/dxsato/Desktop/Julia/test/test
filesize()
:ファイルサイズの取得.
basename()
:ベース名の取得.
dirname()
:ディレクトリ名の取得.
joinpath()
:パスの連結.
cp()
:コピー. force=true
を指定すると、コピー先を削除してからコピーできる.
mv()
:ファイルの移動.
rm()
:ファイルの削除.recursive=true
を指定するとディレクトリの中身も全て削除できる.
JuliaからRを使う
やはりggplotを使いたいという時がある.
]
でパッケージモードに入り, add
で追加.
(v1.4) pkg> add RCall
julia> using RCall, Distributions, Random, DataFrames julia> Random.seed!(0) MersenneTwister(UInt32[0x00000000], Random.DSFMT.DSFMT_state(Int32[748398797, 1073523691, -1738140313, 1073664641, -1492392947, 1073490074, -1625281839, 1073254801, 1875112882, 1073717145 … 943540191, 1073626624, 1091647724, 1073372234, -1273625233, -823628301, 835224507, 991807863, 382, 0]), [0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 … 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], UInt128[0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000 … 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000, 0x00000000000000000000000000000000], 1002, 0) julia> dat = rand(MvNormal([1 0.75; 0.75 1]), 1000) 2×1000 Array{Float64,2}: 0.679107 -0.353007 0.586617 0.0649475 -0.51421 -0.688907 0.397482 -0.346355 … 0.791341 -0.52823 -1.01701 0.300868 0.398911 0.831824 1.75993 -0.342151 1.05727 -0.353953 0.636632 -0.0233976 0.655664 -1.02123 0.834954 -0.383834 0.296767 -1.07364 -0.963753 -0.160464 0.109914 2.31958 1.47322 0.0729502 julia> df = DataFrame(permutedims(dat))
R""
で内容を囲むと、R内で実行できる
julia> R"1+1" RObject{RealSxp} [1] 2
$
を打つとRモードに入れる
(なぜかこの機能はstartup.jl
に
using RCall
を入れてREPLを起動しても働かない)
R> install.packages("viridis")
Rのライブラリを読み込む.
julia> @rlibrary ggplot2 julia> @rlibrary viridis
ggplotでプロットする.
julia> ggplot(df,aes(x=:x1,y=:x2)) + geom_point()
RDatasets
を使えば、irisデータ等も使える.
julia> using RDatasets julia> iris = dataset("datasets", "iris") julia> ggplot(iris,aes(x=:SepalWidth,y=:PetalWidth,size=:SepalLength,col=:Species)) + geom_point()
julia> ggplot(iris,aes(x=:SepalWidth,y=:PetalWidth,col=:SepalLength,shape=:Species)) + geom_point(size=3,alpha=.5) + scale_color_viridis(option = "A",direction=-1) + theme_minimal()
Julia特有の構文メモ2
ライブラリ
Juliaの関数は大きく3つに分けられる.
- コアベースの関数
- 標準ライブラリの関数
- 外部ライブラリの関数
コアベースの関数
Core.
関数
Core.ifelse
判定文が真なら1つ目、偽なら2つ目の引数を返す.
julia> Core.ifelse('a' < 'A', 'a', 'A') 'A': ASCII/Unicode U+0041 (category Lu: Letter, uppercase) julia> Core.ifelse(10/3==10÷3, "same", "not same") "not same" #juliaのif判定はboolean型しか受け付けない. julia> Core.ifelse(1, "one", "not one") ERROR: TypeError: non-boolean (Int64) used in boolean context Stacktrace: [1] top-level scope at REPL[4]:1
Core.applicable
引数が関数に適用可能か判定する.
julia> myfunc(a::Int64,b::Int64)=a*b myfunc (generic function with 1 method) #引数が一つだけでもダメ julia> applicable(myfunc,2) false #片方がFloatでもダメ julia> applicable(myfunc,2,2.5) false #2つが両方IntならOK julia> applicable(myfunc,2,2) true
Core.tuple
タプルを作成する(関数がTupleではなくtuple).
julia> stationery=tuple("Pencil","Eraser","Ruler") ("Pencil", "Eraser", "Ruler") julia> typeof(stationery) Tuple{String,String,String}
参照渡しについて.
変数の代入は=
で普通に値を渡すだけ.
b
の値を更新してもa
は影響を受けない.
値が格納される参照先(アドレス)が別々だから.
julia> a = 2 2 julia> b = a 2 julia> b = 3 3 julia> a 2
一方でコレクションは参照渡しなので、 代入した後で更新すると、元のも更新される.
julia> arr_a = [1,2,3] 3-element Array{Int64,1}: 1 2 3 julia> arr_b = arr_a 3-element Array{Int64,1}: 1 2 3 julia> arr_b[2]=20 20 julia> arr_a 3-element Array{Int64,1}: 1 20 3
Base.
関数
Base.copy
浅いコピーcopy
と深いコピーdeepcopy
がある.
参照渡しでないコピーなので、値を更新しても互いに影響しない.
julia> ary_a = [1,2,3] 3-element Array{Int64,1}: 1 2 3 julia> ary_cp = copy(ary_a) 3-element Array{Int64,1}: 1 2 3 julia> ary_dpcp = deepcopy(ary_a) 3-element Array{Int64,1}: 1 2 3 julia> ary_a[2] = 20 20 julia> ary_cp 3-element Array{Int64,1}: 1 2 3 julia> ary_dpcp 3-element Array{Int64,1}: 1 2 3
Base.pointer
配列や文字列のアドレスを出力する.
julia> pointer(ary_a) Ptr{Int64} @0x0000000109e47a10
要素が配列になっている深い配列を考える.
浅いコピーではary_a
の更新に伴って値が変わっている.
julia> ary_a = [[1,2,3],[4,5,6]] 2-element Array{Array{Int64,1},1}: [1, 2, 3] [4, 5, 6] julia> ary_shallow = copy(ary_a) 2-element Array{Array{Int64,1},1}: [1, 2, 3] [4, 5, 6] julia> ary_deep = deepcopy(ary_a) 2-element Array{Array{Int64,1},1}: [1, 2, 3] [4, 5, 6] julia> ary_a[2][2] = 50 50 julia> ary_shallow 2-element Array{Array{Int64,1},1}: [1, 2, 3] [4, 50, 6] julia> ary_deep 2-element Array{Array{Int64,1},1}: [1, 2, 3] [4, 5, 6]
アドレスを見てみると、外枠は違うように見えるが、
julia> pointer(ary_a) Ptr{Array{Int64,1}} @0x000000010a56d7f0 julia> pointer(ary_shallow) Ptr{Array{Int64,1}} @0x0000000109b7b290 julia> pointer(ary_deep) Ptr{Array{Int64,1}} @0x000000010a0a59d0
その要素は、浅いコピーでは元配列と同じ場所に格納されているらしい.
julia> pointer(ary_a[2]) Ptr{Int64} @0x00000001099c5a90 julia> pointer(ary_shallow[2]) Ptr{Int64} @0x00000001099c5a90 julia> pointer(ary_deep[2]) Ptr{Int64} @0x00000001099a2f90
Base.
やCore.
は.
の前を省略できるが、関数によって出来るものと出来ないものがある.
標準ライブラリの関数
Juliaインストール時からすでに用意されている関数.
使う際にはusing
で関数名を宣言する必要がある.
Dates.
関数
julia> Dates.now() ERROR: UndefVarError: Dates not defined Stacktrace: [1] top-level scope at REPL[43]:1 julia> using Dates julia> Dates.now() 2019-10-25T20:51:38.306
Dates.
を省略してもいい.
julia> now() 2019-10-25T20:54:06.016
now()
関数はDateTime型、Data()
関数はDate型を返す.
year()
関数は年を取得する.
dayofweek()
関数は曜日の値、dayname()
関数は曜日の名前を返す.
julia> typeof(now()) DateTime julia> Date(now()) 2019-10-25 julia> year(now()) 2019 julia> year(Date("2019-10-25")) 2019 julia> dayofweek(now()) 5 julia> dayname(now()) "Friday"
Day()
は日、Hour()
は時間を取得する.
それぞれDay
型、Hour
型.
julia> Day(now()) 25 days julia> Hour(now()) 21 hours
足したり引いたり、計算もできる.
julia> Day(now() + Hour(3)) 26 days julia> Date("2019-10-25") + Day(1000) 2022-07-21
型が違う場合
#`==`は計算結果が同じならOK. julia> Hour(1) == Minute(45) + Minute(15) true #`===`は型が同じでないとダメ. julia> Hour(1) === Minute(45) + Minute(15) false
外部ライブラリの関数
JSONを例に.
using JSON #JSON形式にシリアライズするための辞書を用意する. julia> stationery=Dict("Pencil"=>80,"Eraser"=>50,"Ruler"=>100) Dict{String,Int64} with 3 entries: "Ruler" => 100 "Eraser" => 50 "Pencil" => 80 julia> JSON.print(stationery) {"Ruler":100,"Eraser":50,"Pencil":80} #インデントの指定.4は4文字分ということ. julia> JSON.print(stationery,4) { "Ruler": 100, "Eraser": 50, "Pencil": 80 }
julia> stationery_json = JSON.json(stationery) "{\"Ruler\":100,\"Eraser\":50,\"Pencil\":80}"
JSON形式のデータをパース.
julia> stationery_parse = JSON.parse(stationery_json) Dict{String,Any} with 3 entries: "Ruler" => 100 "Eraser" => 50 "Pencil" => 80 julia> println(stationery_parse) Dict{String,Any}("Ruler" => 100,"Eraser" => 50,"Pencil" => 80) #元々の辞書. julia> println(stationery) Dict("Ruler" => 100,"Eraser" => 50,"Pencil" => 80)
Julia特有の構文メモ
Symbol
Symbol("test") #のように使う
文字列を表すが、Symbolは常に同じオブジェクトであることが保証されるため、メモリ効率がいい. DataFrameのラベル名などに使われる.
ショートカット構文
条件 || 実行文 #左辺が偽のときだけ実行される 条件 && 実行文 #左辺が真のときだけ実行される
コメントアウト
#=
と=#
で囲うと複数行のコメントアウト.
レンジ
for i in 1:10 #1と10は生成される列に含まれる println("$i") end collect(10:-2:1) #ステップサイズは3組にして真ん中で指定 10 8 6 4 2
文字と文字列
julia> 'a' #chracter 'a': ASCII/Unicode U+0061 (category Ll: Letter, lowercase) julia> "a" #string "a" julia> 'ab' #文字列(string)になっているのでエラーになる ERROR: syntax: invalid character literal Stacktrace: [1] top-level scope at REPL[26]:0 julia> "ab" #こちらは大丈夫 "ab" julia> abcdef = "abcdef" "abcdef" julia> abcdef[2] #インデックス指定もできる(1オリジン) 'b': ASCII/Unicode U+0062 (category Ll: Letter, lowercase) julia> abcdef[3:end] "cdef" julia> abcdef[3:end-1] "cde" julia> abcdef[:4] 'd': ASCII/Unicode U+0064 (category Ll: Letter, lowercase) julia> ghijk = "ghijk" "ghijk" julia> abcdef * ghijk #文字列の結合 "abcdefghijk" julia> string(abcdef,ghijk) #これでもOK "abcdefghijk" julia> println(abcdef) abcdef julia> println("$abcdef") #文字列内での展開 abcdef julia> println("$abcdef","$ghijk") abcdefghijk julia> println("1+2=$(1+2)") #カッコでくくると計算も展開できる 1+2=3 julia> raw"1+2=$(1+2)" #rawをつけるとraw文字列になる "1+2=\$(1+2)"
if文
julia> x=3; y=5; julia> if x < y println("$x is smaller than $y") end 3 is smaller than 5 julia> if x < y < 4 #3つ以上の項目を書ける println("$x < $y < 4 です") else println("$x < $y < 4 ではありません") end 3 < 5 < 4 ではありません julia> if x < y < 4 res_str = "$x < $y < 4 です" end #ifブロック内のみの変数は、ifブロック内で使われなかった場合はエラーになる julia> println(res_str) ERROR: UndefVarError: res_str not defined Stacktrace: [1] top-level scope at REPL[5]:1 julia> if x < y < 4 res_str = "$x < $y < 4 です" else res_str = "$x < $y < 4 ではありません" end "3 < 5 < 4 ではありません" #elseの中で使われているのでエラーにならない julia> println(res_str) 3 < 5 < 4 ではありません julia> x = 1; ifelse(x > 1, x + 1, x + 2) #trueだったら左、falseだったら右を返す 3
3項演算子
r = 5 > 3 ? 5 : 3 #?の左の式が真だったら:の左を出力、偽だったら右を出力 5 #こんなこともできる julia> println(5 > 3 ? "5は3より大きい" : "5は3より大きくない") 5は3より大きい #if-elseif-elseみたいにできる julia> println(5 > 3 ? 5==3 ? "5は3に等しい" : "5は3より大きい" : "5は3より大きくない") 5は3より大きい #関数の定義にも使える($aの後ろにはスペースが必要、エスケープもできなさそう) julia> is_morethan(a,b) = println(a > b ? "$a は$b より大きい" : "$a は$b より大きくない") is_morethan (generic function with 1 method) julia> is_morethan(10,50) 10 は50 より大きくない
while文
julia> i = 1 1 #v1.0以降ではグローバルスコープの変数を書き換える場合はglobalを入れないとエラーになる julia> while i <= 3 println(i) i += 1 end ERROR: UndefVarError: i not defined Stacktrace: [1] top-level scope at ./REPL[25]:2 #こうするとうまくいく julia> while i <= 3 println(i) global i += 1 end 1 2 3
for文
julia> for j = 1:3 #:でもいい println(j) end 1 2 3 julia> for j in 1:3 #inでもいい println(j) end 1 2 3 julia> for j in [1,2,3] #配列を参照してもいい println(j) end 1 2 3 julia> for j in "123" #文字列を参照してもいい println(j) end 1 2 3 julia> for i = 1:2, j in "abc" #多重ループも1行で書ける println(i,j) end 1a 1b 1c 2a 2b 2c julia> arr = [x for x = 1:3] #内包表記 3-element Array{Int64,1}: 1 2 3 julia> [(i,j) for i = 1:2, j in "abc"] #複数要素をtupleに入れながら、2次元配列を返す 2×3 Array{Tuple{Int64,Char},2}: (1, 'a') (1, 'b') (1, 'c') (2, 'a') (2, 'b') (2, 'c') julia> println([i for i in 1:200 if i % 16 == 0]) #if文を入れることもできる [16, 32, 48, 64, 80, 96, 112, 128, 144, 160, 176, 192] julia> [3x + 5y for x = 1:3, y = 5:7] #こんなことも 3×3 Array{Int64,2}: 28 33 38 31 36 41 34 39 44
配列
#Array{T,N}(undef,dims)と書く #Int64型 2次元 1次元の要素数3,2次元の要素数3 #数字は勝手に適当なものが入る julia> arrtwoint1 = Array{Int64,2}(undef,3,3) 3×3 Array{Int64,2}: 4592616224 4592617456 4592618576 4592616224 4592618576 4415784480 4413668112 4592617456 4592618576 julia> arrtwoint1 = [1 2 3; 4 5 6; 7 8 9] 3×3 Array{Int64,2}: 1 2 3 4 5 6 7 8 9 julia> arrtwoint1[2,2] #[2][2]ではない 5 julia> arrtwoint1[2,3] #2行目3列 6 julia> arrtwoint1[1:3] #1:3行目1列 3-element Array{Int64,1}: 1 4 7 julia> arrtwoint1[1:3,2] #1:3行目2列 3-element Array{Int64,1}: 2 5 8 julia> arrtwoint1[2,1:3] #2行目1:3列 3-element Array{Int64,1}: 4 5 6 julia> [[1,2,3],[4,5,6]] #これは2次元ではなく1次元配列なので注意 2-element Array{Array{Int64,1},1}: [1, 2, 3] [4, 5, 6] julia> [1 2 3; 4 5 6] #正しくはこう書く(行列) 2×3 Array{Int64,2}: 1 2 3 4 5 6
文字列を配列にする.
julia> li = split(str, ",")
配列はカンマ区切り
julia> an = [1,2,3] 3-element Array{Int64,1}: 1 2 3 julia> push!(an,4) #要素を追加 4-element Array{Int64,1}: 1 2 3 4 julia> pop!(an) #最後の要素を削除 4 julia> an 3-element Array{Int64,1}: 1 2 3
行列はスペース区切り
julia> an = [1 2 3] 1×3 Array{Int64,2}: 1 2 3 julia> an = [[1,2,3] [4,5,6] [7,8,9]] #要素の値に配列を入れれば2次元の行列になる 3×3 Array{Int64,2}: 1 4 7 2 5 8 3 6 9 julia> an = [1 2 3; 4 5 6; 7 8 9] #こちらも行列. しかし格納の順番(方向)が異なる 3×3 Array{Int64,2}: 1 2 3 4 5 6 7 8 9 #つまりJuliaではPythonのNumPyの機能が標準装備されている julia> ([1,2,3] == [1 2 3], [1,2,3] == [1; 2; 3]) (false, true) julia> (reshape([1,2,3,4,5,6],2,3) == [1 3 5; 2 4 6]) true #行列の回転 julia> mtr = reshape([i for i in 1:16],4,4) 4×4 Array{Int64,2}: 1 5 9 13 2 6 10 14 3 7 11 15 4 8 12 16 julia> rot180(mtr) #180度回す 4×4 Array{Int64,2}: 16 12 8 4 15 11 7 3 14 10 6 2 13 9 5 1 julia> rotl90(mtr) #90度左(left)に回すrotl90関数. 右に回すrotr90もある 4×4 Array{Int64,2}: 13 14 15 16 9 10 11 12 5 6 7 8 1 2 3 4 julia> rotl90(mtr,3) #回転数の指定もできる 4×4 Array{Int64,2}: 4 3 2 1 8 7 6 5 12 11 10 9 16 15 14 13 #応用 julia> reshape([i for i in 1:64 if i % 4 ==0],4,4) 4×4 Array{Int64,2}: 4 20 36 52 8 24 40 56 12 28 44 60 16 32 48 64
辞書(Dict)型
Dict(:a => 1, :b => 2)
辞書型. Dict()関数で作成する. Pairと呼ばれる=>で区切られる構造を引数として与えることで、リテラルっぽく書くことができる.
dict = Dict{Int64,Int64}() dict = Dict{Int64,Dict}() #valueを辞書型にすることもできる(これで2次元ハッシュみたいな).
初期宣言.
julia> Dict("a" => 1, "b" => 2) Dict{String,Int64} with 2 entries: "b" => 2 "a" => 1 julia> dict_test = Dict([("a",1),("b",2)]) #Tuple型の配列を入れてもいい Dict{String,Int64} with 2 entries: "b" => 2 "a" => 1
キーはStr,Int,Floatでもいいが、定義した型から外れる他の型は代入できない.
dict_test["a"] = "20" ERROR: MethodError: Cannot `convert` an object of type String to an object of type Int64 Closest candidates are: convert(::Type{T<:Number}, ::T<:Number) where T<:Number at number.jl:6 convert(::Type{T<:Number}, ::Number) where T<:Number at number.jl:7 convert(::Type{T<:Integer}, ::Ptr) where T<:Integer at pointer.jl:23 ... Stacktrace: [1] setindex!(::Dict{String,Int64}, ::String, ::String) at ./dict.jl:380 [2] top-level scope at REPL[76]:1
julia> dict_test["a"] = 20 20
forループでキーと値を取得 そのまま受けるとPair型のオブジェクト
julia> for item in dict_test println(item) end "b" => 2 "a" => 20
(key, value)形式で受ける
julia> for(name,price) in dict_test println("$name : $price") end b : 2 a : 20
特定の要素の有無を確認
julia> haskey(dict_test,"aa") false julia> haskey(dict_test,"a") true
値を取得する: get(collection,key,default)
julia> get(dict_test,"a",120) #default(120の部分)はオプショナルでなく必須. 20
julia> keys(dict_test) Base.KeySet for a Dict{String,Int64} with 2 entries. Keys: "b" "a"
julia> values(dict_test) Base.ValueIterator for a Dict{String,Int64} with 2 entries. Values: 2 20
要素の削除: delete! (要素削除後の辞書を返す)
julia> res = delete!(dict_test,"b") Dict{String,Int64} with 1 entry: "a" => 20
要素の削除: pop! (削除された要素の値を返す)
julia> dict_test["b"] = 4 4 julia> res = pop!(dict_test,"b") 4
二つの辞書をmergeする(後ろ優先になる)
julia> dict_test Dict{String,Int64} with 3 entries: "c" => 10 "b" => 4 "a" => 20 julia> dict_test2 Dict{String,Int64} with 2 entries: "b" => 200 "a" => 100 julia> println(merge(dict_test,dict_test2)) Dict("c" => 10,"b" => 200,"a" => 100) julia> println(merge(dict_test2,dict_test)) Dict("c" => 10,"b" => 4,"a" => 20)
タプル(Tuple)型
配列や辞書型と同じく複数の値を入れておくことができるコレクションの一つだが、後から内容の変更ができない(イミュータブルと言う).
a = tuple("a","b","c") a = ("a","b","c") #単に括弧でもいい julia> typeof(a) Tuple{String,String,String}
インデックス指定で値を取得できる
julia> a[1] "a"
名前つきタプル(NamedTuple)
julia> test_tuple = (a = 1, b = 2, c = 3) (a = 1, b = 2, c = 3) julia> test_tuple.a #こういう指定ができる 1 julia> test_tuple[3] #もちろんインデックス指定もできる 3
ペア(Pair)型
辞書型の要素となる A => B . 値の更新はできない.
julia> item = "Pencil" => 80 "Pencil" => 80 julia> item.first #firstで最初の要素 "Pencil" julia> item.second #secondで2番目の要素を指定できる 80
Dict()のなかにTuple型の配列を入れる場合でも、要素はPair型となる.
julia> stationary = Dict([("Pencil",80),("Eraser",50),("Ruler",100)]) Dict{String,Int64} with 3 entries: "Ruler" => 100 "Eraser" => 50 "Pencil" => 80 julia> for item in stationary println("$(item.first) : $(item.second)") end Ruler : 100 Eraser : 50 Pencil : 80
集合(Set)型
重複した要素を持たない. 順序がない. 和/積/差/対称差/部分集合/上位集合といった集合演算が使える.
julia> Set([3,1,2,3]) #重複した3は消える. Set([2, 3, 1]) #順番も適当.
配列も入れられる.
julia> [3x+5y for x = 1:3,y=3:4] 3×2 Array{Int64,2}: 18 23 21 26 24 29 julia> Set([3x+5y for x = 1:3,y=3:4]) Set([24, 23, 26, 29, 21, 18])
pushやpopも使える (順番はない).
julia> set_even = Set([2i for i in 1:3]) Set([4, 2, 6]) julia> push!(set_even,8) Set([4, 2, 8, 6]) julia> pop!(set_even) 4 julia> set_even Set([2, 8, 6])
存在確認 (in関数あるいは∈(\inをtab変換)や∋(\ni))
julia> in(6,set_even) true julia> in(5,set_even) false julia> 6 ∈ set_even true julia> set_even ∋ 9 false
和演算
julia> set_a = Set([1,2,3]) Set([2, 3, 1]) julia> set_b = Set([3,4,5]) Set([4, 3, 5]) julia> union(set_a,set_b) Set([4, 2, 3, 5, 1]) julia> set_a ∪ set_b #\cupをtab変換 Set([4, 2, 3, 5, 1])
積
julia> set_a = Set([1,3,4]) Set([4, 3, 1]) julia> set_b = Set([2,3,4,5]) Set([4, 2, 3, 5]) julia> intersect(set_a,set_b) Set([4, 3]) julia> set_a ∩ set_b #\capをtab変換 Set([4, 3])
差
#左辺のみに含まれる項を抽出 julia> setdiff(set_a,set_b) Set([1]) julia> setdiff(set_b,set_a) Set([2, 5]) #どちらかのみに含まれる項を抽出(対称差) julia> symdiff(set_b,set_a) Set([2, 5, 1])
部分集合 (右辺に左辺の値の全てが含まれているかの判定)
julia> set_a = Set([1,2,3]) Set([2, 3, 1]) julia> set_b = Set([1,3]) Set([3, 1]) julia> issubset(set_a,set_b) false julia> set_a ⊆ set_b #\subseteqをtab変換 false julia> set_b ⊆ set_a true
上位集合 (左辺に右辺の値の全てが含まれているかの判定)
julia> set_a ⊇ set_b #\supseteqをtab変換 true
関数
julia> function myfunc(a,b) return a*b end myfunc (generic function with 1 method) julia> myfunc(4,100) 400 #"return"がなくてもいい. julia> function myfunc(a,b) a*b a/b #この場合は最後の式が返される. end myfunc (generic function with 1 method) julia> myfunc(3,2) 1.5 #簡単な書き方もできる. julia> f(a,b)=a*b f (generic function with 1 method) julia> f(3,2) 6
default値(代入がなかった場合にそれを使う)を設定できる.
julia> f(a,b=5)=a*b f (generic function with 2 methods) julia> f(3,2) 6 julia> f(3) 15
引数を可変にする.
julia> function mf(a, b, v...) println(a) println(b) println(v) end mf (generic function with 1 method) julia> mf(3,2) 3 2 () julia> mf(3,2,5,6,7) 3 2 (5, 6, 7)
キーワード引数の指定
julia> function mf(a, b ; item = "Pencil", price = 80) println("$a, $b, $item, $price") end mf (generic function with 2 methods) julia> mf(3,2,item="Note",price=50) 3, 2, Note, 50
引数の型指定
julia> af(a,b::Int64) = a*b af (generic function with 1 method) julia> af(2,3) 6 julia> af(2,3.5) #Float型を渡したのでエラーになる. ERROR: MethodError: no method matching af(::Int64, ::Float64) Closest candidates are: af(::Any, ::Int64) at REPL[55]:1 Stacktrace: [1] top-level scope at REPL[57]:1
戻り値の型指定
julia> af(a,b)::Int64 = a*b af (generic function with 2 methods) julia> af(2,3) 6 julia> af(2,3.5) 7 julia> af(2.5,3.5) ERROR: InexactError: Int64(8.75) Stacktrace: [1] Type at ./float.jl:703 [inlined] [2] convert at ./number.jl:7 [inlined] [3] af(::Float64, ::Float64) at ./REPL[58]:1 [4] top-level scope at REPL[61]:1
複数の戻り値
julia> function myfunc(a,b) return a*b, a/b, 2a+3b end myfunc (generic function with 1 method) julia> myfunc(3,2) (6, 1.5, 12)
受け取る側もカンマ区切りにするとタプルがアンパックされる.
julia> res_1, res_2, res_3 = myfunc(3,2) (6, 1.5, 12) julia> println("$res_1 : $res_2 : $res_3") 6 : 1.5 : 12
タプルで返すのであれば、インデックス指定もできる.
julia> myfunc(3,2)[2] 1.5
無名関数
julia> a -> a^3 + a*3 #10 (generic function with 1 method)
map関数と一緒に使う. もちろん普通に定義した関数も使えるが、簡単な式の場合は無名関数で十分.
#配列を渡す. julia> map(a -> a^3 + a*3, [4, 2.5, -3]) 3-element Array{Float64,1}: 76.0 23.125 -36.0 #タプルを渡す. julia> map(a -> a^3 + a*3, (4, 2.5, -3)) (76, 23.125, -36)
無名関数を変数に格納することもできる.
julia> lambda = a -> a^3 + a*3 #18 (generic function with 1 method) julia> map(lambda, (4, 2.5, -3)) (76, 23.125, -36)
多重ディスパッチ 複数のメソッドを同じ関数に入れることができる.
julia> function mf_dis(a::Int64) return a^3+a*3 end mf_dis (generic function with 1 method) julia> function mf_dis(a::String) println("Argument : $a") end mf_dis (generic function with 2 methods) julia> function mf_dis(a,b) return a*b end mf_dis (generic function with 3 methods)
渡す引数によってどれを実行するか選択できる.
julia> mf_dis(2) 14 julia> mf_dis("test") Argument : test julia> mf_dis(2,4) 8
構造体
イミュータブル(更新不可)のstuructと ミュータブル(更新課)のmutable structがある.
julia> struct Kitchenware item price::Int64 stock end
インスタンスを作成する.
julia> Kitchenware1 = Kitchenware("Bowl",100,10) Kitchenware("Bowl", 100, 10)
型は構造体名になる.
julia> typeof(Kitchenware1) Kitchenware
メンバの型が宣言と合わないとエラーになる.
julia> Kitchenware2 = Kitchenware("Ladle",150.2,5) ERROR: InexactError: Int64(150.2) Stacktrace: [1] Type at ./float.jl:703 [inlined] [2] convert at ./number.jl:7 [inlined] [3] Kitchenware(::String, ::Float64, ::Int64) at ./REPL[82]:2 [4] top-level scope at REPL[85]:1
値の参照は.メンバ名でする.
julia> Kitchenware1.item
"Bowl"
mutable struct
julia> mutable struct Tableware item::String price::Int64 stock::Int64 end julia> tableware1 = Tableware("Cup",120,30) Tableware("Cup", 120, 30) julia> tableware1.item "Cup" julia> tableware1.price 120
値の更新ができる.
julia> tableware1.stock = 29 29
構造体の配列を作成する.
julia> arr_kitchenware = Array{Kitchenware}(undef,3) 3-element Array{Kitchenware,1}: #undef #undef #undef
julia> arr_kitchenware[1] = Kitchenware("Bowl",100,10) Kitchenware("Bowl", 100, 10) julia> arr_kitchenware[2] = Kitchenware("Ladle",150,5) Kitchenware("Ladle", 150, 5) julia> arr_kitchenware[3] = Kitchenware("Flying pan",3500,6) Kitchenware("Flying pan", 3500, 6) julia> arr_kitchenware[3].item "Flying pan"
宣言した要素数以上入れようとするとエラーになる.
julia> arr_kitchenware[4] = Kitchenware("Kettle",1000,3) ERROR: BoundsError: attempt to access 3-element Array{Kitchenware,1} at index [4] Stacktrace: [1] setindex!(::Array{Kitchenware,1}, ::Kitchenware, ::Int64) at ./array.jl:766 [2] top-level scope at REPL[97]:1
push!関数なら要素の追加ができる.
julia> push!(arr_kitchenware, Kitchenware("Kettle",1000,3)) 4-element Array{Kitchenware,1}: Kitchenware("Bowl", 100, 10) Kitchenware("Ladle", 150, 5) Kitchenware("Flying pan", 3500, 6) Kitchenware("Kettle", 1000, 3)
簡単な形式.
julia> mutable struct Tableware item::String price::Float64 stock::Int64 end julia> arr_tableware = [Tableware("Cup",108.5,30),Tableware("Spoon",210.1,50),Tableware("Dish",1041.3,10)] 3-element Array{Tableware,1}: Tableware("Cup", 108.5, 30) Tableware("Spoon", 210.1, 50) Tableware("Dish", 1041.3, 10)