OmniAICreator/Qiita-1.07M huggingface dataset:
GitHubに英大文字・小文字それぞれ同名フォルダがあって困ったときの解決法

#GitHubに同じ内容のフォルダが複数あってビックリした

どういうことかっていうと、フォルダの名前をローカルで英大文字→小文字に変更をしたところ、何故かGitHubが「別物」として認識してしまったのです。

具体的には、以下のような状態になってしまったわけです。

```
[GitHub上]
　　img
    ├─Thumbnail
    │  ├─画像１
    │  ├─画像２
    │  ├─画像３
    │  └─画像４
    ├─thumbnail	
    │  ├─画像１
    │  ├─画像２
    │  ├─画像３
    │  └─画像４

```

```
[ローカル]
　　img
    ├─thumbnail	
    │  ├─画像１
    │  ├─画像２
    │  ├─画像３
    │  └─画像４

```
名前を変更した当初はこんなことになっているとは気づかず、後で困って解決法を模索したので、今回はその時の話です。



##この状態、何が困るのか　ーーバグが起こりやすくなります。
諸事情あって、普段使っていた開発ディレクトリとは違う場所に、GitHubからクローンしたときのこと。
GitHub上にある"Thumbnail"フォルダと"thumbnail"フォルダが衝突したというメッセージがでました。

「え？」と思ってクローン先のフォルダを確認すると、"Thumbnail"フォルダ一つだけクローンされていました。
一方、ソースコード上での該当フォルダの参照は、"thumbnail"の表記に統一されている。

するとどうなるかというと、環境によっては英小文字と大文字を区別して、
「このフォルダに格納されているファイルが見つからない！住所間違ってるよ！！」という事態になります。困る。


##もう一度リネームするんじゃダメなの？　ーーダメでした。
ローカル上でリネームしても、GitHub上に2つのフォルダは残ったままになります。

いちいち衝突するし、他の人がクローンするときにまた特定のファイルが表示されなくなってしまうのはビックリするでしょう。
何より本番障害につながるのが怖いですよね。



#試した解決法
リネームしてダメなら、２つともフォルダごと削除→コミット→正しいフォルダ名で新しいフォルダとしてコミットするのが一番楽かなと。

##前提

まずはGitHubのリポジトリをクローンしたローカルディレクトリが**２か所**必要です。
私の場合は、以下の①②の状況です。

①開発メインディレクトリ内に"thumbnail"フォルダのみ存在
②別ディレクトリ内にクローンした"Thumbnail"フォルダのみ存在

##フォルダ整理手順

1. "thumbnail"フォルダをローカル上の安全な場所に退避させる
1. ①の"thumbnail"フォルダを削除してコミット
1. ①からGitHubにPush
2. ②のディレクトリに移動、Fetch,Pullしておく
2. ②の"Thumbnail"フォルダを削除してコミット
3. ②からGitHubにPush
4. GitHub上から"thumbnail", "Thumbnail"ともに削除されていることを確認する
5. ①のディレクトリに、退避させていた"thumbnail"フォルダを復元する
6. ①からコミット、Pushする


手順が多くてちょっとめんどくさいですが、これで整頓できました。


#こんなことになるのはレアケースだと思いますが、だからこそ備忘録として。

今回の事象に直面した時、私は焦って調べたけどあまりヒントが得られず…。
検索の仕方が悪かったのかもしれませんが、なんてワードで調べたらいいんですかねこの事象？？

リネームで大文字→小文字に変更するだけなんて、皆さんあまりやらないのかもしれません。

そんなわけで、また同じような悩みが発生したときのために、備忘録として残すことにしました。


**他の賢いやり方があるよ！という方がいれば、ぜひ教えてください！！**
vscode key binding


```
// Place your key bindings in this file to override the defaultsauto[]
[
  // 相対パスのコピー
  {
    "key": "ctrl+cmd+e",
    "command": "copyRelativeFilePath",
  },
  // gitのブランチ選択UIを開く
  {
    "key": "ctrl+cmd+c",
    "command": "git.checkout"
  },
  // cli パネルを全体化
  {
    "key": "ctrl+cmd+b",
    "command": "workbench.action.toggleMaximizedPanel"
  }
]
```
JupyterLabで隠しファイルが表示されるようにするための設定方法

# はじめに
JupyterLabを立ち上げた後のフォルダ一覧に隠しファイルが表示されないのがたまに不便に感じる時があったので調べました。
ここでは、JupyterLabのconfigファイルに設定を追加して対応します。

# 方法

JupyterLabのconfigファイルがない方は下記のコマンドを実行の上作成してください。

```bash
$ jupyter-lab --generate-config
```

configファイルがある方は下記のように設定を追加してください。

```python:~/.jupyter/jupyter_lab_config.py
## Allow access to hidden files
c.ContentsManager.allow_hidden = True
```

これでJupyterLabのフォルダに隠しファイルも表示されるようになります。

面倒だなぁと思った方はコマンド実行時にオプションとして渡すことでできます。このコマンドのaliasなどを組むと良いと思います。

```bash
$ jupyter lab --ContentsManager.allow_hidden=True
```
CSSソース分割指針（案）～重複とサイズ肥大化を回避する

# １．CSSの部品分け

SassとPostCssを使うこと前提の部品分け。
できるだけ不要なスタイルはコードとしてビルドしない。

## （１）スタイル集合

- 関連しあう配置、装飾の集合。
- セレクタの名前を原則使わない。（場所と部品に依存しない）
- mixinで管理。(mixinにすることで、必要なときだけ定義を利用）
- ベンダープリフィックスなどはPostCssのプラグインに任せて、シンプルに記述。

## （２）共通部品のスタイル

- elementやboxのセレクタにスタイルを定義。
- mixinでセレクタごと管理。(mixinにすることで、必要なときだけ定義を利用）

## （３）画面ごとに１つのCSSファイルを読み込み

- セレクタの定義をする際に、上記の「スタイル集合」や「共通部品」をincludeする。
- indexで各パーツを読み込み、一つのcssファイルにする。
- 共通部分などを分割して読み込むと、画面が増えるごとに衝突の可能性が高まり、定義が煩雑になる。


# ２．コードの重複やビルドサイズ

- いろいろな画面で、いろいろな定義を使い回すと衝突することがあり、importantなどの定義をつかった無駄な定義をする可能性がある。1画面1cssファイルにすることで、画面間の衝突を回避する。
- mixinでパーツを管理することで、必要なときに必要な定義を使う。
- 分割してCSSを読み込むと、何が使われているのかわからず、デバッグに時間をとる可能性が高いので、分割読み込みはできるだけしない。

# ３．肥大化回避の為、原則フレームワークは利用しない

- FlexやGrid、Sass、PostCssなど技術的な進展、IEの利用減少とブラウザの進歩により、技術的な差違を埋める必要が減ってきた。
- フレームワークを利用すると、汎用性があるが故に、不要な定義を利用する可能性がありビルドサイズが肥大化する。
- フレームワークは、プロトタイプなどすぐに作りたいなど時間短縮には有効であるが、会社のサービスであれば、必要な定義をmixinで管理して利用する方が細かい調整が効く。
- フレームワークを利用するにしても、mixin経由で定義を必要なときだけ利用する。

# ４．共通の定義を複数ファイルに分けて複数の画面で読み込む弊害

- 再利用性を考えて、共通の定義ファイルを独立して複数の画面で読み込むと、イレギュラーな画面があった場合に、定義の衝突が起きてしまう。
- 利用しない定義を読み込み、その分は、サイズの無駄になる。
- BEM記法など名前の衝突をしないための冗長なセレクタにせざるを得なくなる。
Macで外付けHDDが認識しない場合の対応方法(exFAT)

# 概要
ファイルシステム「exFAT」の形式でフォーマットしてあり、他のPCからだと問題なく認識される外付けHDDが特定のMacだと認識されないことがあったため対処法の備忘録。

# 事象
* 外付けHDDをMacに接続しても認識されない。いくら待っても認識されない。
* FirstAidを実行してもエラーで終わる。状況は改善されない。
* ディスクユーティリティからマウント実行しても認識されない。
* 外付けHDDとMacを再起動しても認識されない。

# 原因予想
* 外付けHDDが正常に取り外せずにゾンビプロセスが残るなどした場合に発生するのかも。
* ファイルシステム「exFAT」を利用している場合に発生することが多い印象。この形式はいろいろとエラーが多いのかも。

# 対処方法

1. アクティビティモニタを起動し、プロセス「```fsck_exfat```」をkillする。
1. kill完了後、外付けHDDが瞬時に認識され、Finderやデスクトップにディスクアイコンが表示されることを確認する。
1. 外付けHDDに接続し、そこに保存してあるファイル郡が正常に操作できることを確認する。
1. 念のため、ディスクユーティリティからFirstAidを実行し修復チェックをかけておく。

# その他
* 利用環境やエラーの内容によっては、この方法が有効でない、もしくは不適切な場合があるため実施の際は自己責任で。
* 利用環境(PCやHDDなど)にマッチしていないファイルシステムの形式を選択してフォーマットをかけている場合はそもそも正常に動作しない(認識されない等)場合があるため注意。
* バックアップは複数取得保持しておいたほうがよい。
【Mono Depth】PackNet : velocityのsupervise

<h1>3D Packing for Self-Supervised Monocular Depth Estimation</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/9a60a014-347c-2a5f-cc55-4156672a422c.png)




<h1>新規性</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/25ccfec6-163d-7854-41ec-aa23d658c6c6.png)
velocityのsupervise


