GitLabを解析ログとして使うと良いのではないかという話

データ解析のログをどうやったら効率的に取れるのか、なかなか解が見つからないものです。どうすれば解析の再現性が得やすいか、やったことをまとめられるか、時系列に出来るか、やらなければならないことをリストアップ出来るかなど、本来悩まなくて良いところにリソースが割かれてしまいます。

もちろん、解析ログのとり方の正解は人によって異なります。手書きノートに絵を貼ってペンで書くのが良い人もいれば、私みたいな面倒くさがりな人はやれ印刷して、切って、貼って、書いて、、、というのがしんどい人もいます。

そこで、血迷って解析ログを色々なところにぶちまけた私が最近たどり着いた?と思える解を紹介したいと思います(今年のGWは、東京ではStay home week, 神奈川ではGW(がまん week)らしいので、時間がある今、こう使うつもりでやっているんだよ、と自分への戒めを込めて書きます)。

GitLabという選択肢

GitLabはプロジェクトの管理を行えるWebアプリケーションです。GitHubとほぼ同じ機能を持ちつつ、オンプレサーバーにタダで(Community Edition)インストールすることが可能です。つまり、制約がなく(GitHubもかなりFreeプランでも制約がなくなってきましたが)プロジェクトの管理が出来ます。

前提としては複数の人数でプロジェクトを円滑に回すための機能が充実していますが、基本はソロプレイ(コードを触っている、という意味でです)の解析でも上手く使えば案外イケるのでは、と思いたちました。

失敗例

これまでの取り方の失敗例を上げてみます。

  • 手書きのノート

    • 絵を印刷して切って貼る作業が辛くなる
      • 次第に貼る絵を絞り過ぎて薄くなっていく
    • ノートを家に忘れると地獄
    • ミーティングで見せにくい
      • 結局電子化の二度手間
      • (でも、スライドとしてまとめるのは重要な気はする)
  • Word的なもので上から下にひたすら絵と文章を書き連ねる

    • どこでトピックが切れるかなどが分かりにくい
      • indexを作れば良いのだが…
    • どの情報が重要なのか分からない
      • 連ねていくうちにファイルが重くなる
  • One noteでトピック毎に分けてみようとする

    • 時系列がとにかく追いにくい
      • Last updateでSortするとTopicでバラバラになる
    • トピックをどう分ければ良いかの基準が分からない
      • 結果としてバラバラになる
    • 結局あの時の解析の絵はどこだと探し回ることになる

これを読んで分かるかと思いますが、私はとにかく面倒くさがりでだらしない人なんです。。。これらの方法で出来ている人はたくさんいると思います。

こんな人間でも、きちんとプロトコルを決められるようにすれば、出来るのではないかと試行錯誤して、GitLabにたどり着きました。

GitLabの利点

利点を列挙していきます

高い再現性の保持

データ解析で重要なのは、解析に再現性を保つことだと思います。物書きをしなければならないときに

あの時のヒストグラムを、軸を直して作り直さなければ

となることがあるかと思います。そういった時に、色々とパラメータを変えてしまって、あの時の状態と同じ絵を出すのに苦労した経験があります。これはとても時間の無駄です。しかし、これはGitで

  • ソースコード
  • マクロ
  • steeringファイル
  • Parameterファイル

全てを管理しておけます。そして、commit hashをIssueに貼り付けておけばそれが参照出来てDiffも取れるので、便利だと思います。

解析のトピックを管理しやすい

One NoteやDocumentファイルでログを取っていてもこれは実装可能なのですが、GitLabのIssueを使えばトピック分けがしやすい気がします。 IssueにはOpen/Closeの概念があって、トピックの切れを明確に・具体的に定義しやすいのです。

例えば、

PlasticのTimingをBeam triggerで確認する

というIssueを立てます。このIssueのDescriptionにはIssue closeの定義を書いておくと、このIssueではこれをやらなければならないことが分かるし、逆に読み返した時にこれを読めばここまでの事が書いてあるというのが分かります。 Issueはテンプレートを作っておけます。これを作っておけば、穴埋めするだけという易しい仕様です。

私はこのようなIssueのテンプレートを用意しました。Repositoryの頭から.gitlab/issue_template/analysis_issue_template.mdを作ります。

# このIssueの目的

# このIssueのCloseの定義

- [ ] task

## 懸念事項

## 見積もり事項

# まとめ
(Closeする時にまとめを作る)

## 使用したデータセット

## commit hash

## content

gitlab_issue_temp

このように、Issueのテンプレートが呼び出せるようになります。 また、IssueのDescriptionにcheck boxを埋め込むと、それが自動的にTasklistとして定義され、Check boxがどれだけ埋まっているかが明確になります。私はこれをIssueのCloseの定義に入れています。このCheck boxを埋めるように解析し、それが終わればSystematicにIssueをClose出来るようになるからです。

