バイオインフォをやっている大学院生です。プログラミングのことなどを書きます。

Mac で接続した HDD を自動でマウントしない方法

TimeMachine を使って、HDD にバックアップをしているのですが、複数の Mac を使っているため、Mac によってマウントしてほしい HDD が違います。

しかし、ディスプレイをハブとして使用していて、いちいち HDD とディスプレイの接続を切り替えるのは面倒です。

ということで、指定した HDD が自動でマウントがされないようにする設定をしました。

ちなみにこの方法はパーティティションで指定ができるので、一つの HDD に複数のパーティティションが存在している場合でも使用できます。

全体の流れはこのようになります。

  1. UUID を確認する
  2. vifs で自動でマウントしないように設定する

1. UUID を確認する

ディスクユーティリティから確認する方法

まず、UUID を調べたいディスクを選択します。

情報をクリックすると、そのディスクについての情報の一覧が開きます。

その中のファイルシステム UUID という項目を控えておいてください。

ターミナルから確認する方法

diskutil info [ボリューム名]|grep UUID

複数の UUID が表示される場合があると思いますが、そのうちの Volume UUID という項目を控えておいてください。

2. vifs で自動でマウントしないように設定する

UUID が分かったら、次は vifs コマンドを使用して設定を行います。

ターミナルから次のコマンドを実行します。

sudo vifs

パスワードを要求された場合は入力してください。

エディタが開くので、次のように入力し保存します。

UUID=[取得した UUID] none auto noauto

それぞれの項目がどんな意味かはここを参照してください。

(Linux) fstabの書式 主要オプションなど | hara-chan.com

以上の手順により、自動でマウントがされなくなっているはずです。

手動でマウントを行う方法

ディスクユーティリティからマウントのボタンを押せば、手動でマウントをすることが可能です。

ターミナルからマウントをするには

diskutil mount [ボリューム名]

ただし、ロックされた APFS ボリュームをマウントする場合は次のコマンドを使用する必要がありました。

diskutil apfs unlockVolume [ボリューム名] -passphrase [パスフレーズ]

Macでファイルの作成日時・更新日時を取得するコマンド

Macでファイルの作成日時などをまとめて表示させたい場合の方法。

stat -f "access:%Sa%nmodified:%Sm%ninode changed:%Sc%nbirthtime:%SB" test.txt

でできる。出力は

access:Nov 17 19:28:34 2020
modified:Nov 17 19:28:33 2020
inode changed:Nov 17 19:28:33 2020
birthtime:Nov 17 19:28:30 2020

のようになる。

コマンドの説明

stat がファイルの属性や作成した日付などを表示させるコマンド。
-fは出力のフォーマットの指定を表す。フォーマットを表すのが次の文字列。

フォーマットの説明

%a - アクセス日時
%m - 更新日時
%c - inodeが変更された日時
%B - ファイルを作成した日時
これらに対して、%SaのようにSをつけることで、、unix時間ではなく、読みやすい表記で表示されるようにしている。
フォーマットだと、\nではなく%nが改行になっているので注意。

Excelでセルをボタンにしてマクロを実行させるVBA

やりたいこと

f:id:feb_march:20200606160354p:plain
イメージ
このセルをダブルクリックすると、この上に新しい行を追加するマクロが実行されるようにしたい。(今回は行を追加することを目的とするが、マクロの中身は行を新しく追加するものである必要はなく、任意のマクロを行わせることができる。)

基本的な流れはここの内容を参考にした。 しかし、この記事で紹介されているボタンでは、セルの値が固定されている必要がある。行を追加する動作をさせたいので、ボタンの位置が移動してしまうのでこのままでは使えない。また、このボタンを複数個作成するので、関数を複数定義するのもいまいち。

そこで、ボタンの場所ではなく、値が"add row"であるセルをダブルクリックときに行を追加するマクロが実行できるようにする。

方法

まず、作業するブックで、マクロを有効であるとする。Excel2007以降は、拡張子がxlsxだとマクロなしになっている。もしxlsxだったら、拡張子をxlsmにして保存し直す。 なお、MacExcelで作業をした。Windowsの場合とはマクロの設定方法など細かい違いがあるかもしれないが、基本的には同じやりかたで可能だと思う。

1. ボタンを押したときに実行するマクロの定義

まず、ボタンを押したとき呼び出したいマクロを定義する。