<h1>結果</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/03a0ed84-1861-0d11-490b-19c1fca12a29.png)
velocityのsuperviseがあってもほとんど精度が変わらない

<h1>結論</h1>
・velocityをsuperviseしてもほとんど効果がない。pose estimationの精度が良いのか、Ground Truthのvelocityの精度が悪いのか


<h1>参考文献</h1>
3D Packing for Self-Supervised Monocular Depth Estimation
https://arxiv.org/pdf/1905.02693.pdf
SQL group by句を使用して結果をまとめて表示する

# 目的

- SQLのgroup by句を使用して結果をある程度まとめて表示する方法をまとめる

# 情報

- SQL句は小文字で記載する。
- 下記SQLを順に実行してテーブルを作成した。

    ```sql
    create table items (category varchar(10), name varchar(255), price int);
    insert into items values ('stationery', 'eraser', 100);
    insert into items values ('stationery', 'pen', 150);
    insert into items values ('clothing', 't-shirt', 3000);
    insert into items values ('stationery', 'note', 100);
    insert into items values ('clothing', 'belt', 4000);
    insert into items values ('clothing', 'hat', 2000);
    insert into items values ('food', 'orange', 80);
    insert into items values ('food', 'apple', 120);
    insert into items values ('stationery', 'scissors', 500);
    insert into items values ('clothing', 'socks', 200);
    ```

- 下記のような「items」テーブルが存在しているものとする。（下記情報はSQL`show full columns from items;`を実行して確認）

    ```
    +----------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
    | Field    | Type         | Collation          | Null | Key | Default | Extra | Privileges                      | Comment |
    +----------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
    | category | varchar(10)  | utf8mb4_0900_ai_ci | YES  |     | NULL    |       | select,insert,update,references |         |
    | name     | varchar(255) | utf8mb4_0900_ai_ci | YES  |     | NULL    |       | select,insert,update,references |         |
    | price    | int          | NULL               | YES  |     | NULL    |       | select,insert,update,references |         |
    +----------+--------------+--------------------+------+-----+---------+-------+---------------------------------+---------+
    ```

- 上記のテーブルに下記のようなデータが格納されているものとする。（下記情報はSQL'select * from items;'を実行して確認した）

    ```
    +------------+----------+-------+
    | category   | name     | price |
    +------------+----------+-------+
    | stationery | eraser   |   100 |
    | stationery | pen      |   150 |
    | clothing   | t-shirt  |  3000 |
    | stationery | note     |   100 |
    | clothing   | belt     |  4000 |
    | clothing   | hat      |  2000 |
    | food       | orange   |    80 |
    | food       | apple    |   120 |
    | stationery | scissors |   500 |
    | clothing   | socks    |   200 |
    +------------+----------+-------+
    ```

# 普通の足し算の出力

1. まずは基本としてpriceカラムの値をすべて足して出力する。
1. 下記SQLを実行することでpriceカラムの値をすべて足したものを出力する事ができる。

   ```sql
   select sum(price) from items;
   ```

1. sum()句を使用することで指定したカラムのテーブル内のすべての値を足した値は出力することができる。しかしcategoryが一致しているもののみの合計金額を出力したいときは困る。

# 方法

1. categoryカラムが一致しているレコードのpriceカラムの値の合計を出力する。

    ```sql
    select category, sum(price) from items group by category;
    ```

1. 下記の内容が出力される。

    ```
    +------------+------------+
    | category   | sum(price) |
    +------------+------------+
    | stationery |        850 |
    | clothing   |       9200 |
    | food       |        200 |
    +------------+------------+
    ```
DOMとは？

<h1>はじめに</h1>
Reactを使っていると仮想DOMが頻出するので、一旦DOMについて整理します。


<h1>DOMとは？</h1>

DOMとは「Document Object Model」の略。
これだと理解し難いので、↓を引用。
>Document Object Model (DOM) は HTML や XML 文書のためのプログラミングインターフェイスです。

参照：<a href="https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model/Introduction">MDN web docks</a>

つまり、「HTMLやXML文書」と「プログラム」を間でつなげる仕組みのこと。
HTMLやXMLの要素や値をデータとして持っているのがDOM。

<h1>DOMはどんなVALUEを発揮してるの？</h1>

DOMによって、プログラムを使ってHTMLやHML文書を変更することができる。<br/>
例えば、Javascriptを使って、文書構造に変化を加えたり、値を変更したり、スタイルを変更できるのも、<br/>DOMあってこその妙技。<br/>
Javascript自体はHTMLやXMLの要素や値などを持っていないが、DOMがそれらを持っていることで可能になっている。



<h1>まとめ</h1>
DOMDOMよく耳にしてましたが、DOMが何なのか、なぜ必要なのかがわかった気がします。
プログラミング言語がHTMLなどの文書データを持っていないから、それを持っているDOMと連携することで、
ページに動きを加えられるようになるというイメージですね。
realsense-rosを任意のプリセットで実行する


RealSenseシリーズは事前に設定値をプリセットとして保存して使用できる機能があります。
https://dev.intelrealsense.com/docs/d400-series-visual-presets

この記事ではRealSenseViewerで設定したプリセットをjsonファイルで保存して、RealSenseのROSパッケージであるrealsense2_cameraで読み込んで実行する手順をまとめます。

# RealSenseデフォルトのプリセット

RealSenseはデフォルトでいくつかのプリセットが選択できるようになっています。
以下はD400シリーズのプリセットを説明したページです。