解析内容のラベリングが出来る

IssueにはLabel機能があります。これを大まかなカテゴライズとして使えば(例えば"Detector Tune”, “Optics”, “Calibration"など)、自動でIssueが整理されます。

Milestoneをかける

解析は闇雲にやるのではなく筋道立ててやる必要があります。また、大目標を設定し、その間にある小目標を適切に設定することが大事です。 そこで、Milestones機能を使えば、大目標を立てられます。大目標を設定したら、そこへ向かう小目標が出てきます。この小目標がIssueに対応するようにすれば良いわけです。各IssueはMilestoneと紐付け出来て、Progressもひと目で分かるようになります。

Wikiに解析内容のIndexを作れる

GitLabではProject単位でWikiを建てられます。このWikiを、解析内容(Issue)の結果をIndexとしてまとめておけば、これまで苦労していた管理がある程度楽になるのではないかと思います。

私は最近、これまでの失敗例を踏まえて、解析のStoryもWikiで記録することにしました。こういうことを確認したいからこのIssueを立てたという背景を簡単に書いておき

  • Issueの番号
  • そのIssueに関するWiki page link
  • そのIssueでやった解析の結果を完結にさせたもの

を本文中に入れておくと良いと思います。

私はIssue毎にsub sectionに分けて書くことにしました。すると、wikiの本文中に[[_TOC_]]と書くだけで目次を作ってくれるからです。

あとは、ざっくりとした見積もりに必要な数値をまとめたページも作ると良いと思います。例えば焦点面間の距離とか、解析対象のBeamのエネルギー・速度だとかをまとめておくと結構役に立ちます。

CollaboratorをProjectに招待すると、解析ログをシェア出来る

実験のコラボレーターの方をProjectに招待すると、その方もこのIssueなどを見ることが出来るようになります。また、解析ログやMilestoneなど、解析に必要な情報がこのProject全てにまとまっているので、情報共有も容易です。また、相手方が通知をOnにしていると、解析ログを自動で送りつけてくれます。これがメリットになるかは使う人次第ですが……。ただ、コメントしてもらうなども期待できます。

Issue, Milestoneに〆切を決められる

私、この時間管理が特に苦手です。一度立てた目標が時間的に破綻するとシュンとなってします。無理のないように、ただこの週までに終わらせなきゃという時間目標が設定できます。

Markdown記法で書ける

Markdownで書けるのは楽ちんです。GitLabではKaTeXが使えるので、TeX記法の数式も書けます。また、解析ではコードの中身を記述することが多いので、codeタグもよく使います。最近はこのブログ(Hugo), Qiita, GitLabなど、殆どMarkdownで書いています。

画像UploaderがAPIにて実装されている

これは最近知ってとても便利と感じ早速使っているのですが、GitLabではIssueなどに貼り付けるための画像をAPI経由でUpload出来るんです。これはオンプレに導入するGitLab CEでも使えます。これまでのことはぶっちゃけGitHubでも出来るのですが、API経由でのattach fileのUploadは(私が現時点で確認した限りは)GitLabでしか出来ないようです1。 この機能の使い方を詳しく説明します。

まずは、APIにAccessするためのPrivate tokenを取得します。GitLabにアクセスして、右上のアバターをクリックしてからUser settingsを選びます。

gitlab_setting

次に、sidebarからAccess Tokensを選択し、Name, Expires atを指定し、Scopesのapiにチェックを入れてCreate personal access tokenをクリックします。

gitlab_api_token

また、Upload先のProject IDを覚えておきます。

これで準備は完了です。Terminalで、以下のようにコマンドを叩きます。

curl --request POST --header 'PRIVATE-TOKEN: (api token)' --form 'file=@(image path)' https://(GitLab Host)/api/v4/projects/(Project ID)/uploads

送信が完了すると以下のようなJSONが返ってきます。

{"alt":"hoge","url":"/uploads/a67a40cdc92c15441fcbd81b189cb13a/hoge.png","markdown":"![hoge](/uploads/a67a40cdc92c15441fcbd81b189cb13a/hoge.png)"}

このJSONのmarkdown keyの値をIssueなどに貼り付けてPreviewをすると

gitlab_upload_img

このように、正しくアップロード出来ています。

この機能をartemisのcommand upload として実装しました。現在、使えるようになります。宣伝のためにもここに使い方を書いておきます。

このコマンドはsaveコマンドと一緒に使います。先程作ったAccess tokenをどこかのファイル(ここでは~/art_analysis/.gitlab_api_token)に保存しておきます。もしこのファイルをGit管理下にあるディレクトリに置く際には.gitignoreにこのファイルを追加しておくことを強く推奨いたします。

