OmniAICreator/Qiita-1.07M huggingface dataset:
matplotlib エラーバー付きのグラフを描く

# 概要

グラフにエラーバーをつけたいことは多々ありますよね。
今回はグラフにエラーバーをつけて、検量線を描くことを目標とします。

# データの用意

```python

from matplotlib import pyplot as plt
import random
import numpy as np
from sklearn.metrics import r2_score

## テストデータの作成
x = [i+random.uniform(-0.2, 0.2) for i in range(5)] # 変数を初期化
y = [i+random.uniform(-0.5, 0.5) for i in range(5)]
x_err = [random.uniform(-0.5, 0.5) for i in range(5)] # 誤差範囲を乱数で生成
y_err = [random.uniform(-0.5, 0.5) for i in range(5)] 

```

# y軸方向にerror barを設定

もっとも多く使うのはy軸方向にerror barを設定するケースだと思います。
``plt.errorbar``の``yerr``に誤差の入った配列を設定します。以下によく使う引数をまとめました。


| 引数       |       意味 |
|:-----------------|------------------:|
| x            |              x軸の値(配列) |
| y            |              y軸の値(配列) |
| xerr            |              x軸の誤差の値(配列) |
| yerr            |              y軸の誤差の値(配列) |
| fmt | マーカーの表示, 'o', 'v'など　[詳しくはこちら](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.plot.html#matplotlib.pyplot.plot)|
|markersize | マーカーの大きさ|
|color | マーカーの色|
|markeredgecolor | マーカーの縁の色|
| ecolor | エラーバーの色|
|capsize | エラーバーの横線の長さ|

([matplotlib.pyplot.errorbar](https://matplotlib.org/api/_as_gen/matplotlib.pyplot.errorbar.html?highlight=errorbar#matplotlib.pyplot.errorbar)にはもっと詳しくあります。)

また、検量線は``np.polyfit``で一次近似して、scikit_learnの``r2_score``で決定係数を出します。

```python

# y軸方向にのみerrorbarを表示
plt.figure(figsize=(10,7))
plt.errorbar(x, y, yerr = y_err, capsize=5, fmt='o', markersize=10, ecolor='black', markeredgecolor = "black", color='w')
coef=np.polyfit(x, y, 1)
appr = np.poly1d(coef)(x)
plt.plot(x, appr,  color = 'black', linestyle=':')
y_pred = [coef[0]*i+coef[1] for i in x]
r2 = r2_score(y, y_pred)
plt.text(max(x)/3.7, max(y)*6/8, 'y={:.2f}x + {:.2f}, \n$R^2$={:.2f}'.format(coef[0], coef[1], r2), fontsize=15)
plt.xlabel('x', fontsize=20)
plt.ylabel('y', fontsize=20)
# plt.savefig('y_error_bar.png')
```

![y_error_bar.png](https://qiita-image-store.s3.amazonaws.com/0/350253/52810adb-1537-eb00-1410-b365bf5e06b5.png)


# x, y軸両方にerror barを設定

x軸方向にもerror barをつけたいこともあるでしょう。
その場合は、``xerr``引数に誤差配列を渡せばできます。


```python

# x軸方向にもerrorbarを表示
plt.figure(figsize=(10,7))
plt.errorbar(x, y, yerr = y_err, xerr = x_err, capsize=5, fmt='o', markersize=10, ecolor='black', markeredgecolor = "black", color='w')
coef=np.polyfit(x, y, 1)
appr = np.poly1d(coef)(x)
plt.plot(x, appr,  color = 'black', linestyle=':')
y_pred = [coef[0]*i+coef[1] for i in x]
r2 = r2_score(y, y_pred)
plt.text(max(x)/3.7, max(y)*6/8, 'y={:.2f}x + {:.2f}, \n$R^2$={:.2f}'.format(coef[0], coef[1], r2), fontsize=15)
plt.xlabel('x', fontsize=20)
plt.ylabel('y', fontsize=20)
# plt.savefig('xy_error_bar.png')
```

![xy_error_bar.png](https://qiita-image-store.s3.amazonaws.com/0/350253/1cc00102-d3fb-336f-ff02-102690b0f1d4.png)

# リソース
以下のrepositoryに実行コードがあります。
https://github.com/YutoOhno/ErrorBar
Self-Attentionを利用したテキスト分類

# Self-Attentionを利用したテキスト分類

## TL;DR

テキスト分類問題を対象に、LSTMのみの場合とSelf-Attentionを利用する場合で精度にどのような差がでるのかを比較しました。
結果、テキスト分類問題においても、Self-Attentionを利用することで、LSTMのみを利用するよりも高い精度を得られることが確認できました。

Self-Attentionの実装としては[keras-self-attention](https://github.com/CyberZHG/keras-self-attention)を利用しました。

### ベンチマーク用データ

[京都大学情報学研究科--NTTコミュニケーション科学基礎研究所 共同研究ユニット](http://nlp.ist.i.kyoto-u.ac.jp/kuntt/index.php)が提供するブログの記事に関するデータセットを利用しました。 このデータセットでは、ブログの記事に対して以下の4つの分類がされています。

* グルメ
* 携帯電話
* 京都
* スポーツ

## LSTMのみ利用した場合のモデルと結果

[text-vectorian](https://github.com/lhideki/text-vectorian)を利用してベクトル表現に変換したテキスト入力し、LSTMにより学習、
分類先となる4ラベルの何れに該当するかを推論するモデルです。

### モデル

![](https://www.inoue-kobo.com/ai_ml/text-classification-by-selfattention/images/lstm_model.png)

### クラシフィケーションレポート

F1値は0.76でした。

```
              precision    recall  f1-score   support

          京都       0.71      0.75      0.73       137
        携帯電話       0.80      0.81      0.80       145
        スポーツ       0.68      0.72      0.70        47
         グルメ       0.84      0.72      0.78        90

   micro avg       0.76      0.76      0.76       419
   macro avg       0.76      0.75      0.75       419
weighted avg       0.77      0.76      0.76       419
```

## Self-Attentionを利用した場合のモデルと結果

`LSTMのみを利用した場合のモデル`に`Self-Attention`の層を追加したものです。
`Self-Attention`の出力は入力と同じ(sample, time, dim)の3階テンソルであるため、`GlobalMaxPooling1D`によりShapeを変換しています。

### モデル

![](https://www.inoue-kobo.com/ai_ml/text-classification-by-selfattention/images/selfattention_model.png)

### クラシフィケーションレポート

F1値が0.79でした。

```
              precision    recall  f1-score   support

          京都       0.71      0.84      0.77       137
        携帯電話       0.88      0.78      0.83       145
        スポーツ       0.66      0.74      0.70        47
         グルメ       0.88      0.74      0.81        90

   micro avg       0.79      0.79      0.79       419
   macro avg       0.78      0.78      0.78       419
weighted avg       0.80      0.79      0.79       419
```

## 総括

`LSTMのみ`では0.76であったF1値が`Self-Attention`を追加することで3%増加し0.79に向上しました。
それぞれ複数回試しても±1-2%程度の誤差範囲でしたので、`Self-Attention`を追加することは有意であると考えられます。

`Attention`は`NMT(Neural Machine Translation)`のようなシーケンスからシーケンスを推論する問題(seq2seq)への適用が注目されますが、
単純な分類問題にも入出力の形を変えずにそのまま適用出来るため、とりあえず使って見るのは悪く無さそうです。

## 参考文献

* [keras-self-attention](https://github.com/CyberZHG/keras-self-attention)
* [作って理解する Transformer / Attention](https://qiita.com/halhorn/items/c91497522be27bde17ce)
Cloud LaTeXのコマンドの自動補完機能紹介と、MacBook AirのSafariにおいてCloud LaTeXのコマンドの自動補完機能が無効化されている問題への対策

##Cloud LaTeX
![スクリーンショット 2019-01-25 17.53.39.png](https://qiita-image-store.s3.amazonaws.com/0/347645/fc148970-a035-b5ee-ae32-29c4ac25d35b.png)

無駄な環境構築のいらない最強のTeXの環境
https://cloudlatex.io/


#Safari バージョン
![スクリーンショット 2019-01-25 17.49.39.png](https://qiita-image-store.s3.amazonaws.com/0/347645/b8389327-31b8-8408-0a74-966011488310.png)
バージョン12.0.3(おそらく最新)

#コマンド
TeXにはコマンドがあり、数式や特殊文字などを綺麗に書くことができる。

![スクリーンショット 2019-01-27 15.34.38.png](https://qiita-image-store.s3.amazonaws.com/0/347645/473de23f-09d5-a132-d0bb-8d8f41fe486b.png)
こんなコマンドが・・・
![スクリーンショット 2019-01-27 15.34.22.png](https://qiita-image-store.s3.amazonaws.com/0/347645/feaf540d-6a7f-d7ea-628d-680d99397682.png)
こんな感じの特殊文字になったりします！

#コマンド自動補完機能

![スクリーンショット 2019-01-27 15.36.43.png](https://qiita-image-store.s3.amazonaws.com/0/347645/f6956b87-a57a-6488-897a-7dd81eabf069.png)
\ と打つと上のような複数の選択肢が出てくる。
これらを用いることで余分なエラーや覚える量を減らすことができる。

#問題
MACの中古を購入しSafariを利用していたが、この自動補完機能が出てこない。
しかし、
![スクリーンショット 2019-01-25 17.29.55.png](https://qiita-image-store.s3.amazonaws.com/0/347645/d47909bd-aed3-97e1-5587-91c2e49b9e88.png)
このように推奨PCブラウザとなっている。


#対策
FireFoxやGoogleChromeを用いる。
機械学習論文読みメモ_153

[World Models](https://arxiv.org/abs/1803.10122)
強化学習モデルのための環境生成モデルを提案する。
実際の環境を観測としてこのモデルは教師なしで環境の空間的、時間的な表現を
獲得する。
エージェントはこの生成された環境の上で学習する事で
要求タスクを解く方が出来るモデルを学習可能な事を示した。
またこうして学習したモデルはそのまま実際の環境に応用可能である。

[SqueezeNext: Hardware-Aware Neural Network Design](https://arxiv.org/abs/1803.10615)
組込み系へのdeepnetの適用において、メモリ消費と電力消費が
大きなボトルネックとなってきた。
本論ではそうした問題に対象したネットワークとして
SqueezeNetをベースとしたSqueezeNextを提案する。
例えばこのネットワークはAlexNetと同程度の性能を保ちながら、
112分の一までパラメータを減らした。
従来のSqueezeNetと違ってこのネットワークは
two stage squeeze moduleを導入する事でより多くのchannel reductionに
成功した。
また3x3 convolutionを3*1と1*3に分けるseparable convolutionを利用し
パラメータを削減した。
さらにresidual connectionも導入しResNetの構造を取り入れた。

[Forward-Backward Reinforcement Learning](Forward-Backward Reinforcement Learning)
強化学習では主に人の手でデザインされたreward関数に沿って学習が行われる。
この場合アルゴリズム設計者はタスクの目的を的確に表現する必要がある。
また加えてエージェントは非常に疎なreward関数を超えて自分自身で
そうしたタスクの目標を見つけ出す事も求められている。
しかしこの要求は学習プロセスを非常に難しいものにしてしまっている。
本論ではこの問題を緩和するために、通常の学習に加え、タスクの目標から
逆算してそこにたどり着くにはどうしたらよいかを予測させる学習も組み合わせる。
redmineプラグインのクラスたちが読み込めない

書いてある記事が少なかったので展開。

結論から書くとプラグインで指定した名称とフォルダー名を合わせる必要があった。
github等を使ってるとどうしてもredmineという名称にアンダーバーでレポジトリを作って、pluginとしてはredmineを抜いた名前にしがちだと思うので要注意。

たぶんRailsあるあるのよく出てくるエラー、“uninitialized constant”。

Rails（Ruby?）はファイル名とクラス名等の組み合わせが正しくないと読み込めない作りになっているため、初心者のうちはよくミスるらしい。だけどその辺を調べても間違いは見つからず。結局上記した部分のミスだった。エラーメッセージがもう少し親切だといいけど、この読み込み系のエラーってなかなか拾えないだろうな。

タチが悪いのはクラス以外の設定はうまく表示される。うまく読み込めないのはcontrollerとmodelだけだった。
こういうのはやり始めは付き物だけどDjangoが恋しい。
TeraTermマクロ：Cisco機器コンソール接続してログ取得の自動開始(出力Dirは指定する)

# TeraTermマクロ：Cisco機器コンソール接続してログ取得の自動開始(出力Dirは指定する)

+ 本ページはWindows10でCisco機へコンソール接続するためのTeraTermマクロを記載しています。
+ 本業がプログラマでは無いため、レベル的には高く無いと思います。
+ 実機での検証はしていますが、環境によって内容が変わることがあるため参考にする際は自己責任でお願いします。
+ Cisco機器へのコンソール接続とログ取得をするTeraTermマクロです。
+ ログはマクロファイル内で指定したフォルダへ出力します。

## 検証に使用した機器
+ __Ciscoルータ__：CISCO892-K9 (IOS-Version 15.2(4)M3)
+ __検証用PC__：Window10 (TeraTerm Version 4.100)
+ __汎用HUB__：NEC IX2005のSW-HUBポートを使用

## 検証構成
CISCO892-K9 --- 汎用HUB --- Window10 PC

## ログ保存名および保存フォルダ
__ログ保存場所__
マクロファイル内で指定したフォルダへ出力します。

__ログ保存名__
ログ名の確認ボックスが表示されるので、ログ名を入力します。
<font color="Gray">※ログ保存名は「入力内容_YYYYMMDD_hhmmss.log」</font>
<font color="Gray">※そのままEnterでもOK。その場合は「Console_YYYYMMDD_hhmmss.log」</font>

## TeraTermマクロの内容

```console:COMxx_Cisco_ConsoleLogin-logopen_Log保存(指定Dir).ttl
;### Console接続情報の設定 ###
;# 接続情報の設定(環境に合わせて修正してください)
COM_PORT = '3'
LOGIN_ID = 'admin'
LOGIN_PW = 'log-pass'
ENABL_PW = 'en-pass'
LOG_FILE = 'C:\teraterm'


;# ～～～～以下は修正不要です。～～～～

;### Log保存先・LogNameの設定 ###
;# Log保存先 ＝ <LOG_FILE>で事前に指定
;# LogName   ＝ [BOXが出るので入力]_YYYYMMDD_hhmmss.log
getdate DATETIME '_%Y%m%d_%H%M%S.log'
inputbox 'LogNameを入れてください※省略してEnterでも可'  'LogName' 'Console'
FULLPATH = LOG_FILE
strconcat FULLPATH '\'
strconcat FULLPATH inputstr
strconcat FULLPATH DATETIME

;### コンソール接続 ###
COMMAND = '/C=' 
strconcat COMMAND COM_PORT 

connect COMMAND


;### Logの取得開始 ###
loginfo logfilename
if result <> -1 then   ;# Logが取得中か未取得か確認
   logclose
   logopen FULLPATH 0 1   ;# 取得中→Log停止して再度Log取得を開始
else
   logopen FULLPATH 0 1   ;# 未取得→Log取得を開始
endif
sendln ''
pause 1

;### Login、enable、ter len 0 ###
;# Console接続後、プロンプトを見て動作を変えます。
;# Login後、既に"#"の場合にはLogopenのみ。
do
    wait 'Username:' '>' '#'
    if result == 0 then         ;# 0 = 何も表示されない場合
        end
    elseif result == 1 then     ;# 1 = [Username:]が表示された場合
        sendln LOGIN_ID
        wait 'Password:' 
        sendln LOGIN_PW
        wait '>'
        sendln 'enable' 
        wait 'Password:' 
        sendln ENABL_PW
    elseif result == 2 then     ;# 2 = [>]が表示された場合
        sendln 'enable' 
        wait 'Password:' 
        sendln ENABL_PW
    endif
loop while result == 3          ;# 3 =[#]が表示されたらLoopを抜ける

sendln 'terminal length 0'
sendln ''
sendln ''
```

以上です。
Python3 + selenium で京大情報環境機構PandAにログイン&レジュメを一括ダウンロード

# 1. はじめに
京大の授業資料はPandAかKULASISにアップロードされることが多いが、複数ファイルを一括でダウンロードできない!
毎回1つずつファイルを開いて保存するのはあまりにも面倒なため、
1. PandA にログインし、
2. 指定した科目のレジュメがあるページのURLを取得し、
3. レジュメを一括ダウンロードする
以上のプログラムを書いてみたところ結構苦労したので、その時学んだことをまとめました。プログラム書くほうが手動でダウンロードするより時間かかってる、とか言わない(8時間はかかった)。

# 2. 環境
Python3.6.6
用いたライブラリは以下の通り。
>beautifulsoup4      4.7.1    
>selenium            3.141.0
>>chromedriver 2.45

# 2. そもそもPandAをクローリングしていいのか?
機械的ダウンロードが禁止されているサイトは少なくありません。PandAには[robots.txt](https://www.seohacks.net/basic/terms/robots_txt/)のようなファイルは、確認した範囲では存在しなかったので、プログラムでレジュメをダウンロードすることはおそらく想定されていない(当然といえば当然)。しかし、[規程・関連規則](http://www.iimc.kyoto-u.ac.jp/ja/services/ismo/use/regulation.html)にも機械的ダウンロードについての記載はない。5秒間隔開けるので許してください。
だが、BeautifulSoupでの解析を詳細に書くと、京大生しか見れないサイトの構造が世界に公開されてしまうので、全コードは公開できません。ログインの部分は他のサイトでもそのまま使えると思います。

# 3. seleniumでログインする
requestsでやろうとしたが、クローリング初心者にはPandAの壁は高すぎた。[この記事](https://shimi-dai.com/python-selenium-web-scraping-at-login-page/)を参考に、初心者にも扱いやすいseleniumを用いました。

``` py
import os
import platform
import sys
import re
import time
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
```

次に、[この記事](https://qiita.com/memakura/items/f80d2e2c59514cfc14c9)に従って、
ファイルをダウンロードしやすいように、seleniumでドライバーを開くときのoptionを設定します。

```py
# driverを設定
options = webdriver.ChromeOptions()
options.add_experimental_option('prefs', {
        'download.default_directory': download_dir,
        'plugins.always_open_pdf_externally': True})
options.add_argument('--head')
```

次に、自分のIDとパスワードを入れ、ログイン。

```py
# login info
username = '' # ここに自分のIDを入力
password = ''

options.add_argument('--head')
# Chromeを起動
driver = webdriver.Chrome(executable_path='./chromedriver', chrome_options=options)
 
# ログインページを開く
url = 'https://panda.ecs.kyoto-u.ac.jp/portal/login'
driver.get(url)

# ログイン情報を入力してログイン
driver.find_element_by_id('username').send_keys(username)
driver.find_element_by_id('password').send_keys(password)
driver.find_element_by_name('submit').send_keys(Keys.ENTER)

# ログイン後のトップページのhtmlを取得
soup = BeautifulSoup(driver.page_source, "html.parser")
```

ここからBeautifulSoupオブジェクトを解析し、目的の科目のページへ飛びます。
Google chrome の[検証モード](https://developers.google.com/web/tools/chrome-devtools/?hl=ja)を利用しながら、BeautifulSoupオブジェクトから'.*.pdf'を探そうとしても......。

<FONT COLOR=blue>
**ない。'.*.pdf'がない! 検証モードとレスポンスが違う!** 
</FONT>

となり困り果てました。[調べたところ](https://teratail.com/questions/32756)、Javascriptが動いている環境だと、レスポンスと検証モードで表示されるElementとが異なることがよくあるそうです。今時Javascriptが動いてないページの方が珍しい気がするが、どうすればいいんでしょう。教えて有識者。
なので、そこをselenium を用いて修正。目的のページへ飛べました。

(selenium、動作が重たかったので次回以降はrequestsでできるようになりたい)

# 参考にした記事まとめ
https://shimi-dai.com/python-selenium-web-scraping-at-login-page/
https://qiita.com/memakura/items/f80d2e2c59514cfc14c9
https://teratail.com/questions/32756
Herokuのdynoは1日1回再起動する

https://devcenter.heroku.com/articles/dynos#restarting

Dynoは健康のために毎日最低1回再起動される
周期は24時間(プラス最大216分のランダム分、複数Dynoが同時に落ちないように)

その際、
Dynoのアプリケーションプロセス(Tomcat等)にSIGTERMが送信される、
ローカルファイルシステムへの変更は削除される、
ログに「heroku[web.1]: Cycling」が出力される
 
SIGTERMがアプリケーションプロセスに送られて30秒以内に、
アプリケーションプロセスは新しいrequestの受け付けを中止して現在のrequest処理を終了させ、プロセスを終了する必要がある
(TomcatにとってSIGTERMはgraceful shtdownなので処理中のリクエストは最後まで処理される)

30秒経っても残っているプロセスにはSIGKILLが送られ即時終了させられる

ローカルファイルシステムへの変更は削除される＝前日以前のログを見たいならPapertrailが必須
NodeRedでHTTPリダイレクト対応したフローを作る

NodeRedでGoogle App Scriptと通信するフローを作った時にHTTPリダイレクトが必要になりました。

パッとぐぐっても情報を見つけられなかったので、まとめてみました。

# フロー

![](https://qiita-image-store.s3.amazonaws.com/0/97208/07d39928-9ce3-faad-e453-f283fd373ba6.png)

```json
[{"id":"d7b66544.cad228","type":"http request","z":"bf7fc455.b09fc8","name":"","method":"GET","ret":"txt","url":"","tls":"","x":270,"y":1160,"wires":[["ba934f8b.bf0d1","34a354d5.522b7c"]]},{"id":"ba934f8b.bf0d1","type":"debug","z":"bf7fc455.b09fc8","name":"","active":true,"console":"false","complete":"true","x":430,"y":1200,"wires":[]},{"id":"ee827d07.60406","type":"debug","z":"bf7fc455.b09fc8","name":"","active":true,"console":"false","complete":"true","x":1090,"y":1160,"wires":[]},{"id":"9aae099d.e37438","type":"function","z":"bf7fc455.b09fc8","name":"リダイレクト","func":"msg.url = msg.headers.location;\ndelete msg.headers;\ndelete msg.payload;\ndelete msg.statusCode;\ndelete msg.method;\nreturn msg;","outputs":1,"noerr":0,"x":600,"y":1160,"wires":[["c44e1561.006978"]]},{"id":"c44e1561.006978","type":"http request","z":"bf7fc455.b09fc8","name":"","method":"GET","ret":"obj","url":"","tls":"","x":790,"y":1160,"wires":[["f5b05c0a.c51b2","3ef37c00.8133a4"]]},{"id":"34a354d5.522b7c","type":"switch","z":"bf7fc455.b09fc8","name":"","property":"statusCode","propertyType":"msg","rules":[{"t":"eq","v":"302","vt":"num"},{"t":"eq","v":"301","vt":"num"},{"t":"else"}],"checkall":"true","outputs":3,"x":430,"y":1160,"wires":[["9aae099d.e37438"],["9aae099d.e37438"],[]]},{"id":"f5b05c0a.c51b2","type":"switch","z":"bf7fc455.b09fc8","name":"","property":"statusCode","propertyType":"msg","rules":[{"t":"lt","v":"300","vt":"num"},{"t":"else"}],"checkall":"true","outputs":2,"x":950,"y":1160,"wires":[["ee827d07.60406"],[]]},{"id":"3ef37c00.8133a4","type":"debug","z":"bf7fc455.b09fc8","name":"","active":true,"console":"false","complete":"true","x":950,"y":1200,"wires":[]},{"id":"16aa0ce6.c87ac3","type":"inject","z":"bf7fc455.b09fc8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":100,"y":1160,"wires":[["d7b66544.cad228"]]}]
```

# 解説

一つ目のHTTPRequest Nodeで通信したいURLを指定します。
次のSwitchでリダイレクトの301か302の場合、次の関数ノードに処理をつづけます。
関数ノードでは、```msg.url = msg.headers.location;```でヘッダーに含まれた移動先のURLを代入して次のHTTPRequest Nodeで移動先の情報を取得します。

簡単ではありますが、このようになっています。
これで以上になります。簡単にではありますが、誰かの助けになればと思います！
pandas group_byとpct_changeの併用時bug (0.23.N)

# bugの内容
## 概要
pandasのpct_change関数をgroup byと共に使用する際に、group毎にpct_changeを区切って実行してくれないという事象が発生していた。(pandas 0.24.0で修正済み。)

## 何をしたかったのか
以下に参考用のテーブルを用意した。
このデータのValueのpct_changeをして、昨対比(MoM)を見たいという場面を想定。

| Company | Group | Date    | Value |
|---------|-------|---------|-------|
| A       | X     | 2015-01 | 1     |
| A       | X     | 2015-02 | 2     |
| A       | X     | 2015-03 | 1.5   |
| A       | XX    | 2015-01 | 1     |
| A       | XX    | 2015-02 | 1.5   |
| A       | XX    | 2015-03 | 0.75  |
| A       | XX    | 2015-04 | 1     |
| B       | Y     | 2015-01 | 1     |
| B       | Y     | 2015-02 | 1.5   |
| B       | Y     | 2015-03 | 2     |
| B       | Y     | 2015-04 | 3     |
| B       | YY    | 2015-01 | 2     |
| B       | YY    | 2015-02 | 2.5   |
| B       | YY    | 2015-03 | 3     |

Company, Group, Dateでgroup byをして、Valueのpct_changeを実施する。
`df['Pct_change'] = df.sort_values('Date').groupby(['Company', 'Group']).Value.pct_change()`

## 欲しかった結果

| Company | Group | Date    | Value | Pct_change |
|---------|-------|---------|-------|------------|
| A       | X     | 2015-01 | 1     | NaN        |
| A       | X     | 2015-02 | 2     | 1          |
| A       | X     | 2015-03 | 1.5   | -0.25      |
| A       | XX    | 2015-01 | 1     | NaN        |
| A       | XX    | 2015-02 | 1.5   | 0.5        |
| A       | XX    | 2015-03 | 0.75  | -0.5       |
| A       | XX    | 2015-04 | 1     | 0.33       |
| B       | Y     | 2015-01 | 1     | NaN        |
| B       | Y     | 2015-02 | 1.5   | 0.5        |
| B       | Y     | 2015-03 | 2     | 0.33       |
| B       | Y     | 2015-04 | 3     | 0.5        |
| B       | YY    | 2015-01 | 2     | NaN        |
| B       | YY    | 2015-02 | 2.5   | 0.25       |
| B       | YY    | 2015-03 | 3     | 0.2        |

## 実際に吐き出された結果

| Company | Group | Date    | Value | Pct_change |
|---------|-------|---------|-------|------------|
| A       | X     | 2015-01 | 1     | NaN        |
| A       | X     | 2015-02 | 2     | 1          |
| A       | X     | 2015-03 | 1.5   | -0.25      |
| A       | XX    | 2015-01 | 1     | -0.33        |
| A       | XX    | 2015-02 | 1.5   | 0.5        |
| A       | XX    | 2015-03 | 0.75  | -0.5       |
| A       | XX    | 2015-04 | 1     | 0.33       |
| B       | Y     | 2015-01 | 1     | 0        |
| B       | Y     | 2015-02 | 1.5   | 0.5        |
| B       | Y     | 2015-03 | 2     | 0.33       |
| B       | Y     | 2015-04 | 3     | 0.5        |
| B       | YY    | 2015-01 | 2     | -0.33        |
| B       | YY    | 2015-02 | 2.5   | 0.25       |
| B       | YY    | 2015-03 | 3     | 0.2        |

要は、group_byの最初のrow(ex.4行目)のPct_changeカラムに-0.33と入ってしまう。
ここはgroupが違うので、NaNであるべきなのに。

# 解決方法
## 概要
pandasのversionを0.24.0にupしましょう。

## sample
anaconda userはterminalを立ち上げて、以下のコマンドを打ちましょう。
`conda install pandas=0.24.0`

# 参考
https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.pct_change.html
https://stackoverflow.com/questions/40273251/pandas-groupby-with-pct-change
https://github.com/pandas-dev/pandas/issues/21200
iOSでprovisioning設定のコンフリクトが起きたときと、実機のビルドが通らないときの解消法

# 現象①xcode 10 で実機のビルドが通らなくなった

iOSの実機で動作確認しようとしたら突然以下のエラーが出ました＞＜

```
a valid provisioning profile for this executable was not found. xcode 10
```

# 現象②provisioning settingsがコンフリクトした

```
Showing Recent Messages
:-1: [App名] has conflicting provisioning settings. [App名] is automatically signed for development, but a conflicting code signing identity iPhone Distribution has been manually specified. Set the code signing identity value to "iPhone Developer" in the build settings editor, or switch to manual signing in the project editor. (in target '[App名]')
```

# 解決策

Xcode > File > Project Setting... で、Shared Project Settings: の Build System を「Legacy Build System」に変更したら無事に実行できました。
連想配列の配列からキーごとの配列を抜き出す

こういうAPIの返りを

```javascript:APIの返り値

const apiReturn = [
  {
     id: "3fa85f64-5717-4562-b3fc-2c963f66afa1",
     name: 'taro',
   },
   {
     id: "3fa85f64-5717-4562-b3fc-2c963f66afa2",
     name: 'jiro',
   },
   {
     id: "3fa85f64-5717-4562-b3fc-2c963f66afa3",
     name: 'saburo',
   }
];
```

こんな風にキーごとに配列にしたかったので

```javascript:キーごとの配列

[ '3fa85f64-5717-4562-b3fc-2c963f66afa1',
  '3fa85f64-5717-4562-b3fc-2c963f66afa2',
  '3fa85f64-5717-4562-b3fc-2c963f66afa3' ]

[ 'taro', 'jiro', 'saburo' ]
```

こうした

```javascript:snippet.js
const apiReturn = [
  {
     id: "3fa85f64-5717-4562-b3fc-2c963f66afa1",
     name: 'taro',
   },
   {
     id: "3fa85f64-5717-4562-b3fc-2c963f66afa2",
     name: 'jiro',
   },
   {
     id: "3fa85f64-5717-4562-b3fc-2c963f66afa3",
     name: 'saburo',
   }
];

const ids = apiReturn.map(x => x.id);
const names = apiReturn.map(x => x.name);

console.log(ids)
console.log(names)
```

`Array.prototype.map()` は配列を返すんだな

なんでこんなことがしたかったかというと.... つづく。
linuxの perf top は簡単なので日常的に使いたい

linuxカーネルにはパフォーマンス計測のための機能がいくつか備わっています。その中でもperf topは使うのが簡単です。日常的にこれを使っていれば、あるプロセスの負荷が異常に高まった場合にその差に気がつくことができます。

# インストール
perf topは perf の一部なので、perfをインストールします。perfはカーネルのリリースに強く依存しているので、パッケージがカーネルのリリースごとに分かれています。

ubuntuの場合では、以下のようにすれば適切なパッケージをインストールできます。

```shell
sudo apt install linux-tools-`uname -r`
```

# 使い方

システム全体を計測するとき

```shell
sudo perf top
```

システム全体をおおまかに計測するとき (プログラム、ライブラリごとにまとめて表示)

```shell
sudo perf top --sort comm,dso
```

特定のプロセスに注目して計測するとき (例: pid=5749 )

```shell
sudo perf top -p 5749
```

表示更新間隔を10秒にする。(表示内容をコピべするには、このほうがやりやすい)

```shell
sudo perf top -d 10
```
TeraTermマクロ：Cisco機器コンソール接続してログ取得の自動開始(出力Dirはマクロと同じ)

# TeraTermマクロ：Cisco機器コンソール接続してログ取得の自動開始(出力Dirはマクロと同じ)

+ 本ページはWindows10でCisco機へコンソール接続するためのTeraTermマクロを記載しています。
+ 本業がプログラマでは無いため、レベル的には高く無いと思います。
+ 実機での検証はしていますが、環境によって内容が変わることがあるため参考にする際は自己責任でお願いします。
+ Cisco機器へのコンソール接続とログ取得をするTeraTermマクロです。
+ ログは実行したマクロファイルと同じフォルダへ出力します。

## 検証に使用した機器
+ __Ciscoルータ__：CISCO892-K9 (IOS-Version 15.2(4)M3)
+ __検証用PC__：Window10 (TeraTerm Version 4.100)
+ __汎用HUB__：NEC IX2005のSW-HUBポートを使用

## 検証構成
CISCO892-K9 --- 汎用HUB --- Window10 PC

## ログ保存名および保存フォルダ
__ログ保存場所__
実行したマクロファイルと同じフォルダへ出力します。

__ログ保存名__
ログ名の確認ボックスが表示されるので、ログ名を入力します。
<font color="Gray">※ログ保存名は「入力内容_YYYYMMDD_hhmmss.log」</font>
<font color="Gray">※そのままEnterでもOK。その場合は「Console_YYYYMMDD_hhmmss.log」</font>

## TeraTermマクロの内容

```console:COMxx_Cisco_ConsoleLogin-logopen_Log保存(同一Dir).ttl
;### Console接続情報の設定 ###
;# 接続情報の設定(環境に合わせて修正してください)
COM_PORT = '3'
LOGIN_ID = 'admin'
LOGIN_PW = 'log-pass'
ENABL_PW = 'en-pass'
LOG_FILE = 'C:\teraterm'


;# ～～～～以下は修正不要です。～～～～

;### Log保存先・LogNameの設定 ###
;# Log保存先 ＝ このマクロと同じフォルダへ出力
;# LogName   ＝ [BOXが出るので入力]_YYYYMMDD_hhmmss.log
getdir DIR
getdate DATETIME '_%Y%m%d_%H%M%S.log'
inputbox 'LogNameを入れてください※省略してEnterでも可'  'LogName' 'Console'
FULLPATH = DIR
strconcat FULLPATH '\'
strconcat FULLPATH inputstr
strconcat FULLPATH DATETIME

;### コンソール接続 ###
COMMAND = '/C=' 
strconcat COMMAND COM_PORT 

connect COMMAND


;### Logの取得開始 ###
loginfo logfilename
if result <> -1 then   ;# Logが取得中か未取得か確認
   logclose
   logopen FULLPATH 0 1   ;# 取得中→Log停止して再度Log取得を開始
else
   logopen FULLPATH 0 1   ;# 未取得→Log取得を開始
endif
sendln ''
pause 1

;### Login、enable、ter len 0 ###
;# Console接続後、プロンプトを見て動作を変えます。
;# Login後、既に"#"の場合にはLogopenのみ。
do
    wait 'Username:' '>' '#'
    if result == 0 then         ;# 0 = 何も表示されない場合
        end
    elseif result == 1 then     ;# 1 = [Username:]が表示された場合
        sendln LOGIN_ID
        wait 'Password:' 
        sendln LOGIN_PW
        wait '>'
        sendln 'enable' 
        wait 'Password:' 
        sendln ENABL_PW
    elseif result == 2 then     ;# 2 = [>]が表示された場合
        sendln 'enable' 
        wait 'Password:' 
        sendln ENABL_PW
    endif
loop while result == 3          ;# 3 =[#]が表示されたらLoopを抜ける

sendln 'terminal length 0'
sendln ''
sendln ''
```

以上です。
Ubuntu 16.04 x64 + SQL Server2017 Express で AdventureWorks2017.bak を復元してみる

#目的
SQL Server2017 Express で SSMS を使用して AdventureWorks2017.bak を復元してみる
※Oracleでやったようにroleと権限の操作をSQLでゴリゴリたたくと理解が深まるんだろうなぁ・・・
※data-warehouse-install-script\instawdbdw.sql 読むと修正があるかな？
##bkファイルのダウンロード
[Microsoft/sql-server-samples](https://github.com/Microsoft/sql-server-samples/releases/tag/adventureworks)よりAdventureWorks2017.bakをDLする
$ sudo cp AdventureWorks2017.bak /var/opt/mssql/data/
##AdventureWorks2017.bakの復元
・SSMSでsaアカウントでログイン
・[データベース] を右クリックして、 [データベースの復元...] を選択
　->デバイスをクリック
　　->参照ボタン ([...]) をクリックする
　　　->[バックアップ デバイスの選択] ダイアログ ボックスが表示される
　　　　->追加ボタン押下で /var/opt/mssql/data/AdventureWorks2017.bak を選択後、OKボタンを押下する
　　->復元先のセクションの [データベース] ボックスに、復元するデータベースの名前が自動的に表示される
　　->OKボタン押下で復元処理が始まる
##復元後の設定
※demo アカウントで使用可能に設定する
・セキュリティ -> ログイン -> demo をダブルクリックする
　->ユーザーマッピングをクリック
　　->AdventureWorks2017のマップをチェックする
　　->ユーザー：demo
　　->規定のスキーマ：dbo
　　->データベースロールメンバーシップで以下をチェックする
　　　->db_datareader
　　　->db_datawriter
　　　->db_owner
　　　->public
　->OKボタンを押下する
・AdventureWorks2017->セキュリティ -> ログイン -> demo をダブルクリックする
　->所有するスキーマをクリックする
　　->HumanResources
　　->Person
　　->Production
　　->Purchasing
　　->Sales
　->メンバーシップをクリックする
　　　->db_datareader
　　　->db_datawriter
　　　->db_owner
　->OKボタンを押下する
　※SELECT DISTINCT(TABLE_SCHEMA) FROM INFORMATION_SCHEMA.TABLES
　dbo
　HumanResources
　Person
　Production
　Purchasing
　Sales
SSMSでdemoでログイン後正常にアクセスできることを確認する
##参考にしたのは以下のサイト
[データベースを新しい場所に復元する (SQL Server)](https://docs.microsoft.com/ja-jp/sql/relational-databases/backup-restore/restore-a-database-to-a-new-location-sql-server?view=sql-server-2017)
matplotlibでUV-Visスペクトルを描く

# 概要
matplotlibを使って、UV-Visスペクトルを描画する手法を紹介します！
今回はpHによって、吸収スペクトルが変化するケースを例にとります。
グラフの重ね合わせ、凡例の表示、ピークラベルの表示を実装しています。

# データの形式

以下の例で使用する``Uv-Vis.csv``([こちらからダウンロード](https://github.com/YutoOhno/UV-vis/raw/master/UV-Vis.csv))は'wavelength'列に波長を持ち、その他の列は異なるpHごとのabs(吸光度)が入っています。

```
wavelength,1,2,3,4,5
750.0,0.00018,0.00033,0.0007,0.00468,0.00536
749.0,0.00018999999999999998,0.00033,0.00073,0.00468,0.005379999999999999
748.0,0.00021,0.00029,0.00074,0.00468,0.005379999999999999
...

```

# シンプルに重ね合わせる

まずは、複数のグラフを重ね合わせ、それに対応する凡例を表示させます。

```python

from matplotlib import pyplot as plt
import numpy as np

# シンプルに重ね合わせる
data = np.loadtxt("UV-Vis.csv", delimiter=",", skiprows=1)
lines = []
colors = ['black', "red", "blue", "green", "purple"]
pHs =  ['3.67', '4.08', '4.65', '4.89', '7.96']
plt.figure(figsize=(10,7))
for i in range(1, 6):
    lines.append(plt.plot(data[:, 0], data[:, i], color=colors[i-1]))
plt.xlabel("wavelength /nm", fontsize=18)
plt.ylabel("abs", fontsize=18)
plt.legend([i[0] for i in lines], ['pH {}'.format(i) for i in pHs], fontsize=15, loc='upper left')
# plt.savefig("UV-Vis.png")必要に応じて保存
```

こんな感じの出力。概ね良いですが、少し物足りない感じがしますね。
ピーク位置にラベルを付けましょう！

![UV-Vis_simple.png](https://qiita-image-store.s3.amazonaws.com/0/350253/433a67cc-9e54-3839-987b-b3caf2fde452.png)

# ピーク位置にラベルをつける

``plt.text``でラベルを付けます。
ラベルの位置については自分でいい感じに調整してください。

```python

# ピークを位置表示
data = np.loadtxt("UV-Vis.csv", delimiter=",", skiprows=1)
lines = []
colors = ['black', "red", "blue", "green", "purple"]
pHs =  ['3.67', '4.08', '4.65', '4.89', '7.96']
plt.figure(figsize=(10,7))
for i in range(1, 6):
    lines.append(plt.plot(data[:, 0], data[:, i], color=colors[i-1]))
    
# pH 7.96の600nm付近のピーク
peak1_abs = data[:, 5].max()
peak1_wav = data[:, 0][data[:, 5].argmax()]
plt.text(peak1_wav*1.025, peak1_abs*0.9, '{}\n({} nm)'.format(peak1_abs, peak1_wav), color='purple', fontsize=15)  # 位置は手動で微調整...

# pH 3.67の450nm付近のピーク
peak2_abs = data[:, 1].max()
peak2_wav = data[:, 0][data[:, 1].argmax()]
plt.text(peak2_wav*1.025, peak2_abs*1.1, '{}\n({} nm)'.format(peak2_abs, peak2_wav), color='black', fontsize=15) # 位置は手動で微調整...

plt.xlabel("wavelength /nm", fontsize=18)
plt.ylabel("abs", fontsize=18)
plt.legend([i[0] for i in lines], ['pH {}'.format(i) for i in pHs], fontsize=15, loc='upper left')
# plt.savefig("UV-Vis_label.png")

```

ラベルもつきいい感じになりました！

![UV-Vis_label.png](https://qiita-image-store.s3.amazonaws.com/0/350253/f5ccdbde-962b-32d1-e29b-d390fa55aff2.png)

# リソース
以下のrepositoryで同じことができます。
https://github.com/YutoOhno/UV-vis/tree/master
AWS LambdaでApache PDFBox®を使う際の注意点

[Apache PDFBox®](https://pdfbox.apache.org/)とはPDFをゴニョゴニョするためのJavaのオープンソースライブラリです。

AWS LambdaではJava8のランタイムを使えるので、これをAWS Lambda上で動かすこと自体は特に難しいことではないのですがちょっとだけ注意点があったので記事に残します。

## 注意点

Lambda実行時の仕様として`/tmp`以外のフォルダは書き込みなどのアクセス権が制限されていますが、PDFBoxのデフォルトの動作としてfont cacheを更新しようとするのでその際にアクセス権の関係でエラーになります。

これを回避するには`pdfbox.fontcache`というシステムプロパティを`/tmp`にする必要があります。

たとえばLambdaのハンドラー関数実行後、PDFBoxを使う前に

```java:ハンドラー関数
System.setProperty("pdfbox.fontcache", "/tmp");
```

とすることなどで回避できます。

## 参考

[Apache PDFBox®](https://pdfbox.apache.org/)
SceneManagerで，ゲームのシーンを切り替えよう．（Ocu5Game.make）

##SceneManagerとは

Unityがシーンをコントロールするclassを用意してくれています．

それが UnityEngine.SceneManagement classです．

　　　-SceneManager.Load  　　　シーンを追加

　　　-SceneManager.Unload 　　シーンを削除

などを用いてシーンを切り替えます．

##シーンを整理
A:バトルフィールド   (BattleField)　・・・常時表示
B:タイトルシーン     (Title)
C:ゲームプレイシーン (Play)
D:リザルトシーン     (Result)

今回はシンプルに４つのシーンを組み合わせで，ゲームは構築されているとします．
Aのバトルプレイスは常時表示されており，それに載せるシーンが B → C → D 入れ替わっていくといった感じです．

##



##具体例
現在，BattleFieldと，Titleシーンがあるところに，Playのシーンを追加する例を紹介します．

```#C
using UnityEngine;
using UnityEngine.SceneManagement; //デフォルトでは記載されていないので追加する.
    void ChangeScene()
    {   
        //Playシーンの追加
        SceneManager.LoadScene("Play", LoadSceneMode.Additive);
        //Titleシーンの削除
        SceneManager.UnloadSceneAsync("Title"); 
    }
```

LoadSceneMode.Additive は現在，A,Bのシーンがあるところに，Playのシーンを追加するといった状況の際につけます.　多くの場合で，このような状況だとは思われるので，LoadSceneMode.Additiveまでセットで覚えましょう．(反対に何もシーンがないところに，.Additiveでシーンを加えようとするとエラーになります．)
ListAgg関数とwmsys.wm_concat関数の違い

昔、US-OTNに投稿した
ListAgg関数とwmsys.wm_concat関数の違い
[https://community.oracle.com/thread/1090158](https://community.oracle.com/thread/1090158)
を日本語に翻訳しつつ、全面リニューアルしてみました。

かつては、wmsys.wm_concat関数というマニュアルに載ってない関数があったのですが
11gR2XEや12cで消されてしまいました :scream:

ListAgg関数と似た関数だったのですが、
wmsys.wm_concat関数との違いをまとめてみます。

#01 distinctオプションの有無
wmsys.wm_concat関数は、distinctオプションを指定できますが
ListAgg関数では不可です。

```sql
create table diffT(SortKey,Val) as
select 1,'aa' from dual union all
select 2,'bb' from dual union all
select 3,'aa' from dual union all
select 4,'dd' from dual;

col concatV for a20

select wmsys.wm_concat(distinct Val) as concatV from diffT;

concatV
--------
aa,bb,dd
```

#02 文字の接続順序の指定
ListAgg関数は、文字の接続順序を指定できますが
wmsys.wm_concat関数では不可です。

```sql
select ListAgg(Val,',')
       within group(order by SortKey desc) as concatV
from diffT;

concatV
------------
dd,aa,bb,aa 
```

#03 デリミタの指定
ListAgg関数は、文字の接続のデリミタを指定できますが
wmsys.wm_concat関数では不可です。

```sql
select ListAgg(Val,'***')
       within group(order by SortKey desc) as concatV
from diffT;

concatV
-----------------
dd***aa***bb***aa
```

#04 分析関数として使用した時のOrderBy指定
wmsys.wm_concat関数は、分析関数として使用した時にOrderBy指定できますが、
ListAgg関数では不可です。

```sql
select SortKey,wmsys.wm_concat(Val)
               over(order by SortKey) as concatV
  from diffT;

SortKey  concatV
-------  -----------
      1  aa
      2  aa,bb
      3  aa,bb,aa
      4  aa,bb,aa,dd
```

#05 Keep指定
wmsys.wm_concat関数は、Keep指定が使えますが
ListAgg関数では不可です。

```sql
select wmsys.wm_concat(Val) 
       Keep(Dense_Rank First order by Val) as concatV
  from diffT;

concatV
-------
aa,aa
```
tyranobuilderでffmpegのインストールができないと言われる件

続きの記事を書こうとして、ちょっと別件でハマったので。
先行してちょっと記事を書こうと思います。

tyranoユーザにはありがたいデバッグツールのtyranoriderですが
ちょっと直して欲しいというか、バグという事象があったのでここにメモします。


tyranoriderではパッケージングを行なってくれるのですが
ブラウザなどでoggは使えないのでm4a形式に変換してくれる機能があります。
これはおそらくですが、内部でbgmフォルダとsoundフォルダの中身に対して

`ffmpeg -i <input.oggファイル> <output.m4a>`

を行なってくれていると思うのですが…oggファイルの中身によっては
変換が失敗してしまうものがあるようです。
その際に出てくるエラー画面が「ffmpegをインストールしないといけないよ」というエラー。


インストールってffmpegを置くだけじゃないの？


で、死ぬほど色々と調べた結果。

パッケージ出力先のexportファイルにこれまでの出力結果がいっぱい出ていました。
で、bgmフォルダを見て、違和感に気がつきました。

あれ、m4aファイルが出力されてないものもある…
なんじゃこりゃ？と思い、とりあえずffmpegで手動変換していると


<img width="1050" alt="スクリーンショット 2019-01-27 13.24.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/340395/048588fc-e5da-15e5-8c08-580d052d370a.png">

あああ、こけるファイルがあるじゃんかー。
つまり、変換にこけるとそのエラーハンドリングは
「ffmpegインストールできてないぽよ？」ってことかーい


で、対象のエラーが出るファイルを取り除くと無事にパッケージングで来ました。
めでたし、めでたし。



…


（小声）
もうちょっとエラーハンドリング頑張って欲しいなー。
ffmpegのバイナリファイルがあればエラー変えるとか。。。
ffmpegで録画＆静止画化

# カメラ設定
v4l2-ctl -c exposure_auto=3 #自動露出
v4l2-ctl --set-fmt-video=width=1280,height=720,pixelformat=1
v4l2-ctl -p 30 #フレームレート

# 取り込み。-t で録画時間設定。-c copyで無変換で高速に録画できる。そうしないとfpsが下がる。
ffmpeg -y -f v4l2 -input_format mjpeg -i /dev/video0 -c copy -t 10.5 /tmp/1.mkv

# 静止画化。-r 2 で2秒ごとに1つの静止画化。-ss で最初のデータを読み飛ばさないとだめぽい。
ffmpeg -ss 1 -i /tmp/1.mkv -r 2 -f image2 /tmp/a%06d.jpg
pyinstaller ビルド時の”Cannot find existing PyQt5 plugin directories”

#1 環境
Anaconda環境でpyinstallerをインストールするには以下のサイトがわかりやすく参考になります。ちなみに今回の環境はWindows10、pythonのバージョンは3.6です。

[Pyhtonのスクリプトをコマンド1つで実行ファイル(.exe)化する
](http://adliblog.hatenablog.com/entry/2017/11/16/022723)

pyinstallerのインストールはなんの問題もなくうまくいったのですが、pythonのコードをexe化をしようとしたところ

>Cannot find existing PyQt5 plugin directories

のエラーが発生。

#2 対策

PyQt5が見つからない場合の対策も上記のサイトに紹介されているのですが、うまくいきません。

PyQt5をconda installでインストールしようとしましたが、以下のようにはじかれてしまいます。

>UnsatisfiableError: The following specifications were found to be in conflict:
  - pyqt5 -> python=3.5
  - python=3.6
Use "conda info <package>" to see the dependencies for each package.

python3.6に対応してないということでしょうか？
先ほどのエラーをよくみると、以下のパスをチェックしろと書いてあります。


>Exception:
            Cannot find existing PyQt5 plugin directories
            Paths checked: C:/Miniconda3/conda-bld/qt_1535195524645/_h_env/Library/plugins


それで指示されている「/Miniconda3/.../plugins」フォルダを作成し、


>Anacondaインストールフォルダ\envs\仮想環境名\Library\plugins\

にあるplatformsフォルダをフォルダごとコピー

>pyinstaller --onefile hogehoge.py

再ビルドで無事にexeファイルが作成できました。
コーヒーブレイクとネクストアクション

今回は、コーヒーブレイクネタと、ネクストアクションを書き留めます。

# コーヒーブレイク
そもそも作りたいシステムはFXのデータを使ったAIで自動売買できるシステム。
世の中にはその手のシステムが増えてきている、、、。

少しでも自分の環境を構築する上で参考になるものを調べていたら、こんなものを発見した。

https://qiita.com/jiji_platform/items/268377c542706e6f44b1
これはとても素晴らしい!!
FXのデータだけではなく、他の経済情報も考慮に入れたAIシステム。
しかも、オープンソース!!

今回はここから少し学びました。

## 経済情報ってどこから入手するものなの？
一般的にはあらゆる経済情報が提供されているところから、スクレイピングして取得するの主流のようですが、なんと素晴らしいことに、そういう情報をAPIで提供してくれるサービスがあった。

### Quandl(https://www.quandl.com/)
このサイトでは無料で参照できる情報と、有料となる情報がある。
有料の場合は、各情報に応じて、1ヶ月～1年ぐらいで参照ライセンスが付与されるようです。

にしても、無料だけでも十分な量を提供されているようなので、必要な部分はコスト見合いで購入するのもありですね。

### Alphavantage(https://www.alphavantage.co/)
こちらは無料で為替情報へのAPIが提供されているようです。
ここは、主に下記の情報に特化しているようです。FXや仮想通貨、テクニカルインジケータをリアルタイムで提供してくれます。
- Free APIs in JSON and CSV formats 
- Realtime and historical stock data 
- FX and cryptocurrency feeds 
- 50+ technical indicators

### その他
https://blog.rapidapi.com/best-finance-apis/
こちらのサイトにも色々掲載されていた。
気になったのでφ(..)メモメモ

## 学習データの保存
FXのデータを使うのであれば、一度、モデルを作って終わり、、、とは行きません。
そんな中で、どうやって新しいデータを学習していくんだ？
と言う疑問がよぎりました。あまりその辺を明示的に書いている記事が見つからず、、、。

先程のJijiの中でヒントがありました。

Jijiの先にMongoDBと、TensorFlowへ接続し、そのTensorflowの先には、、、「.ckpt」の文字が、、、。
これをGoogle先生に聞いてみた。

### .ckpt
Tensorflow用の学習モデルをCheckpoint(.ckpt)ファイルに保存するようです。
後述の学習モデルの保存では、Kerasのものですが、Tensorflowの場合は、「[Save and Restore](https://www.tensorflow.org/guide/saved_model)」で保存するようですね。

### 学習モデルと、結果を保存するのは
https://m0t0k1ch1st0ry.com/blog/2016/07/17/keras/
では、実際に学習モデルと結果を保存するにはどうするのか？

```python
model_json_str = model.to_json()
open('mnist_mlp_model.json', 'w').write(model_json_str)
model.save_weights('mnist_mlp_weights.h5');
```
これで保存

```python
# モデルを読み込む
model = model_from_json(open('mnist_mlp_model.json').read())

# 学習結果を読み込む
model.load_weights('mnist_mlp_weights.h5')
```
利用するときには読み込む必要があるようようだ。

以前、 https://qiita.com/yanaitti/items/f28951b8231bd8596900 の記事で取り上げた例では参考にしたページの記載では下記の通りだった。

```python
# モデルを保存
model.save('model.h5') # 追加部分
```

```python
    # モデルを読み込む
    model = load_model(os.path.abspath(os.path.dirname(__file__)) + '/model.h5')
```

#### model.save()
これはモデルの重みと構成を両方保存する場合に利用し、load()により両方が読み出されます。

#### model.save_weights()
これはモデルの重みだけを保存する場合に利用し、JSONファイルからモデルを再構築する為の追加コードが必要になるとのこと。

なんか、着実に進んでいるのを実感している、、、が、ゴールはどこなのかｗｗ
【Vue.jsはじめました】勉強用の作業メモ

#Vue.jsはじめました勉強用作業メモ

**公式サイト**
[https://jp.vuejs.org/index.html](Vue.js公式サイト)

## 事前準備環境
- visualStudioCode 
- node.js

## Vue.jsとは(wiki引用)
Vue.js（ヴュージェイエス）、またはVueは、Webアプリケーションにおけるユーザーインターフェイスを構築するための、オープンソースのJavaScriptフレームワークである[4]。他のJavaScriptライブラリを使用するプロジェクトへの導入において、容易になるように設計されている。一方で高機能なシングルページアプリケーション（SPA）を構築することも可能である。

## 導入方法
- 今あるhtmlページ実装に乗せる形で導入したい。→ cdnで導入がおすすめ
- 本格的なSPAページとして1から実装したい。→ cliで導入がおすすめ

## 手順
- cdnで試してみよう

``` index.html
<html>
<title>Vue.js Test</title>
<head>
<script src="http://code.jquery.com/jquery-3.3.1.js"></script>
<script src="http://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
 document.addEventListener("DOMContentLoaded", function(event) {
  var app = new Vue({
   el: '#app',
   data: {
    message: 'メッセージを表示'
   }
  })
 });
</script>
</head>
<body>
<div id="app">
  {{ message }}
</div>
</body>
</html>
```

- 本番バージョン使いたい場合はこちら 
- 
``` index.html
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
```

- 色々いじってみる
- 表示・非表示とか。
- 
``` index.html
<html>
<title>Vue.js Test</title>
<head>
<script src="http://code.jquery.com/jquery-3.3.1.js"></script>
<script src="http://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
 document.addEventListener("DOMContentLoaded", function(event) {
  var app = new Vue({
   el: '#app',
   data: {
    disp1: true,
    disp2: false
   }
  })
 });
</script>
</head>
<body>
<div id="app">
  <div v-show="disp1">表示される</div>
  <div v-show="disp2">表示されない</div>
</div>
</body>
</html>
```

- 色々いじってみる2
- メソッドとか
- 
``` index.html
<html>
<title>Vue.js Test</title>
<head>
<script src="http://code.jquery.com/jquery-3.3.1.js"></script>
<script src="http://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
 document.addEventListener("DOMContentLoaded", function(event) {
	var app = new Vue({
	  el: '#app',
	  data: {
	    message: '時間がでるよ!'
	  },
	  methods: {
	    reverseMessage: function () {
	      this.message = new Date();
	    }
	  }
	})
 });
</script>
</head>
<body>
<div id="app">
  <p>{{ message }}</p>
  <button v-on:click="reverseMessage">時間を取得</button>
</div>
</body>
</html>

```
Sequel Pro が macOS Mojave ですぐ落ちるからテストビルドのやつを使ってみた

追記: Sequel Ace が後を継いだので今ならこっちですね。
[Sequel\-Ace/Sequel\-Ace: MySQL/MariaDB database management for macOS](https://github.com/Sequel-Ace/Sequel-Ace)

MacApp Store からもインストールできる。
[‎Sequel Ace on the Mac App Store](https://apps.apple.com/us/app/sequel-ace/id1518036000)

---

なんか Mac を Mojave にしてから、Sequel Pro がすぐ落ちるようになった。タブをひとつ閉じたらアプリケーションまるごと落ちる。

Sequel Pro は公式サイトでテストビルド版も配布されてて、これを書いている時点での最新版は Mojave にも対応してるようなのでこれを使ってみた。
https://sequelpro.com/test-builds

いまのところ安定して動いてるみたい。

ダークモードにも対応してた。
【Go言語】DBトランザクション共通処理の具体例

# 初めに

Go言語でDBトランザクション処理をシンプルに書く方法を模索していた。
有力な方法が見つかったので検討の経緯とその具体例を共有する。

#検討した実装パターン候補

*＊例コードは[GORM](https://github.com/jinzhu/gorm)を利用している前提。*

###実直に書く

```go
tx := db.Begin()
if tx.Error != nil {
	return nil, tx.Error
}
//　何らかの処理が失敗
tx.Rollback()

// 成功時
tx.Commit()
```

→　もっとDRYにしたい
→　Rollback or Commitのコールを忘れそう。。

###トランザクション状態を管理しつつdefer関数内で判断し必要に応じてRollbackをコール

(以下検討アイデアの雰囲気コード)

```go
myTx, err := db.MyBegin() //←　このレシーバー関数でBeginして管理トランザクション状態を開始にする
if err != nil {
    return err
}
defer myTx.MyFinish() //←　トランザクション状態判定して未完了ならRollback

// 任意のDB処理
user := User {
	Name: "test name",
}
if err := myTx.tx.Create(&user).Error; err != nil {
    return err
}
if err = myTx.MyCommit(); err != nil { //← Commit成功時、管理トランザクション状態を完了にする
	return err
}
return nil
```
→　少しDRYになった
→　もしMyCommit()を忘れてもトランザクションは必ず終了する
→　でも状態管理せずに済むならそちらの方がシンプルで良さそう。。

###（結論）共通ラッパー処理を用意する

共通ラッパー処理を関数化するアイデアを採用した。
以下は返り値情報を受け取る場合。

```go
// トランザクション実行し情報を受取る
func TransactAndReturnData(db *gorm.DB, txFunc func(*gorm.DB) (interface{}, error)) (data interface{}, err error) {
	tx := db.Begin()
	if tx.Error != nil {
		return nil, tx.Error
	}
	defer func() {
		if p := recover(); p != nil {
			tx.Rollback()
			panic(p)
		} else if err != nil {
			tx.Rollback()
		} else {
			err = tx.Commit().Error
		}
	}()
	data, err = txFunc(tx)
	return
}
```

#具体例

以下の様なテーブルスキーマとそれぞれのCreate関数が有ると仮定する。

```go
type User struct {
	ID uint `gorm:"primary_key"`
	Name string
}

type Event struct {
	ID uint `gorm:"primary_key"`
	UserID uint // ← 外部キー
	Name string
}
```

```go
// ユーザー作成
CreateUser(db *gorm.DB, name string) (*User, error)
// ユーザーに紐付くイベント作成
CreateEvent(db *gorm.DB, userID uint, name string) (*Event, error)
```

以下の様にトランザクションを扱いつつまとめて関数化出来る。

```go
func CreateUserAndEventInTransaction(db *gorm.DB, userName, eventName string) (*User, error)  {
	data, err := TransactAndReturnData(db, func(tx *gorm.DB) (interface{}, error) {
        user, err := CreateUser(tx, userName)
		if err != nil {
			return nil, err
		}
		_, errEvent := CreateEvent(tx, user.ID, eventName)
		if errEvent != nil {
			return nil, errEvent
		}
		return user, nil
	})
	if err != nil {
		return nil, err
	}
	// 受け取りたいものをラッパー関数内で返却してキャストすれば良い
	return data.(*User), nil
}
```

ラッパー関数内で漏れなく各処理の結果を返す事だけを守れば安全かつシンプルにトランザクション処理が書ける様になった！

# 参考

[golangでトランザクション管理を少し楽にするラッパー関数]
(http://tsujitaku50.hatenablog.com/entry/2017/11/01/232707)
MacでJIS配列のキーボードを利用しつつ、US配列で入力されるようにする

会社で支給されたMacの付属キーボードがJIS配列だが、どうしてもUS配列で入力したいという方向けの記事
__Karabiner-Elements__というアプリがMac内のキーイベントをキャプチャして異なるキーイベントに変換する機能を持っているため、その機能を利用することで実現する

# 環境
OS: macOS High Sierra
キーボード: Magic Keyboard（テンキー付き）- 日本語（JIS）

# 手順

## Karabiner-Elementsのインストール
[公式ページ](https://pqrs.org/osx/karabiner/)からKarabiner-Elementsをインストール

## キー変換のプリセットをインポート
Karabiner-Elementsは、[キー変換のプリセット](https://pqrs.org/osx/karabiner/complex_modifications/)が複数用意されていて、必要に応じてインポートすることができる
今回の目的に近いプリセットも存在していたが、ごく一部のキー変換しか対応していなかったため、自作することにした

以下URIをブラウザのURLバーに貼り付けて開き、「Karabiner-Elements.appで開く」をクリックすることで、自作したキー変換のプリセットをKarabiner-Elementsにインポートする

```
karabiner://karabiner/assets/complex_modifications/import?url=https%3a%2f%2fraw%2egithubusercontent%2ecom%2fshotaIDE%2fOriginalKeyBind%2fmaster%2fKarabiner%2dElements%2fjis2us%2ejson
```

<img width="986" alt="karabiner_elements_01.png" src="https://qiita-image-store.s3.amazonaws.com/0/125334/6a4c0c24-4b1d-d219-3b2f-541a02a36bfe.png">

Karabiner-Elementsが起動し、以下の画面が出てくるので、[Import]をクリックする
<img width="1000" alt="karabiner_elements_02.png" src="https://qiita-image-store.s3.amazonaws.com/0/125334/56d218ab-7efd-e1cb-c09d-29145719ec69.png">

以下の画面が出てくることを確認し、OKをクリックする
<img width="1000" alt="karabiner_elements_03.png" src="https://qiita-image-store.s3.amazonaws.com/0/125334/46b782d8-acad-28e6-20eb-f422e8f8c521.png">

「JISキーボードの配列をUSキーボードの配列にする」の項目の[Enable All]をクリックする
<img width="1000" alt="karabiner_elements_04.png" src="https://qiita-image-store.s3.amazonaws.com/0/125334/5c26a00e-695d-9e7b-6077-4e3f982d85ed.png">

以下の状態になることを確認する
<img width="1000" alt="karabiner_elements_05.png" src="https://qiita-image-store.s3.amazonaws.com/0/125334/9a443bcc-032e-edaa-cfe1-f63d960a8d28.png">

次に、[Devices]タブを選択する
接続されている物理キーボードのチェックがOFFになっている場合は、ONに変更する
![karabiner_elements_06.png](https://qiita-image-store.s3.amazonaws.com/0/125334/03972cc5-f22f-0fc3-6552-659de172fc87.png)

これで、キー入力がUS配列になっているはずである
試しに、Shift+2を押してみて、「＠」が入力されればキー変換が効いている

# 補足
## キー変換プリセットのインポートについて
ブラウザからインポートできない場合は、以下のJSONファイルを`~/.config/karabiner/assets/complex_modifications`のフォルダの中に保存することでインポートすることができる
https://github.com/shotaIDE/OriginalKeyBind/blob/master/Karabiner-Elements/jis2us.json

Karabiner-Elementsは、現状のキー変換ルールを保持するファイルを`/.config/karabiner/karainer.json`に持っているが、このファイルを直接編集してもキー変換は発動しない
そのため、上記までで紹介したように、プリセットとしてインポートした後アプリから有効化する必要がある

## キー変換プリセットの自作について
キー変換プリセットのJSONファイルを自作する場合、各キーの`key_code`を調べる必要がある
`key_code`は、Karabiner-Elementsをインストールすると一緒にインストールされる、__Karabiner-EventViewer__というアプリで調べられる

アプリを起動し[Main]のタブを選択した状態でキーを押すとキーイベントの詳細が表示されるので、その`name`を`key_code`として読み取れば良い
<img width="874" alt="karabiner_eventviewer.png" src="https://qiita-image-store.s3.amazonaws.com/0/125334/4b0717e4-a731-b3e8-4e42-adca41a6d4d5.png">

# 参考
- [Complex Modificationsのリポジトリ](https://github.com/pqrs-org/KE-complex_modifications)
- [Complex ModificationsのJSONの書き方](https://pqrs.org/osx/karabiner/json.html)
- https://github.com/tekezo/Karabiner-Elements/issues/1665
Laravel 5.7の認証機能でユーザー登録・パスワードリセット・メールアドレス確認のルーティングON/OFFを切り替える方法

# はじめに
Laravelでは、認証機能を以下のコマンドで導入することができます。

```powershell
php artisan make:auth
```

この際、ログインの機能に加え、ユーザー登録機能、メールアドレス確認も追加されますが、
状況により機能を取りやめたい場合があります。
そのための方法をメモとして残します。

# ルーティングの切り替え
認証機能のルーティングは以下の一文で、一括して機能しています。

```routes\web.php
Auth::routes();
```

これに対して、連想配列の引数を渡してあげることで、
認証の各機能に対して、ON・OFFの切り替えを行うことができます。
(正確には、ルーティングを取りやめるということ)

```routes\web.php
Auth::routes(['register' => false, 'reset'=> false, 'verify'=> false]);
```

各連想配列のインデックスは以下に対応します。
`true`がON,`false`がOFFです。
`register` : ユーザー登録へのルーティング 
`reset` : アカウントリセットへのルーティング
`verify` : メールアドレス確認へのルーティング


# ソースコードの挙動
Authクラスは`config\app.php`にて、エイリアスとして定義されています。

```config\app.php
'Auth' => Illuminate\Support\Facades\Auth::class,
```

`routes()`の引数は最終的に`vendor\laravel\framework\src\Illuminate\Routing\Rounter.php`内の
`auth`関数に渡されます。

```vendor\laravel\framework\src\Illuminate\Routing\Rounter.php
    public function auth(array $options = [])
    {
        // Authentication Routes...
        $this->get('login', 'Auth\LoginController@showLoginForm')->name('login');
        $this->post('login', 'Auth\LoginController@login');
        $this->post('logout', 'Auth\LoginController@logout')->name('logout');

        // Registration Routes...
        if ($options['register'] ?? true) {
            $this->get('register', 'Auth\RegisterController@showRegistrationForm')->name('register');
            $this->post('register', 'Auth\RegisterController@register');
        }

        // Password Reset Routes...
        if ($options['reset'] ?? true) {
            $this->resetPassword();
        }

        // Email Verification Routes...
        if ($options['verify'] ?? false) {
            $this->emailVerification();
        }
    }
```

この箇所にて、ルーティングの可否が切り替えられています。
Raspberry Piでシリアル通信試してみた


# 目的
Raspberry PiとSTM32をシリアル通信で接続して、Raspberry Pi上で動作させたROSからSTM32を制御したい。
まずはPythonからシリアル通信を試してみる。

# シリアル通信を使ってみる
## 環境
Raspberry Pi3 model B
Raspbian Stretch (2018-11-13)

## USBシリアルで
とりあえずUSBシリアルで試そう。（別にPCでもできる）
http://akizukidenshi.com/catalog/g/gM-08461/
これをラズパイのUSBポートにさして、TX/RXを直結しておく。

USBシリアルがどれか確認する。

```shell
pi@raspberrypi:~/work/python $ ls -l /dev/ttyUSB*
crw-rw---- 1 root dialout 188, 0 Jan 27 03:02 /dev/ttyUSB0
```

忘れずにシリアルのアクセス権限を追加

```shell
$ sudo usermod -a -G dialout $USER
```

まずはPythonからシリアルアクセスしてみる。

```shell
$ pip install pyserial
```

で、モジュールをインストールして

```python:testser.py
import serial
import time
import threading
import Queue

class SerCom:
    def __init__(self, tty, baud='115200'):
        self.ser = serial.Serial(tty, baud, timeout=0.1)
        self.queue = Queue.Queue()

        self.event = threading.Event()
        self.thread_r = threading.Thread(target=self.recv_)
        self.thread_r.start()

    def recv_(self):
        while not self.event.is_set():
             line = self.ser.readline()
             if len(line) > 0:
                 print(line)
                 self.queue.put(line)

    def send(self, data):
        self.ser.write(data)

    def stop(self):
        self.event.set()
        self.thread_r.join()

ser = SerCom('/dev/ttyUSB0', '115200')
ser.send('test')
time.sleep(2)
ser.stop()
```

こんな感じのお試しプログラムを書いて、実行してみる

```shell
pi@raspberrypi:~/work/python $ python testser.py
test
```

testが表示されればOK
TX/RXの線を外すと、何も表示されないはず。

## 今度はラズパイ本体のシリアルを試す
こちらの回答を参考に、シリアルを有効にする（しなくてもいいのかもしれなが、試してない）
https://raspberrypi.stackexchange.com/questions/45570/how-do-i-make-serial-work-on-the-raspberry-pi3-pi3b-pizerow

たぶん、これがピンヘッダに出ているUART

```
pi@raspberrypi:~ $ ls -l /dev/ttyS*
crw-rw---- 1 root dialout 4, 64 Jan 27 03:17 /dev/ttyS0
```

ピンヘッダの8pinがTX、10pinがRXのようなので、またこの間をショートしておく。
testser.pyの`SerCom('/dev/ttyUSB0', '115200')`を`SerCom('/dev/ttyS0', '115200')`に書き換える。
試して、testが表示されればOK。

```shell
pi@raspberrypi:~/work/python $ python testser.py
test
```