> [D400 Series Visual Presets](https://dev.intelrealsense.com/docs/d400-series-visual-presets)

高密度な点群を取得したい場合は、High Density, ジェスチャーに使用する場合は　Hand
などが選べるようです。

# RealSenseViewerからプリセットファイルの保存

まずRealSenseをPCに接続しRealSenseVieweを起動

```bash
realsense-viewer
```

左側メニューの`Preset`を選択、L515の場合デフォルトとしてDefault, No Ambient Light, Low Ambient Light, Max Range, Short Rangeの5つの設定が選択できるようになっています。



![Screenshot from 2021-01-30 03-31-08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399606/a2071be2-871c-5377-679d-321dc183f268.png)

`Custum`を選択し、RGBカメラ、Depthカメラの設定を好きな値に変更

![Screenshot from 2021-01-30 03-33-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399606/35d02f2c-26d9-4a59-bf61-074b6aaf0ea0.png)

Preset:の右の`Save config stereo module settings to file`をクリック、保存したいディレクトリを指定し、ファイル名を入力してOKをクリック。

![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399606/b86a5386-162c-cce9-ec7c-2bf6214d858f.png)

今回はcustom.jsonで保存。

![Screenshot from 2021-01-30 03-36-14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399606/596c1f8f-61c9-2eb0-d944-f8ec1863603f.png)



# realsense-rosで使用する

今回はrealsense2_cameraにデフォルトで入っている`rs_camera.launch`を編集します。
4行目の`"json_file_path"`に先ほど保存したjsonファイルのパスを入力します。

以下はrealsense2_camera直下に保存した場合の例

```xml
<launch>
  <arg name="serial_no"           default=""/>
  <arg name="usb_port_id"         default=""/>
  <arg name="device_type"         default=""/>
  <arg name="json_file_path"      default="$(find realsense2_camera)/custom.json"/>
  <arg name="camera"              default="camera"/>
  <arg name="tf_prefix"           default="$(arg camera)"/>
  <arg name="external_manager"    default="false"/>
  <arg name="manager"             default="realsense2_camera_manager"/>
  <arg name="output"              default="screen"/>
```

launchファイルを保存して実行

```bash
$ roslaunch realsense2_camera rs_camera.launch
```

# 参考

https://dev.intelrealsense.com/docs/d400-series-visual-presets

https://github.com/IntelRealSense/realsense-ros/issues/411
メモ：selenium、selenideについて

###Seleniumについてのリンク集

- [テスト自動化のためのフレームワーク](https://www.geekfeed.co.jp/geekblog/wordpress_on_testautomation)



###SeleniumとSelenideの違い


- [Seleniumの弱点を補うブラウザ自動テスト用フレームワーク「Selenide」とは (1/3)](https://www.atmarkit.co.jp/ait/articles/1803/05/news010.html#:~:text=Selenium%E3%81%AFWeb%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%AE,%E5%8C%96%E3%81%97%E3%81%9F%E3%83%84%E3%83%BC%E3%83%AB%E3%81%A7%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82&text=Selenide%E3%81%AFWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE,%E7%94%A8%E3%81%AE%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A7%E3%81%99%E3%80%82)


####そもそもseleniumとは？
Webアプリケーションのブラウザテストを自動化するツール


####seleniumの欠点1
- SeleniumはWebブラウザの操作を自動化するためのツール。
- Webアプリケーションのテストに特化したツールではない
- そのため、Seleniumを使ったテストコードには、冗長になってしまう部分があった。

####seleniumの欠点2
- 非同期処理についてSeleniumは苦手
- 「Seleniumで非同期処理をテストする」場合

1 「同期処理か非同期処理かを意識してテストコードを書く必要がある」
2 「非同期の処理の場合は明示的な待機処理を書かなければいけない」といった問題があります。

####Selenideの登場

- Webアプリケーションのテストに特化したツールとして登場。
- SelenideはWebアプリケーションのテスト自動化に特化したJava用のフレームワーク。
- Selenideを使うことで、Seleniumでは冗長な記述となってしまう部分も簡潔にテストコードが書けるようになっています。

参考にした記事（いつもありがとうございます）
---

- [テスト自動化のためのフレームワーク](https://www.geekfeed.co.jp/geekblog/wordpress_on_testautomation)
- [Seleniumの弱点を補うブラウザ自動テスト用フレームワーク「Selenide」とは (1/3)](https://www.atmarkit.co.jp/ait/articles/1803/05/news010.html#:~:text=Selenium%E3%81%AFWeb%E3%83%96%E3%83%A9%E3%82%A6%E3%82%B6%E3%81%AE,%E5%8C%96%E3%81%97%E3%81%9F%E3%83%84%E3%83%BC%E3%83%AB%E3%81%A7%E3%81%AF%E3%81%82%E3%82%8A%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82&text=Selenide%E3%81%AFWeb%E3%82%A2%E3%83%97%E3%83%AA%E3%82%B1%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%81%AE,%E7%94%A8%E3%81%AE%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A7%E3%81%99%E3%80%82)

SmaSurf クイック検索
HackerRank BotClean Large


問題URL：https://www.hackerrank.com/challenges/botcleanlarge
一番近くの「d」をBFSで探索して、その方向に移動するようにした
ベストな解答ではないが、54.1ptだった

```cpp
 #include <iostream>
 #include <vector>
 #include <queue>
 using namespace std;
 
 template<typename T>
 void print_vector(vector<T> &v){
     for(auto const& a:v){
         cout << a << " ";
     }
     cout << "\n";
 }
 vector<vector<int>> bfs(int height,int width,vector<string>grid,pair<int,int> s){ //no goal
     // distance list
     vector<vector<int>> visited(height);
     for(int i=0;i<height;i++)visited[i]=vector<int>(width,-1);
     // for(int i=0;i<n;i++)print_vector(visited[i]);
     visited[s.first][s.second]=0;
     
     const int white=-1;
     const int gray=0;
     const int black=1;
     // visited or not
     vector<vector<int>> color(height);
     for(int i=0;i<height;i++)color[i]=vector<int>(width,white);
 
     queue<pair<int,int>> Q;
     Q.push(s);
 
     // 移動4方向
     int dx[]={1, 0, -1, 0}; // {1, 0, -1, 0, 1, -1, 1, -1}
     int dy[]={0, 1, 0, -1}; // [0, 1,  0, -1, 1, -1, -1,  1]
 
     while(!Q.empty()){
         auto u=Q.front();Q.pop();
         for(int i=0;i<4;i++){
             if(u.first+dx[i]>=0 && u.first+dx[i]<height 
                 && u.second+dy[i]>=0 && u.second+dy[i]<width
                 && color[u.first+dx[i]][u.second+dy[i]]==white){
                 color[u.first+dx[i]][u.second+dy[i]]=gray;
                 visited[u.first+dx[i]][u.second+dy[i]]=visited[u.first][u.second]+1;
                 // cout << visited[u.first+dx[i]][u.second+dy[i]] << endl;
                 Q.push(make_pair(u.first+dx[i],u.second+dy[i]));
             }
         }
         color[u.first][u.second]=black;
     }
     // for(int i=0;i<n;i++)print_vector(visited[i]);
     return visited;
     // cout << visited[t.first][t.second] << "\n";
 }
 
 void next_move(int posr, int posc, int dimh, int dimw, vector <string> board) {
     // add logic here
     // for(int i=0;i<5;i++)cout << board[i] << endl;
     vector<vector<int>> d=bfs(dimh,dimw,board,make_pair(posr,posc));
     // cout << "distance:\n";
     // for(int i=0;i<5;i++)print_vector(d[i]);
     int min_=1000;
     pair<int,int> min_pos;
     for(int i=0;i<dimh;i++){
         for(int j=0;j<dimw;j++){
             if(board[i][j]=='d'){
                 if(min_>d[i][j]){
                     min_pos=make_pair(i,j);
                     min_=d[i][j];
                 }
             }
         }
     }
     // cout << "i:" << min_pos.first << " j:" << min_pos.second << "\n";
     if(min_pos.second<posc)cout << "LEFT\n";
     else if(min_pos.second>posc)cout << "RIGHT\n";
     else if(min_pos.first<posr)cout << "UP\n";
     else if(min_pos.first>posr)cout << "DOWN\n";
     else cout << "CLEAN\n";
 }
 
 int main(void) {
     int pos[2];
     int dim[2];
     vector <string> board;
     cin>>pos[0]>>pos[1];
     cin>>dim[0]>>dim[1];
     for(int i=0;i<dim[0];i++) {
         string s;cin >> s;
         board.push_back(s);
     }
     next_move(pos[0], pos[1], dim[0], dim[1], board);
     return 0;
 }
```
SPAとは？

<h1>はじめに</h1>
はじめまして。
現在、営業をしながら独学でプログラミングを学んでいます。
学んだプログラミング知識を頭の中で整理するべく、コチラに言語化していきたいと思います。

直近Reactでアプリ開発をしていたため、まずはSPAから。
（以前、Rubyで個人開発のアプリを作った時に、ページ遷移の遅さにストレスを感じて、SPAの勉強を開始した次第です。。）

<h1>SPAとは</h1>
<p>SPAはシングルページアプリケーションの略で、アプリケーションの設計構造の名称のこと。<br/>（フロントエンド開発で耳にします。）</p>

非SPAのアプリケーションは、ページ遷移のたびにページ全体のレンダリング（画面上に描画）が発生。
一方、SPAを導入しているアプリケーションの場合は、ページ全体をレンダリングするのではなく、__変更する部分のみを__書き換え、その結果を画面に表示することができる。

<h1>SPAの何がいいのか？</h1>

<h3>動作性が向上する<h3/>


遷移する度にページ全体をレンダリングしていると、時間がかかり使用感としてストレスを感じるが、
SPAでは**「変更が必要な部分のみを書き換える」**という形をとっているため、滑らかに画面の表示内容を変えることができる。
（滑らかすぎて、かなり気持ちいい。）

<h1>逆にSPAのデメリットは？</h1>

<h3>最初のページ表示に時間がかかる<h3/>

初めのページローディングには時間がかかる。
SPAを実装するためには、Javascriptのコード量が多くなるため、それが原因で初回のページ表示には時間がかかってしまう。

<h1>SPAはどんなアプリに向いてる？</h1>
SPAはページ遷移などのユーザーアクションに対するリアクションの速さに強みがあるため、
滞在時間が長く、ユーザーアクションが多くなるアプリケーションで強みを発揮する。

逆に初めのローディングに時間がかかるという弱みを持っているため、
ストレスがかかるとすぐに離脱されてしまうブログとかには向いてないそう。

<h1>まとめ</h1>
初めてSPAで実装した時は動きが滑らかすぎて、感動しました。
最初は概念の理解が難しかったですが、最近徐々にわかってきたかもしれない。。
【Mono Depth】L1 LossよりReprojection Lossが良いらしい

<h1>Robust Semi-Supervised Monocular Depth Estimation with Reprojected Distances</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/8a8f9cb8-848e-2501-fb8c-969649981b83.png)
この論文ではReprojection LossというLossを新たに提案している。


<h1>アルゴリズム</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/b92f0589-4c3b-7220-be9f-05ea18aefc5f.png)
Lphoto => per-pixel photometric loss
Mphoto => カメラと同じ速度で動いている物体とカメラが動いていない時のマスク
Lsmooth =>Depthの2回微分
Lrep =>今回提案されるreprojection loss

* [LphotoとMphotoの詳細](https://qiita.com/minh33/items/b879bead45231eb45462)



<h1>新規性</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/c163b179-26b5-da75-47d3-e46c9cbbde51.png)
LiDARを使ったSupervise LossはDepth Mapの距離を比較するのだが、
Lrepでは"推定したDepth"と"Ground TruthのDepth"をPoseNetによって推定されたTt->sによってwarpさせる
warpした時にDepthが違えばReprojectionされる位置がずれる。その差分をlossとして定義する。




![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/57e49999-12e9-b4f6-ad9a-8222e12a2d22.png)
数式で表すとこうなるらしい。

<h1>結果</h1>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482094/d19d7661-32dd-22e7-f682-b3ee01fc4908.png)
DepthのLossをL1よりReprojection lossにしたほうが精度が出たらしい。

<h1>結論</h1>
・なぜだか理解できていないが、L1 LossよりReprojection Lossの方が精度が上がるらしい。


<h1>参考文献</h1>
Robust Semi-Supervised Monocular Depth Estimation with Reprojected Distances
https://arxiv.org/pdf/1910.01765.pdf
Chromeで「STATUS_ACCESS_VIOLATION」が発生したときの解決策

# 今回のお題
お仕事中、AWSのコンソール画面を触っていてプルダウンメニューをクリックすると以下の画面になってクラッシュしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/930724/1ebb57c6-c3fb-594f-5592-4fe7b6a74e80.png)

特にAWSで障害情報も出ておらず、特定のサービスに限ったことではなく複数サービスでこの挙動を確認しました。
このままでは随分と作業に支障があるのでなんとかしたい！！

# 解決策

先人の知恵はすごい。

https://techdows.com/2020/07/chrome-crashes-with-status_access_violation-error.html

こちらに情報ありました。

```
Fix Status_Access_Violation error on Chrome and Microsoft Edge

Google Chrome

1. Right click on Chrome shortcut on desktop, select Properties
2. Click open File Location
3. Rename Chrome.exe  to Chrom.exe or something else. This is the super trick that fixed and worked for most users that affected by aw snap error.

Microsoft Edge

1. Right click on Microsoft Edge shortcut on desktop, select  Properties
2. Click on Open File Locaiton
3. Rename msedge.exe to msed.exe or something else.
```

Google Chromeのショートカットから、アプリの場所を開き名称を「chrome.exe」から「chrom.exe」など別の名前に変えてみろ、と。
・・・なぜそれで解決する？
まあいいか。とりあえずやってみましょう。

# やってみた

chrome.exeはここにいました。

```
C:\Program Files\Google\Chrome\Application
```

これを

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/930724/9f8f346d-f3fd-5194-f392-7cca2243b006.png)