f:id:feb_march:20200606161413p:plain
Mac版のばあいでのマクロの登録
新しいマクロの登録は、ツール→マクロ→新しいマクロの記録というところからできる。今回は選択したセル(ボタンにしたセル)をクリックしたときに、その上に新しい行を追加したい。だから、適当なセルを選んでおいて、マクロの記録を開始したら、右クリック→挿入→行全体を選択して、セルの上に新しい行を追加する。これでマクロの記録は終わりで、マクロの名前はadd_rowとしておく。

2. ボタンの作成

セルにしたいボタンに対して、"add row"と入力する。なお、これから"add row"と書かれたセルをボタンと判別するVBAをかくことになるので、ボタンの値は他のボタンでないセルとかぶらないように注意する。たとえば、"____add row____"などにすることで、偶然他のセルと値が被ってしまう可能性を下げられるだろう。 なお、見た目をボタンっぽくする方法はここで紹介されている。やってみたい方はここを参照してやってみてほしい。

kokodane.com

3. VBAの作成

"add row"と書いてあるセルがダブルクリックされたときに、1.で定義したマクロ"add_row"が呼ばれるVBAを書く。 まず、ツール→マクロ→Visual Basic Editorを開く。 機能を追加したいシートを左側のファイルナビゲータから開くと、エディタが表示される。そこに次のコードをかく

Private Sub Worksheet_BeforeDoubleClick(ByVal Target As Range, Cancel As Boolean)
If Not (Target.Value = "add row") Then Exit Sub
add_row
End Sub

2行目の"add row"は2.でボタンにしたセルの値を入力する。3行目は行いたいマクロの名称を指定している。マクロを他の名前で登録していたら、それに応じてなおしてほしい。

VBA script
VBAスクリプト

上の選択項目も画像のように直す。

テスト

"add row"としたセルをダブルクリックして、上に行が追加されることを確認した。また、このセルをコピペして他の場所にうつしても、同様に動作することを確認した。

GASで無料で定期的に実行するSlackボットを作る

Slackに定期的に投稿をするボットを作ります。

今回はSlackのWebAPIを設定して、Google Apps Script(GAS)からslackへ投稿する方法を紹介します。

GASはGoogleのサーバー上で動くサービスで、無料で使うことができます。 (制限があるので注意。すごく頻繁にやったりしなければslackのbotくらいなら引っかからないと思います。

【GAS】Google Apps Scriptで注意すべき制限まとめ【実行回数・時間・容量】 | monoblog )

f:id:feb_march:20200409211948j:plain
やり方イメージ

slackアプリの作成

まずSlackアプリの作成から始めます。

api.slack.com

このページのCreate New Appというボタンを押します。

f:id:feb_march:20200409212239p:plain

するとこのような画面が出てくるので、作りたいアプリの名前と、そのアプリをどのワークスペースに紐づけるかを設定します。ブラウザでログインしていないワークスペースは選択できるワークスペースに出てこないので、Sign in to another workspaceというところから目的のワークスペースにログインしてください。これでアプリの作成は終わりです。

アプリの権限の設定

次に作成したアプリで、投稿に必要な設定をします。左側のメニューから、OAuth&Permissionを開いてください。その中のScopeの設定で、Bot Token Scopesの設定を行います。この設定は、このアプリに与える権限を設定します。

f:id:feb_march:20200409213120p:plain

いま、channels:read、chat:write、chat:write.publicという3個のスコープを設定しました。chat:write.publicに関しては、このbotがメンバーでないチャンネルであっても投稿することを許可します。このアプリが投稿できるチャンネルが絞られているのであれば、chat:write.publicのスコープは必要ありません。

では、OAuth&Permissionsの一番上のほうにある、Install App to WorkSpaceを押してください。今設定したスコープに応じて、権限が要求されるので、問題がなければ許可して進んでください。

インストールが終わると、Bot User OAuth Access Tokenが表示されます。このトークンが投稿するのに必要なので、どこかにメモしておいてください。他の画面に映ってしまっても、この画面にくればいつでも確認することができるので安心してください。

インストールできたら、投稿したいチャンネルにアプリを追加してください。chat:write.publicのスコープを追加していなかった場合、アプリは自分が追加されていないチャンネルには投稿ができないので、投稿ができません。

curlで投稿するテスト