次に、artemislogon.Cに以下を追加します。

   TCatCmdFactory *cf = TCatCmdFactory::Instance();
   // ...... (add the other commands) ......
   art::TCmdSave *cmdsave = art::TCmdSave::Instance();
   cmdsave->SetDefaultDirectory("figs") // Do NOT include ~ charactor when you use upload command. If you specify the home directory, please write by absolute path.
   cmdsave->SetAddDateDir(kTRUE);
   cmdsave->SetAutoName(kTRUE);
   cmdsave->AddFormat("png",1); // specify '1' at the 2nd parameter
   // ...... (Add format)
   cf->Register(cmdsave);

   art::TCmdUpload *cmdupload = new art::TCmdUpload();
   cmdupload->SetUploadURL("(GitLab host)/api/v4/projects/(project ID)/uploads");
   cmdupload->SetPrivateTokenFile(".gitlab_api_token");
   // --- (option) command for copying to clipboard ---
   cmdupload->SetClipBoardAccessCommand("xsel -bi");
   cmdupload->UseTmux(kTRUE); // if you use tmux & want to copy to clipboard, please add
   // --- end option ---
   cf->Register(cmdupload);

このコマンドはXのクリップボード共有を用いて、出力結果のMarkdownをクリップボードにコピーするところまで自動化しています。その際にはホストにxselxclipなどのソフトウェアをインストールして、SetClipBoardAccessCommand("xsel -bi")などとクリップボードに入力するコマンドを指定します。Xを使用するので、クライアントにX serverを導入するのと、SSHで接続する時には-X optionをつけてX Forwardしてください。また、VNCを使っている場合、DISPLAYを指定しないとXのクリップボードにアクセス出来ません(詳しくは私のQiitaでの記事に書いてあります)。tmuxを使っている場合はUseTmux(kTRUE)とするだけで何の問題もありません。

これで使える準備は出来ました。artemisを起動させてHistogramになにか書きます。その後に

artemis [] save
artemis [] upload

とすると、

artemis [] upload
Info in <art::TCmdUpload::Run>: upload image file: figs/20200501/1588344333.pngto https://(GitLab URL)/api/v4/projects/(Project ID)/uploads
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 24042  170   170  100 23872    553  77718 --:--:-- --:--:-- --:--:--  143k
Upload completed. Markdown:
![1588344333](/uploads/xxxxxxxxxx/1588344333.png)

という感じでMarkdownが表示されます。これをIssueなどに貼り付ければOKです。クリップボードの設定が上手くいっていれば、自分のクライアントのクリップボードにもこのMarkdownがセットされていることでしょう。

このコマンドのもう一つの利点は、MarkdownのAltの名前がファイル名になっているので、もしsaveコマンドでROOTファイルのフォーマットも保存していれば、オブジェクトをそのまま引っ張り出せることにあります。 例えば軸ラベルを直しただけでarticleに貼りつける時には、Issueを見てこのファイルのCanvasオブジェクトを取得し、再PDF化するだけで良い、なんて事が出来ます。

一つのツールとして完結している

これまで書いたそれぞれの機能をこのGitLab一つでやれます。

ノートを取るのはこのアプリで、スケジュール管理はこのアプリで、それを紐付けして、、、と、分散していくとそれだけで面倒くさい。 それが一極集中になるのはとても良いことだと思います。

さいごに

データ解析って一人でしか開発していなくても普通にプロジェクトなんですよね。だからこそ、このように色々と整っているものを上手く使えば、きっとまとまった情報源になれる気がします。

ここに触れてはいませんが、GitLabはCI(継続的インテグレーション)ツールもあるので、これを使ってコードの品質を保っておくことが出来ます(今は解析では使っていませんが、他の要件でCIを使っています)。

ちなみに、2020/05/22 にGitLabv 13.0がリリース予定なのですが、これで、オープンソース(Free)版のGitLabでIssueの紐付けが出来るようになるらしい。これはめちゃくちゃ便利そう(公式) ある作業中に新たな問題が生じた時に親をある作業Issueにして、子供のIssueを立てられるよう。早く使ってみたいです!

(5/28 追記) GitLab 13.0にupdateしましたが、まだOpen source版では使えないみたいですね。ただ、公表はされているので、近々のUpdateで実装されると思います。。。

まだこの形式始めて数ヶ月しか経っていないのですが、これを書いているうちに「もっとこうした方が良いかも」とか思えた分だけ(私自身にも)この記事には価値があると思いました(実は、偉そうに書いていてやってなかった部分があるので、これから追記していきます)。

良いなと思ったあなた、是非GitLabをお試しを! GitLab.comでも良いし、オンプレサーバーはラズパイとかでも出来るらしいですよ。


  1. GitHubではcommitを伴うファイルのアップロードは出来ますが、ここで紹介するような使い方は出来ません ↩︎

Shoichiro Masuoka

CNS, the Univ. of Tokyo. Dcotoral student

関連項目