こうする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/930724/fe7d37c8-910d-2bdd-3a47-6901547f948c.png)

どうだ・・・
いけた・・・マジか。

と、いうわけで同じ悩みでお困りの方はお試しあれ。
macOSをBig Surにアップデートしたらgitが使えなくなった

macOSをBig Surにアップデートしたらgitが動かなくなった。

gitコマンドを実行すると以下のようなエラーが発生。

`xcode-select: Failed to locate 'git', requesting installation of command line developer tools.`

どうやらアップデートしたことによってxcodeが消えていたらしい。

xcodeを再インストールして無事解決。
https://apps.apple.com/jp/app/xcode/id497799835?mt=12


年度末で仕事が忙しい時期だったので焦った...（三点リーダー症候群）
JetBrains Riderで変数のprivateアクセス修飾子の補完を切るには

## はじめに
Unityでの開発において、個人的には、private変数にはアクセス修飾子を付けるスタイルが好みなのですが、変数のprivateアクセス修飾子を省略するスタイルが好みの方も多いと思います。しかし、JetBrains Riderのデフォルトの設定では、privateアクセス修飾子を補完する機能が有効になっているため、この補完を切る方法を紹介したいと思います。

## 確認環境
- macOS Big Sur (バージョン11.1)
- JetBrains Rider (2020.3.2)

## 設定方法
Macの場合、JetBrains RiderのPreferences → Editor → Code Style → C# → Syntax Style → ModifiersのPrefer explicit/implicit private modifier for type membersをImplicitに設定すれば変数のprivateアクセス修飾子の補完が切れます。Windowsの場合は、File → Settings以下で設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/5879/811fc973-a779-1a90-d575-812baea450ce.png)