とりあえずcurlコマンドで投稿できるかやってみましょう。ターミナルから、下のコードを実行してください。

url -X POST -d "Content-Type: application/json" -d "token=TOKEN" -d "channel=CHANNELNAME" -d "text=hello" https://slack.com/api/chat.postMessage

TOKENをさきほど取得したBot User OAuth Access Tokenに置き換えてください。CHANNELNAMEは投稿したいチャンネルの名前です。チャンネル名の前の#はあってもなくても大丈夫です。 うまくいっていれば次のように投稿ができます。

f:id:feb_march:20200409215001p:plain

なお、Windowsの場合はcurlコマンドがデフォルトで入っていないそうなので、試すにはインストールが必要になります。面倒だったらここは飛ばして、次パートでGASからの投稿をしてしまうのでいいでしょう。

GASを使って定期的に実行する

Google Apps Scriptを使って、定期的に実行することができるようにしましょう。GASはGoogleのサーバーで実行され、サーバーを自分で準備したりすることなく、手軽に実行環境を用意することができます。 まずGoogleDriveにアクセスして、適当なところで右クリックしてその他からGoogle Apps Scriptを選択してください。

まずトークンを設定します。ファイル->プロジェクトのプロパティ->スクリプトのプロパティにアクセスして、tokenという名前でアプリのトークンを入力してください。 エディタを次のように編集します。MESSAGEを自分が投稿したい文章に、CHANNEL NAMEを投稿したいチャンネル名に変更してください。

var token = PropertiesService.getScriptProperties().getProperty("token")
var text = "MESSAGE"
var channel = "CHANNEL NAME"
function post_to_slack() {
  post(text,  channel)
}

function post(text, channel){  
  var data = {
    "text":text,
    "channel":channel
  }
  var options = {
    "method":"post",
    "contentType":"application/json",
    "headers":{"Authorization":"Bearer "+token},
    "payload":JSON.stringify(data)
  }
  var ret = UrlFetchApp.fetch("https://slack.com/api/chat.postMessage",options)
  Logger.log(ret)
}

できたら、上のタブから実行→関数を実行→post_to_slackを選択して、このスクリプトを実行してください。slackに投稿できたら大丈夫です。 次に、定期的に実行させるために、トリガーの設定を行います。上のタブから編集→現在のプロジェクトのトリガーを選択してください。

f:id:feb_march:20200409220822p:plain
GASのトリガーの設定
このように設定すると、毎日午後7~8時の間にコードが実行されるようになります。

おまけ: Pythonからの投稿例

Pythonから投稿する場合のコード例です。

import requests
import json

d = {}
d["text"] = "Hello"
d["channel"] = "CHANNEL NAME"

token = "your token"
h={}
h["Authorization"] = "Bearer "+token
h["contentType"] = "application/json"

r = requests.post("https://slack.com/api/chat.postMessage", data=d, headers=h)

 

VSCodeでC++のコードのコンパイルがうまくいかない

C++のコードをコンパイルするタスクが突然動かなくなってしまい、調べても解決方法がでてこなかったので備忘録です。

状況

昨日まで使っていた下のようなタスクが動かなくなりました。Macを使用してます。

"tasks": [
        {
            "label": "gnu_build",
            "type": "shell",
            "command": "/usr/local/bin/g++-9",
            "args": [
                "-std=gnu++1y",
                "-Wall",
                "-o",
                "${fileDirname}/${fileBasenameNoExtension}.exe",
                "${file}"
            ],
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": [
                "$gcc"
            ]
        }
    ]

/usr/local/bin/g++-9 -std=gnu++1y -Wall -o "作成される実行ファイルのフルパス" "コンパイルしたいファイルのフルパス"をシェルで実行するタスク。
テスト用のスクリプトtest.cppはこの通り。

#include <iostream>

int main()
{
    std::cout << "Hello" << std::endl;
    return 0;
}

タスクをVSCode上で実行すると、エラーメッセージ

collect2: fatal error: cannot find 'ld'
compilation terminated.
The terminal process terminated with exit code: 1

/usr/local/bin/g++-9 -std=gnu++1y -Wall -o "作成される実行ファイルのフルパス" "コンパイルしたいファイルのフルパス"をターミナルを開いて実行するとコンパイルできた。 ターミナルで次のように実行。