## 参考
- [how do you turn off auto complete adding a private in front of my variable?](https://rider-support.jetbrains.com/hc/en-us/community/posts/360006746240-how-do-you-turn-off-auto-complete-adding-a-private-in-front-of-my-variable-)
- [Settings/Preferences](https://www.jetbrains.com/help/rider/Settings_Preferences_Dialog.html)
[未経験エンジニア]のオリジナルアプリ制作の反省2.  「バリデーションの適用範囲」

# 今回書くこと
バリデーションを、特定の条件下のみで発動させたい場合、どのような処理を記述すればいいか

## 環境
Ruby 2.6.5
Ruby on Rails 6.0.4.3

## 結論
on: :アクションを用いる

## 記述方法

#### モデル

```article_model.rb
class Article < ApplicationRecord
  validates :title, presence: true, on: :create
  validates :text, presence: true
end
```

titleにon: :createと記述されています。このオプションによって、このタイトルへのpresence: trueは、createアクションのみに適応されることになります。textのpresence: trueは、create, updateにかかっていることになります。

createをupdateに変えることもできます。

[Rails ガイド](https://railsguides.jp/active_record_validations.html#on)では

>バリデーションのタイミングを変更したい場合、on: :createを指定すればレコード新規作成時にのみ検証が行われ、on: :updateを指定すればレコードの更新時にのみ検証が行われます。

とされています。

ちなみに、複数のバリデーションにまとめてオプションをつける時の記述は、このようにした方が可読性が高まるでしょう。

```article_model.rb
with_options on: :create do |create|
  create.validates :title, presence: true
  create.validates :text, presence: true
end
```

特定のバリデーションを、特定のタイミングで起動させたい。と思っている方の参考になればと思います。

## 浮かんだ疑問
今回のバリデーションとしてpresence: trueを例に出しましたが、実際に利用するときは、どんなバリデーションにこのオプションをかけるといいのかなと思いました。[カスタムコンテキスト](https://railsguides.jp/active_record_validations.html#on)なども踏まえ、この辺についてもう少し掘り下げたいですね。

## 最後に
最後まで読んでいただいた皆様、ありがとうございます。
ソースコード、記事の書き方について**「もっとこうしたほうがいいよ！」というご意見**、**「そこどうなっているの？」というご質問**など、お待ちしております。

## 参考文献
Active Record バリデーション
- https://railsguides.jp/active_record_validations.html
状況によってsave時に実行するバリデーションを切り替える
- https://qiita.com/kadoppe/items/061d137e6022fa099872
Rails 簡易的なチュートリアル機能の実装

##実装イメージ
・〇件投稿しよう！
・〇件いいねをつけよう！
みたいな簡易的なやつです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/989457/008a3b0d-3082-2f02-ce7c-df8fb74499c5.png)
ユーザーのマイページに実装します。
項目ごとに完了したら『クリア！』を表示。
オマケで、全部完了したら名前の横の初心者マークが外れてダサくなくなるギミックを付けます。

条件分岐とカラム追加で実装します。
もっとシンプルなやり方があれば教えていただけますと幸いです。

##前提
+ Rails 5.2.4.4
+ ユーザー及び、チュートリアルに含める投稿などのテーブルは既にある
+ ユーザーと各種投稿などのアソシエーションも組めている

##Userテーブルにカラムを追加
該当のユーザーがチュートリアルクリアしたかどうか？のカラムを追加します。
2択なのでboolean型、カラム名はbeginnerとしてみました。

```command
rails g migration AddColumnToUser beginner:boolean
```
trueの場合はチュートリアル完了前
falseの場合はチュートリアル完了後という感じにします。

```migrate/0X0X0X0X_add2_column_to_user.rb
class AddColumnToUser < ActiveRecord::Migration
  def change
    add_column :users, :beginner, :boolean, default: true, null: false
  end
end
```
デフォルトでtrue(チュートリアル完了前)を指定。

```command
rails db:migrate
```

[マイグレーションコマンド参考](https://qiita.com/zaru/items/cde2c46b6126867a1a64)

##Viewにチュートリアル内容と初心者マーク（条件分岐）を記述
今回はユーザーのマイページに記述します。
例えばチュートリアル内容が、
・投稿（tweetモデルとします）を2つ以上、
・tweetにいいね（favoritesモデルとします）を3回以上
であれば…

```ruby:show.html.erb
<!--チュートリアル完了後の場合-->
<% if user.beginner == false %>
  <p>チュートリアル完了！</p>

<!--チュートリアル完了前の場合-->
<% else %>
  <p>
    2つ以上のtweetをしよう！
    <% if @user.tweets.count < 2 %>
      (<%= @user.tweets.count %> / 2)
    <% else %>
      クリア！
    <% end %>
  </p>
  <p>
    3つ以上のtweetにいいねをしよう！
    <% if @user.favorites.count < 3 %>
      (<%= @user.favorites.count %> / 3)
    <% else %>
      クリア！
    <% end %>
  </p>
<% end %>
```
こんな感じです（ハイライトがおかしいですが、構文変ですかね…？）。
取り急ぎ、雰囲気は伝わるかと思います。

オマケですが、チュートリアル完了前の場合は
ユーザー名の横に初心者マークを付けます。
その他、ユーザー一覧など、任意の場所につけてください。

```ruby:show.html.erb
<p>
  <%= @user.name %>
  <% if @user.beginner == true %>
    <%= image_tag '初心者マーク.png', :size =>'14x14' %>
  <% end %>
</p>
```

##コントローラーに追記（チュートリアル完了でuser.beginnerをfalseに）
チュートリアルが終わっているかどうかのジャッジを、
マイページへ遷移するコントローラーで行います。
今回の場合、showアクションの中に追記します。

```ruby:users_controller.rb
# チュートリアルが終わっていればbeginnerをfalseにする
if @user.beginner == true && @user.tweets.count >= 2 && @user.favorites.count >= 3
  @user.update(beginner: false)
end
```

これで、実装完了です。
チュートリアルが完了した状態で、
マイページにアクセスするタイミングで、
beginnerカラムがfalseになり、初心者マークは外れます。
また、チュートリアル内容は消えて、完了のメッセージが表示されるはずです。

##補足
beginnerカラムを追加せずとも、Viewの条件分岐のみでも実装可能です。
ただ、その場合、チュートリアル完了後にtweet削除等で2tweetを下回ると
初心者マークが復活してしまいます。
なんかあれなので、このやり方で実装しました。

間違っている点、補足などあればご教示いただけますと幸いです。
よろしくお願いいたします。
manimの作法 その39

#概要

manimの作法、調べてみた。
add_sound使ってみた。

#サンプルコード

```
from manimlib.imports import *

class test(Scene):
	def construct(self):
		text = Text('お掃除します。', font = 'IPAGothic')
		self.play(Write(text))
		self.add_sound('20201228093158.wav')
		self.wait(2)


```

#生成した動画

https://www.youtube.com/watch?v=Zc1300I4hUI


以上。
mousewheel.jsでのエラーを解決して横スクロールができるようになった

```javascript:main.js
//マウス上下で横スクロール
$(document).ready(function() {
	$('html, body, *').mousewheel(function(e, delta) {
	this.scrollLeft -= (delta);
	document.addEventListener('mousewheel DOMMouseScroll', { passive: false });
	});
	});
```

で動作する。
横スクロールする度にエラーが増幅して困ってた。また、googleのconsoleでは動くのにページで表示すると動かなかった。エラーはconsoleでも出ていた。
エラーメッセージは、
>[Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. 




```javascript:元の.js
$(document).ready(function() {
$('html, body, *').mousewheel(function(e, delta) {
this.scrollLeft -= (delta);
e.preventDefault();
});
});
```
修正した箇所は、最後のところ
`e.preventDefault();`を`document.addEventListener('mousewheel DOMMouseScroll', { passive: false });`に変更

解決のお世話になったURL
https://github.com/peachananr/onepage-scroll/issues/346#issuecomment-547004469
らぶ！Mr.stayacid
Swift5 今日の日付を取得する方法

#はじめに
日付のデータの取得方法が分からなかったので調べました。
#環境
Xcode12.3
Swift5.3.2
macOS Catalina 10.15.4

#日付を取得する

```Swift
 //日付の取得
        let dateFormatter = DateFormatter()
        dateFormatter.dateStyle = .medium
        dateFormatter.timeStyle = .none

        let date = Date()
        dateFormatter.locale = Locale(identifier: "ja_JP")
        print(dateFormatter.string(from: date))
```

#結果
![スクリーンショット 2021-02-01 18.26.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/683624/9ca2e250-a4d9-508b-30e8-05089e74ca8f.png)
※2021年2月1日に実行しました。

#終わりに
何か間違えがあれば、優しく教えていただけると嬉しいです。

#参考サイト
https://developer.apple.com/documentation/foundation/dateformatter


Twitterやってます。
[Twitter](https://twitter.com/koara1237)
Routerについて

##Routerとは

RouterはReactで扱うコンポーネントを使って画面遷移をすることができる技術の一つです。
具体的な例を用いて説明します。
![React.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1066052/760fd622-6550-9f87-e2fa-78329a8422f3.jpeg)
※今回はRouterを説明するためにコンポーネントの分割は画面単位でのみ行なっているものとします。
Appと言う親コンポーネントに対して、display1とdisplay2という子コンポーネントがあるとします。
display1にあるボタンをクリックすると画面2に遷移するにはどうすれば良いでしょうか？

このときに利用できるのがRouterです。
今回はdisplay1とdisplay2がともに画面コンポーネントです。通常ブラウザで表示できる画面にはそれぞれ固有のURLが設定されているかと思います。RouterはこのURLに関する技術で、今回の「画面遷移」をすると言うのは実際のところは「URLを変更してリクエストし直す」と言う動きになります。
では今回は以下のようにURLを設定するとします。
![React2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1066052/97b0d7fd-16ef-d3f8-d74a-e0a805e2273d.jpeg)
この図をコードにすると以下のようになります。

```react:App.js
<Router>
   <Route path="/display1" component={display1}/>
   <Route path="/display2" component={display2}/>
</Router>
```

これでそれぞれのコンポーネントに対するURLを設定することができたので、実際にあとはボタンを押したときにそのURLに遷移すると言うものをHTMLで記述するのみです。

```html:display1.js
<a href="example/App/display2"><buttton>Button</button></a>
```

これで画面の遷移ができるようになりました。
このようにコンポーネントにはURLを設定することができ、そのとき利用するのがRouterです。
<Router>のタグ内にRouteとして設定したいページを記述することで画面構成を作ることができます。


###exact pathについて
`exact path`について今回は扱っていませんが、
`<Route path="/display1" component={display1}/>`
を
`<Route exact path="/display1 component={display1}/>`
と記述することもできます。こうすることで、完全一致のpathのみが適用されるようになります。逆に言うと、`path="/display1"`の場合は`path="/display1/2`これも同じアドレスにアクセスができてしまうと言うことです。それはつまりpathの場合にはその下の階層に画面コンポーネントを作ってもアクセスができないということになります。

####関連
- [Reactについて](https://qiita.com/kunrenyouAcount/items/27cbcb4d91904baa2aba)
- [propsについて](https://qiita.com/kunrenyouAcount/items/317ed50ca358b593041b)
プログラミング初学者メモ(2)　コンピュータの回路

#この記事について
プログラミング学習の基礎づくりのため、基本情報技術者の参考書で学習したことを記録しています。
今回はコンピュータの回路についてまとめました。
2,3,4章では、演算結果が1になる入力を縦にペアができるように記述しています。

##1.目次
1.目次
2.論理演算
3.論理回路
4.加算器
5.ビット操作

##2.論理演算
論理演算とは、1を真(True)、0を偽(False)とみなして行う演算。ベン図を用いると考えやすい。
AとB、二つの条件があると仮定して、基本的なものを以下に示す。

###論理積(AND)
「AかつB」の場合を示す。
A:1
B:1

###論理和(OR)
「AまたはB」の場合を示す。
A:0,1,1
B:1,0,1

###否定(NOT)
「Aではない」の場合を示す。
A:0,0
B:0,1

##3.論理回路
論理演算を行う回路。

###基本回路
上述の3種類の論理演算それぞれを行う回路。

###否定論理積(NAND)
ANDとNOTを組み合わせた回路。ANDと逆の出力をする。
A:0,0,1
B:0,1,0

###否定論理和(NOR)
ORとNOTを組み合わせた回路。ORと逆の出力をする。
A:0
B:0

###排他的論理和(EORまたはXOR)
AとBのうち、片方だけの場合に演算結果が1となる回路。
A:0,1
B:1,0

##4.加算器
2進数の加算を行う回路を加算器という。論理回路を利用する。
###半加算器
下位からのくり上がりを考慮しない加算器。1桁目の計算で用いられる。
2桁目を出力C、1桁目を出力Sとする。

出力C
A:1
B:1
→ANDと同じ

出力S
A:0,1
B:1,0
→EORと同じ

したがって、半加算器はANDとEORを組み合わせた回路と言える。

###全加算器
下位の桁からのくり上がりも考慮した加算器。2桁目以降の計算で用いられる。
入力として、A,Bに下位からのくり上がりC'を加えて考える。
そうすると、

A＋Bをする半加算器(出力をC1,S1とする)
S1+C'をする半加算器(出力をC2,S2とする)

C1とC2どちらかでしかくり上がりは起きないので、
C1 OR C2　とする(出力をC3とする)。

演算結果としては、C3,S2　でわかる。

このように、全加算器は半加算器２つとORで構成される。

##5.ビット操作
引き算をするために2の補数を作ったり、浮動小数店を扱うためにビットを取り出したりする際に
ビット操作が必要になる。これは、論理演算が利用できる。

###ビットの反転
排他的論理和(EORまたはXOR)を用いる。
反転させたいビット列をA = 00000011 とする。

1.反転させたい位置に1を入れたビット列A'(マスクパターンという)を用意する。
A' = 11111111

2.A EOR A'をとる
A00000011
A' 11111111

AとA'どちらかだけが1の時に、1を出力するので
演算結果は
11111100
となる。

###ビットを取り出す
ビットを取り出す場合は、論理積(AND)を利用する。
対象となるビット列をB = 01101011 とする。

1.取り出したい位置に1を入れたビット列B'をマスクパターンとして用意する。
下4桁を取り出すと仮定して、B' = 00001111 とする。

2.B AND B' をとる
B 01101011
B'00001111

BとB'どちらも1の時に、1を出力するので、
演算結果は
00001011となり、指定したビットを取り出すことができる。
Magenta(Googleの音楽機械学習ライブラリ）のRNNセルはどこにあるのか？

Magenta(Googleの音楽機械学習ライブラリ）のRNNセルはどこにあるのか？
またどの様に書き換えや開発を行うのか？

基本的にMagentaのRNNセルはevents_rnn_graph.pyという共有ファイルの中に記述されています。

GitHubのレポジトリでいうと

https://github.com/magenta/magenta/blob/d1b5ea5853a19890a5db2fd5eb0afe3a3778be15/magenta/models/shared/events_rnn_graph.py

の２８〜３２行目のmake_rnn_cell関数のところです。

```python:events_rnn_graph.py

def make_rnn_cell(rnn_layer_sizes,
                  dropout_keep_prob=1.0,
                  attn_length=0,
                  base_cell=rnn.BasicLSTMCell,
                  residual_connections=False):

```


base_cell=rnn.BasicLSTMCell
のBasicLSTMCellが選択されているRNNセルです。

このRNNセルはTensorFlowのRNNセルクラスですのでTensorFlowのサイトからセルの中身がどんな処理を行うプログラムなのか？確認する事ができます。

tf.compat.v1.nn.rnn_cell.BasicLSTMCellのページはこちら
https://www.tensorflow.org/api_docs/python/tf/compat/v1/nn/rnn_cell/BasicLSTMCell


おそらくLSTMが、音楽生成にはもっとも適していそうなので（当然Magentaの開発者の方々が1番検証されたでしょう）他のセルを試す必要はない様に思えます。
がもし、他のセルを使用したい場合はBasicLSTMCellを他のセルに変えれば良いわけです。


TensorFlowのRNNセルのページはこちらです。
どんなセルがあるか確認できます。

https://www.tensorflow.org/api_docs/python/tf/compat/v1/nn/rnn_cell

各セルの解説は今回はしません。
また全ての書き換えを実践・検証したわけではないのできるものできないものがあるかもしれませんが、可能なセルについては簡単に書き換えが可能でした。

音楽生成もそれぞれ違いを検証しましたが、すぐにわかる明らかな違いはありませんでした。
しかし、詳細に実践していけば当然違いはあると思います。
また何か発見したら報告したいと思います。
Rust で git cat-file -p コマンドを作る

晴れて無職となったので、今後はもうちょい積極的に更新していこうと思う。

### これは何
https://engineering.mercari.com/blog/entry/2015-09-14-175300/
こちらの記事で解説されていることをRustとGitの仕組みの勉強を兼ねて試してみた。

### 方法
zlib圧縮されたファイルを解凍する。


### 解説
#### 今回したこと
リポジトリは[こちら](https://github.com/makutak/git_cat_file_p)。

```sh
$ cargo run .git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad 
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/git_cat_file_p .git/objects/3b/18e512dba79e4c8300dd08aeb37f8e728b8dad`
hello world

$ cargo run .git/objects/a4/940ec3db4cd24542203a9447c4259c96294c09 | nkf -w
    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
     Running `target/debug/git_cat_file_p .git/objects/a4/940ec3db4cd24542203a9447c4259c96294c09`
坊っちゃん
夏目漱石

-------------------------------------------------------
【テキスト中に現れる記号について】
------
省略
------
```

こんな感じで`.git/objects/` 配下のファイルをzlib解凍して、`git cat-file -p <hash 値>` と同じ結果になるようにした。

#### コード
コードはDQNEOさんの記事で使われてるC言語のものをRustで書き直したものです。
DONEQさん、奥村先生、ありがとうございました！

```rust
use libflate::zlib::Decoder;
use std::{
    fs::File,
    io::{self, Cursor, Read},
    str,
};

fn usage() {
    println!("Usage: ");
    println!("git_cat_file_p blob_file");
}

fn decompress(mut file: File) -> Result<String, io::Error> {
    let mut buf = Vec::new();
    file.read_to_end(&mut buf).unwrap();

    let mut decoder = Decoder::new(Cursor::new(&buf)).unwrap();
    let mut decoded_data = Vec::new();
    decoder.read_to_end(&mut decoded_data).unwrap();

    unsafe {
        let str_data = String::from_utf8_unchecked(decoded_data);
        Ok(str_data)
    }
}

fn format(decoded: &str) -> &str {
    decoded.trim_end().split('\u{0}').collect::<Vec<_>>()[1]
}

fn main() {
    let args: Vec<String> = std::env::args().collect();
    if args.len() == 1 {
        usage();
        std::process::exit(1)
    }

    let f = File::open(&args[1]);

    let file = match f {
        Ok(file) => file,
        Err(error) => panic!("{}: Can't open: {}", error, args[1]),
    };

    let decoded = decompress(file).unwrap();
    let formatted = format(&decoded);
    println!("{}", formatted);
}
```

ただファイルをオープンして、それをzlib解凍して、コンテンツ本体部分を取り出して出力するだけというシンプルなものです。
`String::from_utf8`でなく、`String::from_utf8_unchecked`を使っているのは、Shift_JISのときにエラーになるため。(坊っちゃんのファイルがShift_JIS)

改めて見ると、コンテンツ本体を取り出す方法`format` 関数のところをもっとスマートにできたらいいなあって感じですね。

### 参考記事
大変参考になりました。ありがとうございました。

- https://engineering.mercari.com/blog/entry/2015-09-14-175300/  
- https://oku.edu.mie-u.ac.jp/~okumura/compression/zlib.html

### 備考
自身の[はてなブログ](https://noukomakuta.hatenablog.com/entry/2021/02/02/021109)より転載。
CentOS7でのquotaの設定

ディスクの容量というのは、通常あまり気にしていないのだけれども、使い切ると結構深刻な事態がが生じる。ディスクの残量が少ない状況では、システムが極めて遅くなることが多いし、ディスクを使い切ると、運が悪いとシステムが立ち上がらなくなることもある。というわけで、quotaで事前に使える要領に制限をかけたり、制限に近づいたりしたときに警告を出すようにしておくと、こゝろ安らかに過ごすことができる。

参考にさせていただいたURL: [【CentOS7】xfsファイルシステムでのクォータ（quota）設定 | server-memo.net](https://www.server-memo.net/centos-settings/system/quota_xfs.html)

# quotaのインストール
以下でインストール。

```bash
yum install quota
```
とはいえ、ミニマルインストールでなければ、入っていることも多い。

# quotaでファイルの容量制限ををユーザー単位で設定
quotaでファイルの容量制限がかけられるのは、ユーザー単位、グループ単位、プロジェクト単位がある。ここでは、大学の研究室位を単位とする、小規模なサーバーを念頭に、ユーザーの単位で制限をかけることを考える。

## パーティションの設定
quotaを適用するには、mountする際に関連属性を付けておく必要がある。裏を返すと、パーティション単位で監視対象になるか否かが決まる。
一例として、以下のような形で`/home`がmountされているとする。(CentOS7を念頭に置いているのでxfsでマウントされているとする)

```:/etc/fstab(抜粋)
UUID=hogehogehogehogehogehogehogeohgeohge /home                   xfs     defaults        0 0
```
この`/home`をユーザー単位のquotaで管理には、以下のように`uquota`オプションを付けてマウントする。

```:/etc/fstab(抜粋)
UUID=hogehogehogehogehogehogehogeohgeohge /home                   xfs     defaults,uquota 0 0
```
このように設定ファイルを書き換え、`# umount /home`でアンマウントした後に`# mount /home`をすることで、quotaが適用できる状態になる。(一般ユーザーでログインしており、かつその`${HOME}`が`/home`にある場合は、この手続きでbusyになってしまって、umountできない。直接rootにログインする必要がある。)

quotaの設定は`# xfs_quota -x -c 'report -h' パーティション`のコマンドで確認できる。この設定の場合は、`# xfs_quota -x -c 'report -h' /home`を実行すると以下の感じの出力が得られる。(グループ、プロジェクト単位のquotaも、設定されていればこれに引き続いて表示される)

```
User quota on /home (/dev/sdb1)
                        Blocks
User ID      Used   Soft   Hard Warn/Grace
---------- ---------------------------------
root            0      0      0  00 [------]
user1         48K      0      0  00 [------]
user2         48K      0      0  00 [------]
user3       38.1M      0      0  00 [------]
user4         56K      0      0  00 [------]
```
このsoftとhardの欄に現れている0の表示は、**quotaが設定されていないこと**を意味する。

## quotaの制限要領を設定
コマンドは、`# xfs_quota -x -c 'limit bsoft=サイズ bhard=サイズ 設定ユーザ'　パーティション`で、設定ユーザーにquotaで制限をかけられる。例えば`# xfs_quota -x -c 'limit bsoft=400G bhard=500G user3' /home`を実行してから`# xfs_quota -x -c 'report -h' /home`を見ると

```
User quota on /home (/dev/sdb1)
                        Blocks
User ID      Used   Soft   Hard Warn/Grace
---------- ---------------------------------
root            0      0      0  00 [------]
user1         48K      0      0  00 [------]
user2         48K      0      0  00 [------]
user3       38.1M   400G   500G  00 [------]
user4         56K      0      0  00 [------]
```
なる出力が得られる。

## 一般ユーザーの各自の確認
quotaが入っていれば、`$ quota -s`で自分のアカウントの状況は確認できる。例えば

```
Disk quotas for user user3 (uid 1002):
     Filesystem   space   quota   limit   grace   files   quota   limit   grace
      /dev/sdb1  39000K    400G    500G             249       0       0
```
みたいな感じ。

## soft limitを超えたらどうなるの？
私の場合は

```console
/usr/bin/xauth: error in locking authority file /home/user/.Xauthority
```
が出た。それと、ログイン後にすごく時間がかかる。
このメッセージに関連して色々調べてみて処方箋を試してみた(例えば、一回`.Xauthority`を消すとか)が、問題は解決せず。多分、soft limitにあたって、新しいファイルを作ることが阻害され、それに関連して問題が現れていた模様。
不要なファイルを消したら、この問題は生じなくなった。
Hamlの書き方

<H1>Hamlとは？</H1>
* HamlとはHTML abstraction markup languageの略
* HTMLのコードをより効率よく書くことができる
* PHPやRubyOnRailsで使用される
* エディター上のhamlファイルは、ブラウザ上ではHTMLのコードに変換されて表示される

**公式サイト**
https://haml.info/

**HTML⇄Haml変換サイト（勉強用）**
https://htmltohaml.com/

<h2>基本的な書き方</h2>
||HTMLでの書き方|Hamlでの書き方|
|----|----|----|
|DOCTYPE宣言|<!DOCTYPE html>|!!!|
|コメント（HTMLコードに変換される）|<!-- コメント -->|/ コメント|
|コメント（HTMLコードに変換されない）|<!-- コメント -->|-# コメント|
|タグ|`<body>`|%body|
|class属性|`<div class="class1">`|.class1|
|id属性|`<div id="id1">`|#id1|
|属性|`<div class="class2" style="color: red">`|.class2{style: "color:red"}|
|属性|`<div class="class2" style="color: red">`|.class2{:style => "color:red"}|
|cssを適用|`<style> ~ </style>`|:css|
|javascriptを適用|`<script> ~ </script>`|:javascript|
|式埋め込み|<% price = 500 * 1.1 %>|- price = 500 * 1.1|
|文字列埋め込み|`<%= item.name %>`|=item.Name|


* Hamlでは、属性付きのdivタグはdivを省略可能です。
* 以下の例文のようにインデントをつけることで階層構造をつけることができます。

```Sample.html.haml
!!!
 %html
  %body
   %table
    %tr
     %td 列1
     %td 列2
     %td 列3
```
GAEでNode.jsのバックエンドサーバーを用意するときは、ファイル名をserver.jsにしよう。

GAEにNode.jsのサーバーを用意して、デプロイしたのだが、
公開したページにアクセスすると
`Error: Server Error The server encountered an error and could not complete your request. Please try again in 30 seconds`
というエラーが表示された。

GCPでログを確認してみると、server.jsがないと言われているため、エラーになっていたらしい。
<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/640981/2d059bdf-2aba-c573-d6d4-9b8886fec475.png"/>
[ログ確認場所](https://console.cloud.google.com/logs/)

package.jsonの`"main": "index.js",`は関係ないのかな。
私の理解が間違っているのか。
勉強しよう！
Matlabのzscore()をpythonで

スケーリングといえばやっぱりzスコアが基本でしょ。

基本なだけに、色々とやり方はあるけれど。
matlabのzscore()にはscipy.stats.zscore()がほぼ同じ。
ほかには、scikit-learnでも便利なのがあるらしい。

# scipy.stats.zscore()

matlabでXのDim軸方向zscore(X,flag,Dim)で求める。
flagはデフォルトで0で、flag=0のときはn-1で、flag=1のときはnで割ったstdを使う。

同じことは、scipy.stats.zscore(X,axis=Dim-1, ddof=1-flag)でできる
ここでDim-1としてるのは、Pythonではaxisｊは0から始まるので、Matlab的な書き方に合わせるとこうなるから。
ddofを1-flagとしているのは、0のときはn、1のときはn-1で割ったstdを使うので、matlabと０、１が反転しているから。
もっとも、ddofは自由度を表しているので、scipyの方が理にかなっているように見える

# 例:zscore() in Matlab
```matlab
>> zscore(sin((-1:0.25:1)*pi),0)

ans =

   -0.0000   -1.0000   -1.4142   -1.0000   -0.0000    1.0000    1.4142    1.0000    0.0000
```
# 例:scipy.stats.zscore() in Python
```python
>>> import numpy as np
>>> from scipy import stats
stats.zscore(np.sin(np.arange(-1,1.1,0.25)*np.pi),ddof=1)
array([-1.92434679e-16, -1.00000000e+00, -1.41421356e+00, -1.00000000e+00,
       -1.92434679e-17,  1.00000000e+00,  1.41421356e+00,  1.00000000e+00,
        1.53947743e-16])
```
np.arange(-1,1,0.25)とすると、1が入らないので、範囲を揃えるためにnp.arange(-1,1.1,0.25)としている。
どこで丸めるかという差はあるが、同じ結果。

# scikit-learnのpreprocessing.StandardScaler()
zスコアを出すのに使うmean/stdをとってくるデータと、実際にスコアに落とすデータを分けられて、それぞれ１行で書けるという便利なやつがある、らしい。
つまり、Matlabのzscoreより便利なやつがある、と。
これはまた、気が向いたら書くかも。
オハイオリージョンのEBSがずっと課金されていた話

## 概要

半年ほど前からudemyで継続的にAWSの学習を進めているのですが、最近「あれ？請求額思ったより高くない？」と感じたとので調べてみた所、停止状態のEC2のEBSがずっと課金されていたことが分かりました。(初歩的ミス..)

特にAWS初学者の方は課金相場をよく分からないまま使ってる方も多いのではないでしょうか。
無駄な課金を抑えるためにも、請求詳細の$確認方法についてまとめてみました。



## 1.請求額詳細の確認

#### マイ請求ダッシュボードから請求情報を確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506412/3c9e9e1f-b59f-213b-85c2-b151a3df62c7.png)

#### 料金の使用状況はサイドバー「請求書」から確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506412/5feb4d44-7fd2-6a30-8528-4e4b0eda2ec4.png)


EC2が微妙に高い...
最近AWSの料金相場が分かってきた私、ようやくおかしいことに気づく。
確認したところ、オハイオリージョンのEBSの料金が加算されていた模様。多分AWSを触り始めてだいぶ初期にやったミスがずっと残っていたのでしょう...

ちなみにEC2の利用料は...t2.microのインスタンスで約0.015`$`=1100円/月、EBSは0.1`$`/GB・月、位です
自分の使用してるサービスの課金額の目安は大体でいいから把握しておくといいですね。

## 2.EC2の意外な落とし穴

EC2の課金には注意する点が二つあります。

- ElasticIPアドレス
- EBS


ElasticIPアドレスはインスタンスに固定のグローバルIPアドレスを付与するためのサービスですね。
こちらは**インスタンスにアタッチしてない場合のみ** 0.005$/hのペースで課金されていきます。
未使用のElasticIpアドレスは消していこう！


EBSはストレージサービスの一つですね。0.72`$`の原因がこれでした。
EBSはインスタンス内のデータを保存しておく場所、EC2インスタンスを立ち上げると大抵それにくっついてEBSも作成されます。(料金は1Gあたり約0.1`$`/月)EC2を停止しただけではEBSは消えないので注意ですね。


## 3.リージョンに注意すべし

プルダウンを開くと課金の詳細が見れるようになっています。  
ん？オハイオリージョンなんて使った覚えないけど...
しかもインスタンス本体ではなくEBSの課金、毎月数百円の請求だから今までちゃんと見てなかった...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506412/44e2f79e-0aac-7cec-9b91-404dc392b4a3.png)

サービスによっては利用可能なリージョンが限られているので、リージョンを移動した際に未使用サービスが残らないように注意が必要ですね。

#### オハイオリージョンに移動

こいつか、さいなら！(削除)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506412/7c960f19-69e8-7518-121a-7087846643ab.png)


### まとめ

無駄な課金がないか定期的に確認しましょう。


**参考**
https://dev.classmethod.jp/articles/cost-check-point/
TMDB APIを使う

# 何をしたのか
映画やドラマの感想を書けるチャットサイトを作っていて、映画とかのポスターを取得できるAPIないかなと思って調べたらTMDBのAPIというのを見つけました。
そのAPIがすごく便利だったのでTMDBのAPIをどう使ったのかを書きました。

[作ったチャットサイト](https://yoin-chat.netlify.app/)

# TMDBとは
https://www.themoviedb.org/
「The Movie Database」の略で映画やテレビ等のデータベースのようです。
海外のサイトのようですが日本の作品も結構あるみたいです。

# 検索
作ったチャットサイトは『トークルームを作成→そのトークルームでチャット』という流れになっています。
トークルームの作成でTMDBのAPIの検索機能を使いました。
例えば「ルパン」で検索した場合は下のようになりました。
切り取ったので画像は一部しか載ってないのですが、たくさんヒットしました。
![スクリーンショット 2021-02-02 0.47.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1057421/a427a8ef-c5ef-d4a1-f2ff-546cb4339c89.png)

コードは下のようになりました。
今回は`searchWord`には「ルパン」、`TMDB_API_KEY`にはTMDBのAPI用のkeyが入っています。
`TMDB_BASE_URL`は`https://api.themoviedb.org/3/search/movie`となっています。

```javascript
const params = {
  params: {
    query: searchWord,
    page: 1,
    language: 'ja-JA',
    api_key: process.env.TMDB_API_KEY
  }
}

try {
  const res = await axios.get(TMDB_BASE_URL, params)
  if (!res || !res.data) return

  const movies = res.data.results.map((result: any) => {
    return {
      title: result.title,
      image: result.poster_path
    }
  })
  commit('setMovies', movies)
} catch (e) {
  throw e
}
```

レスポンスは下記のようになりました。
今回は`title`と`poster_path`だけ取得しました。

```json
{
  "page":1,
  "results": [
    {
      "adult":false,
      "backdrop_path":"/z1N17Y5q1EE0IMrBbALyCHBuNE8.jpg",
      "genre_ids":[28,12,35],
      "id":241868,
      "original_language":"ja",
      "original_title":"ルパン三世",
      "overview":"ユリウス・カエサルがクレオパトラ7世に贈った・・・",
      "popularity":7.743,
      "poster_path":"/nJ2Ra5Y6l4CL11aqvPkIasFycoL.jpg",
      "release_date":"2014-08-30",
      "title":"ルパン三世",
      "video":false,
      "vote_average":6,
      "vote_count":63
    },
    {
      "adult":false,
      "backdrop_path":"/iQgb3uBH2JYGqc2Gje3MlXEGPx7.jpg",
      ・・・
    }
  ]
}
```

# ポスター
先ほど取得した`poster_path`でポスター画像を表示できます。
例えば下記のようにimgタグに指定すれば画像が表示されます。

```html
<img src="https://image.tmdb.org/t/p/w185/z1N17Y5q1EE0IMrBbALyCHBuNE8.jpg" />
```

URLの`w185`は画像のサイズで他に下記のサイズを指定できます。

```javascript
"poster_sizes": [
  "w92",
  "w154",
  "w185",
  "w342",
  "w500",
  "w780",
  "original"
]
```

# 参考
https://developers.themoviedb.org/3/configuration/get-api-configuration
【解決法】’steps_per_epoch=None’ is only valid a generator based on the ‘keras.utils.Sequence’ class. と出てしまった



こんにちは。かをるです。

機械学習を進めていて、このエラーに陥ってませんか？

最初は意味が分からず苦戦しましたが、解決法がわかりましたので困っている方はご覧ください。

詳細はブログに記載しました。
https://kaworublog.com/steps_per_epochnone/
curl コマンドを Node.js に変換するなら curlconverter が便利かも

## curlconverter とは

curlconverter は curl コマンドをプログラミングコードに変換してくれるツールです。
下記のURLでブラウザ上で試すことができます。
https://curl.trillworks.com/
![スクリーンショット 2020-11-28 23.49.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/195024/3e77a942-223c-9149-d251-f8f57796aaa0.png)


Python, Node.js, R, PHP, Go, Dart, Elixir, Rust などの言語 JSON への変換などにも対応しているようです。

開発しながらAPI ドキュメントを読んで curl コマンドを自分の開発言語で読み替えている方も多いと思います。
こちらのツールを使わせていただいて自動変換すれば作業が捗りそうです。

GitHub のリポジトリはこちらでした。
NickCarneiro/curlconverter
https://github.com/NickCarneiro/curlconverter


## 例

たとえば PayPal Developper のドキュメントの Orders API の curl コマンドをコピペで入力し、変換先に node.js (fetch) を選択してみると、
https://developer.paypal.com/docs/api/orders/v2

```bash
curl -v -X POST https://api.sandbox.paypal.com/v2/checkout/orders \
-H "Content-Type: application/json" \
-H "Authorization: Bearer Access-Token" \
-d '{
  "intent": "CAPTURE",
  "purchase_units": [
    {
      "amount": {
        "currency_code": "USD",
        "value": "100.00"
      }
    }
  ]
}'
```

以下のように `fetch`を使った node.js 上で動作する JavaScript に変換されました。

```js
var fetch = require('node-fetch');

fetch('https://api.sandbox.paypal.com/v2/checkout/orders', {
    method: 'POST',
    headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer Access-Token'
    },
    body: JSON.stringify({ "intent": "CAPTURE", "purchase_units": [ { "amount": { "currency_code": "USD", "value": "100.00" } } ] })
});
```
【備忘録】macのターミナルコマンド（基本編）

## ◆◇よく出る言葉◆◇
ディレクトリ・・・フォルダのこと。
カレントディレクトリ・・・現在いるディレクトリのこと。
ホームディレクトリ・・・ターミナルを起動したときのデフォルトのディレクトリのこと。

## ◆◇コマンド一覧◆◇
**ls コマンド**
カレントディレクトにあるファイルを表示する。（listの略）
`ls   ⇒ カレントディレクトリにあるファイルやディレクトリを表示する`
`ls -l  ⇒ ファイルやディレクトリの詳細も同時に表示する`
`ls -a   ⇒ 隠しファイルも含めファイルやディレクトリを全て表示する`
`ls −la   ⇒ 隠しファイルを含む全てのファイルやディレクトリの詳細を表示する`

**cd コマンド**
カレントディレクトリにあるファイルに移動する。（change directoryの略）
`cd test.html ⇒ testというファイルに移動する`
`cd ~/  ⇒ ホームディレクトリに移動する`
`cd ..  ⇒ 一つ上の階層のファイルに移動する`

**pwd コマンド**
カレントディレクトリのパスを表示する。（print working directoryの略）
`pwd  ⇒　カレントディレクトリのパスを表示する`

**touch コマンド**
中身が空のファイルを作る。
`touch test.html  ⇒　「test.html」という、中身が空のファイルを作る`

**mkdir コマンド**
新しい空のディレクトリを作る。（make directoryの略）
`mkdir test  ⇒　testというファイルを作る`

**mv コマンド**
ファイルを移動したり、ファイル名を変更したりする。（moveの略）
`mv test.html tmp/  ⇒　test.htmlというファイルを相対パスでtmp/に移動する`
`mv test.html test2.html   ⇒　test.htmlというファイルをtest2.htmlに名前変更する`

**cp コマンド**
ファイルをコピーする。（copyの略）
`cp test.html tmp/   ⇒　test.htmlを相対パスでtmp/というディレクトリの中にコピーする`
`cp test.html test2.html   ⇒　test.htmlをtest2.htmlという名前でコピーする`
`cp −r dir /tmp/   ⇒　dirというディレクトリとその中身を絶対パスで/tmp/にそっくりコピーする`

**rm コマンド**
ファイルを削除する。（removeの略）
`rm test.html  #test.htmlを削除する`
`rm -r test  #testというディレクトリとその中身を削除する`
`rm -f test  #testというファイルを警告なしで削除する`
`rm -rf test  #testというディレクトリとその中身を警告なしで削除する`
　　※rmコマンドは取り返しのつかないファイルの削除になる。
　　　コマンドにあまり慣れていない人は、使わないほうがいい。

**openコマンド**
ターミナルからFinderでファイルを開く。
`open .  #現在のターミナルのディレクトリFinderで開く`
`open ~/  #ホームディレトリをFinderで開く`

**source コマンド**
ファイルの設定を読み込み有効にする。
`source ~/.bash_profile  #ホームディレクトリにある.bash_profileに書き込んだ設定を読み込み有効にする`
`source .bash_profile  #カレントディレクトリにある.bash_profile設定を読み込み有効にする`

**history コマンド**
これまでのコマンド履歴を表示する。
`history  #これまで実行してきたコマンドの履歴を表示する`
`history -c  #これまで実行してきたコマンドの履歴を消去する`
Matlabのnormpdf()をpythonで

何かとお世話になるガウシアンの書き方。
scipyのstatsを使うのが良さそう。

#
matlabで平均M,分散SのXでのPDFはnormpdf(X,M,S)で求める。
同じことは、scipt.stats.norm.pdf(X,M,S)でできる。

#例:normpdf() in Matlab
```matlab
>> normpdf(-2:0.5:2,0,1)

ans =

    0.0540    0.1295    0.2420    0.3521    0.3989    0.3521    0.2420    0.1295    0.0540
```

#例:scipy.stats.norm.pdf() in Python
```python
>>> from scipy import stats
>>> import numpy as np
>>> stats.norm.pdf(np.arange(-2,2,0.5),0,1)
array([0.05399097, 0.1295176 , 0.24197072, 0.35206533, 0.39894228,
       0.35206533, 0.24197072, 0.1295176 ])
```

ほとんど一緒。

#other than normal?
ここでは正規分布を扱ったので、stats.normだったけど、
このnormを色々と変えると、ポアソンやらガンマやら、色々な分布を同じように扱えるらしい。