$ which ld
/usr/bin/ld

VSCodeでのパスが問題っぽい。

Code->Preferences->Settingsをひらく。Userのタブからsetting.jsonを適当なところから開く(デフォルトのままなら多分~/Library/Application Support/Code/User/settings.jsonになるはず)。

"terminal.integrated.inheritEnv": false

となっていた。デフォルトはtrueなので、設定をうっかり変えてしまっていたらしい。ここをtrueにしたらコンパイルできるようになった。
ちなみにこの設定項目についての説明は
Whether new shells should inherit their environment from VS Code. This is not supported on Windows
となっている。これだけだとよくわからないが、下のリンクで説明してくれている。
日本語メモ:June 2019 (version 1.36) / Visual Studio Code Updates - やまだのブログ

Rで標本分散、標準偏差、CVを計算する

Rでvarやsdで計算されるのは標本分散、標本標準偏差ではなくそれぞれ不偏分散と不偏標準偏差になります。 nをサンプル数、\overline{x}を平均値とします。

標本分散

f:id:feb_march:20200123155543p:plain

標本標準偏差

f:id:feb_march:20200123155555p:plain

不偏分散

f:id:feb_march:20200123155603p:plain

不偏標準偏差

f:id:feb_march:20200123155615p:plain

標本分散と標準偏差、ついでにCV(coefficient of variation, 標準偏差/平均)を求める関数は下のようになります。

# 標本分散
sample_var <- function(x,...){
    return(var(x,...) * (length(x)-1) / length(x))
}

# 標本標準偏差
sample_sd <-function(x,...){
    return(sd(x,...) * sqrt((length(x)-1)/length(x)))
}

# 変動係数
cv <- function(x,...){
    return(sample_sd(x,...)/mean(x))
}

参考
http://cse.naro.affrc.go.jp/takezawa/r-tips/r/59.html

Rのplotの色指定方法まとめ(量的データの場合)

量的データのプロットに関して、色を付ける方法を紹介する。また、凡例をどうつければいいか一例を示す。なお、データがカテゴリカルデータの場合はこちらの記事をみてほしい。 f:id:feb_march:20191027215511p:plain

グレースケールで表示する方法

gray
グレースケール
gray(level)(levelは0から1の間)で指定できる。0で黒、1で白になる。

RGBで指定する方法

赤、緑、青の値で色を表現する。Rではrgb(red,green,blue)で指定する。デフォルトだとそれぞれの色は0から1の間にする必要がある。rgb(red,green,blue,maxColorValue=255)とするとそれぞれの色の範囲を0から255として指定できる。

red, green, blueのパラメータのうちの一つを変化させた。他の二つのパラメータは0
red, green, blueのパラメータのうちの一つを変化させた。他の二つのパラメータは1

HSVで指定する方法

hsv
HSVによる色の指定
HSVはhue(色相)、saturation(彩度)、value(明度)によって色を表現する。RGBの場合と同じように、hsv(hue, saturation,value)によって指定できる。上の図は、3つのパラメータのうち一つだけを0から1へ変化させた場合の色の変化を示したもの。なお、変化させない2つのパラメータは共に1である。

colorRampを使う方法

colorRamp
colorRampによる色指定の例
colorRampでは、複数の色を指定して、それらの色のグラデーションを用いて表すことができる。図は上から順に、

pal = colorRamp(c("blue", "red"), space="rgb")
pal = colorRamp(c("blue","white","red"),space="rgb")
pal = colorRamp(c("blue","green","yellow","orange","red"),space="rgb")

として色を指定した。このとき、palは0から1の数値を引数に取りその値に対応するRBG値を返す関数である。

凡例の付け方

一番上の散布図の凡例はSDMtoolsというライブラリのlegend.gradientという関数を用いて書いた。

pnts = cbind(x =c(2.5,3,3,2.5), y =c(3,3,2,2))
legend.gradient(pnts,
    cols=apply(colorRamp(c("blue","yellow","red"),space="rgb")(0:100/100)/256,1,function(x){rgb(x[[1]],x[[2]],x[[3]])}),
    limits=c(0,1),
    title=""
)

pntsは凡例の位置、colsは描画するのに使う色(2色以上で今は101色)、limitsは値の範囲、titleは凡例の題名。

使ったコード

https://github.com/kubotam-m/R_codes/blob/master/color_test.R