techno_memo

個人用の技術メモ。python・ROS・AI系のソフトウェア・ツールなどの情報を記載

トップページ

このブログのコンセプト

業務等で活用しやすい『機能単位』でノウハウをまとめる

  • イラスト1つでやりたいことがわかる構成とする

  • 一般的なPCの開発環境(Windows+Anaconda等)ですぐに試せるコードをgithubに残す

  • 詳細な機能の記事(各種ライブラリに関する使い方説明など) は他サイトのリンクにとどめる

カテゴリ

pythonによるデータ分析

  • 業務等でpythonスクリプトを用いたデータ処理・業務改善を行うことを想定した場合のノウハウまとめ

f:id:sd08419ttic:20190321220444p:plain

データ読み込み

題目 説明 リンク
数値データの読み込み 指定したフォルダの各種ファイル(csv/xlsx/json等)から数値データを読み込む リンク
画像・動画データの
読み込み
指定したフォルダの画像・動画ファイル(jpg/png/avi等)から数値データを読み込む リンク
Webサイトからの
データ取得
WEBサイトから情報を取得する リンク
命名規則・作成日などの
条件付きファイル探索
条件にマッチしたファイルだけを探索して取得する リンク

前処理

題目 説明 リンク
画像データの前処理 画像データを処理しやすいように整える(サイズ・ノイズ除去など) リンク
数値データの前処理 数値データのノイズ・欠損値を処理する リンク
数値データマージ・削減 データの内容に応じてマージ・削減する処理 リンク

特徴抽出/パターン認識

題目 説明 リンク
物体検出① 簡易的な物体検出を行う(テンプレートマッチング/色検出/エッジ検出) リンク
物体検出② YoloV3を用いたWebカメラ画像の物体検出 リンク
統計処理 入力データの特性を算出して可視化する TBD
機械学習 データの特性を学習し、適切に分類する TBD

GUI出力/ユーザー要求処理

題目 説明 リンク
GUI tkinterを用いたGUI実装 リンク
グラフ表示 matplotlibを用いたデータの可視化 リンク
グラフ表示(アニメーション) matplotlibのアニメーション描画 リンク
exe化 pyinstllerを用いたpythonスクリプトの実行ファイル化 リンク
ユーザー入力の受理 pygameを用いたキーボード/ゲームパッド操作取得 リンク

電子工作プロトタイピング

f:id:sd08419ttic:20190221233311p:plain

前提知識

題目 説明 リンク
開発環境 プロトタイプ用ハード・開発環境に関する考え方 リンク
Raspberry Pi開発環境(ハード) 必要なハードウェアについて リンク
Raspberry Pi開発環境(ソフト) Ubuntu mate/ROSの導入方法について リンク
ソフトウェアアーキテクチャ プロトタイピング時のソフトウェアアーキテクチャについて リンク

環境構築

題目 説明 リンク
Pythonソフト構造 複数機能・ファイルから成り立つプロジェクトの構築 リンク
Python処理タイミング 各機能の動作タイミングの設計方法 TBD
Arduinoソフト構造 複数機能・ファイルから成り立つプロジェクトの構築 リンク
Arduino処理タイミング 各機能の動作タイミングの設計方法 リンク

通信機能

題目 説明 リンク
ArduinoとPCの通信 シリアル通信(USBケーブル) リンク
PCとの接続 リモートデスクトップ/カメラ画像の送信/信号の送信 TBD
クラウドサービスとの接続 IFTTT連携 (Google Home/スマートフォン) TBD

ROS開発

題目 説明 リンク
ROS基礎 概念/用語/コマンドの使い方 リンク
ROS基礎2 プロジェクト構築 リンク
PCとの通信 Ubuntu PCとRaspberry piとの接続/制御信号の通信 リンク
ロボットモデルの記述 URDFファイルにロボットのモデルを記述する リンク
移動ロボット基礎 シミュレーション上でロボットを移動させる リンク
移動ロボットの走行経路 ロボットの走行経路を設定する リンク
移動ロボットの経路追従 走行経路を追従する車速・角速度の制御 リンク

センシング

題目 説明 リンク
カメラセンシング Raspberry pi カメラを使った画像処理 リンク
各種センサ実装 各種センサの実装 TBD

loggingを用いた動作ログ出力

概要

 pythonのライブラリloggingを用いた動作ログの出力方法についてまとめる

logger

loggingはpython標準のログ出力用ライブラリであり、ソフトの動作(デバッグ用情報、エラー、例外など)の発生時刻やレベルを管理してログファイルに出力することができる。

loggerモジュールは下記の手順で使用する。

1. loggerの設定

loggerはログの生成・受け渡し等を管理するオブジェクトである。ログを出力ために、ソフトの最初でloggerを生成する。loggerはエラーの種類によって出力する対象を下記の5つのレベルで分類できる。

エラーレベル 使用例
DEBUG 10 開発時のみ使用するメッセージ
INFO 20 想定内の動作の確認用メッセージ(ソフトの起動/終了など)
WARNING 30 動作に影響のないエラー(正常値範囲外となる信号など)
ERROR 40 機能に影響のあるエラー(動作条件を満たせない信号異常)
CRITICAL 50 プログラムの動作に影響のある致命的なエラー

loggerが出力するレベルの閾値をlogger.setLevel関数で制限できる。setLevelで設定した値以下のエラーレベルの警告が無視されるようになる。開発時と正式運用で出力するログのレベルを調整したい場合に活用できる。

    filename = "test"
    logger = logging.getLogger(filename)
    logger.setLevel(10)    #DEBUG情報は表示しない

2. handlerの設定

handlerはloggerから受け取ったエラー情報の出力をするオブジェクトである。handlerに対して、エラー時に出力するメッセージのフォーマット設定をすることができる。

一例として、ログファイルにエラーの発生時刻・エラーレベル・logger呼び出し時に引数にセットした文字列を出力したい場合には次のように設定できる。

    #フォーマッタの設定
    fmt = logging.Formatter('[%(asctime)s] (%(levelname)s) %(message)s')
    #ファイルハンドラの作成
    fh = logging.FileHandler(filename, encoding='utf-8')
    #ファイルハンドラにフォーマッタを設定
    fh.setFormatter(fmt)
    #ファイルハンドラをロガーに設定
    self.logger.addHandler(fh)

クラスを使った簡易化

上記設定後に各モジュールがloggerを読み込んで出力用の関数(logger.debug("TEST") 等)を呼び出すとログ出力をすることができる。 しかし、実装が煩雑になるため関連処理をクラスにまとめておくと使用しやすくなる。下記ページで公開されているコードが参考になった。

resanaplaza.com

上記ページのLogManクラスをlogMan.pyとして保存しておいたときに、ログ出力を呼び出すときのコードを下記に示す。 注意点として、exceptionを呼び出す際にはエラー内容は自動的に表示されるため文字列には何も設定する必要はない

import os
from logMan import LogMan

if __name__ == '__main__':
    lm = LogMan(os.path.abspath('.')+"/log/log.txt",stdout=True)
    lm.info("Program started!!")

    #error A
    lm.error("Error A!!")

    #warning B 
    lm.error("WARNING B!!")

    #exception
    try:
        x = 1/0
    except:
        lm.exception("EXCEPTION X")
    
    lm.info("Program Finished!!")

生成されるログファイル

[2023-02-26 16:44:08,760] logMan.py (INFO) Program started!!
[2023-02-26 16:44:08,761] logMan.py (ERROR) Error A!!
[2023-02-26 16:44:08,761] logMan.py (ERROR) WARNING B!!
[2023-02-26 16:44:08,762] logMan.py (ERROR) EXCEPTION X
Traceback (most recent call last):
  File "d:\WS\VS_project\BlogProject\BlogProject\loggintTest.py", line 18, in <module>
    x = 1/0
ZeroDivisionError: division by zero
[2023-02-26 16:44:08,763] logMan.py (INFO) Program Finished!!

参考記事

qiita.com

plotlyによる3Dグラフ描画

概要

 pythonのライブラリ plotlyを用いて3Dグラフおよびアニメーションの表示をする方法について記述する

3Dグラフの表示

plotly で3次元の散布図を描画する例を下記に示す。scatter_3dを呼び出し3dxyzの座標を与えればグラフを描画できる。

import plotly.graph_objects as go
import plotly.express as px
import numpy as np
import pandas as pd

x = np.arange(20)
y = np.random.rand(20) *20
z = np.random.rand(20) *5

# plotly expresを使う場合
# df = pd.DataFrame({ 'x_data' : x,
#                     'y_data' : y,
#                     'z_data' : z})
#
#
# fig = px.scatter_3d(df, x='x_data', y='y_data', z='z_data')
# fig.show()

# graph objectを使う場合
fig = go.Figure(data=[go.Scatter3d(x=x,y=y,z=z,mode='markers')])
fig.show()

f:id:sd08419ttic:20211031161028p:plain

散布図ではなく平面図として描画したい場合には、Surfaceを用いる。 Surfaceではxyzの各辺の成分を代入して3D平面をプロットすることができる。

# -*- coding: utf-8 -*-
import plotly
import plotly.graph_objects as go
z=[
    [0.0,0.0,0.0,0.0,0.0]
    ,[0.0,1.0,2.0,3.0,0.0]
    ,[0.0,2.0,10.0,6.0,0.0]
    ,[0.0,1.0,2.0,3.0,0.0]
    ,[0.0,0.0,0.0,0.0,0.0]
]
fig = go.Figure(data=[go.Surface(z=z,x=[-5.0,-2.5,0.0,2.5,5.0],y=[-20,-10.0,0.0,10.0,20.0])])
fig.update_layout(
    title='Surface'
    ,scene=dict(
        xaxis=dict(title='x')
        ,yaxis=dict(title='y')
        ,zaxis=dict(title='z')
    )
)
fig.show()

f:id:sd08419ttic:20211205172442p:plain

複数グラフの描画(画像上に散布図を表示)

上記を組み合わせて複数のグラフを同時に描画することができる。 ここで、3DSurfaceのcolormapとして画像データを出力するようにすると、3D空間に平面として画像を表示しその上にデータをプロットすることができる。

# -*- coding: utf-8 -*-
import plotly
import plotly.graph_objects as go
from PIL import Image
import numpy as np

from PIL import Image
img_as_8bit = lambda x: np.array(Image.fromarray(x).convert('P', palette='WEB', dither=None))
dum_img = Image.fromarray(np.ones((3,3,3), dtype='uint8')).convert('P', palette='WEB')
idx_to_color = np.array(dum_img.getpalette()).reshape((-1, 3))
colorscale=[[i/255.0, "rgb({}, {}, {})".format(*rgb)] for i, rgb in enumerate(idx_to_color)]

im = np.array(Image.open('D:/VS_WS/pytest/image/Mandrill.bmp'))

trace=go.Surface(
        z=np.zeros([256,256])-50,
        surfacecolor=img_as_8bit(im),
        cmin=0, 
        cmax=255,
        hoverinfo= 'none',  #画像の各画素にホバーしたときの説明を非表示にする
        colorscale=colorscale,  
        showscale=False #右のカラーバーを非表示にする
          )
trace2=go.Scatter3d(x=[0, 10, 50, 100, 200],
                   y=[0, 30, 70, 150, 200],
                   z=[0,-10, 30, -20, 10],
                   mode='markers',
                   marker_color='rgba(0, 255, 0, .8)',
                   )

fig = go.Figure(
    data=[trace,trace2],
    layout_title_text="3D Face Mesh",
)

fig.show()
fig.write_html("3Dtry.html")

f:id:sd08419ttic:20211205172807p:plain

参考記事

plotly.com

www.dmysd.net

Postgres SQLの導入・環境設定・DBの読み込み

概要

PostgreSQLの導入とDBの基本操作についてまとめる

PostgreSQLの導入

Ubuntu 20へのPostgreSQLの導入は下記コマンドを実行する。

sudo apt update
sudo apt install postgresql postgresql-contrib

合わせてPostgreSQLGUI管理ツールである"pgadmin4"をインストールする。

sudo curl https://www.pgadmin.org/static/packages_pgadmin_org.pub | sudo apt-key add
sudo sh -c 'echo "deb https://ftp.postgresql.org/pub/pgadmin/pgadmin4/apt/$(lsb_release -cs) pgadmin4 main" > /etc/apt/sources.list.d/pgadmin4.list && apt 
update'
sudo apt install pgadmin4

インストール後にメールアドレスとパスワードを設定する。

sudo /usr/pgadmin4/bin/setup-web.sh

pgadmin4でDB情報にアクセスするためには、postgreSQLの管理用ロールである"postgres"のユーザー名を変更する必要がある。 下記コマンドでパスワードを変更する。 (xxxxxxxに設定したいパスワードを入力)

sudo -u postgres psql -c "ALTER ROLE postgres WITH password 'xxxxxxx'"

また、デフォルトではDBのアクセス設定とubuntuのユーザー名が一致していないとエラーとする設定としているため/etc/postgresql/12/main/pg_hba.confの 下記行を変更する。

# "local" is for Unix domain socket connections only
local   all             all                                     md5

上記設定を完了後に下記コマンドでpostgreSQLのサービスを再起動してブラウザでhttp://127.0.0.1/pgadmin4/にアクセスする。

sudo service postgresql restart

pgadminの左の"Servers"を右クリックしてCreate->Serverを選択し、下記設定を入力する。 (HostName以降の設定はConnectionタブに切り替えて入力)

Name: PostgreSQL 12
ServerGroup: Servers
HostName/address: localhost
Port: 5432
Username: postgres
Password: xxxxxxx (↑の手順で入力したもの)
Store password: Checked

正しく設定できると下記のようにDB情報が表示される。 f:id:sd08419ttic:20211114150508p:plain

roleの作成

最初から登録してあるroleの"postgres"はユーザー登録等に使うスーパーユーザー権限を持つ管理者用のroleである。 データベース操作は他roleで行ったほうが良いためroleを追加する。pgadmin4の”Login/Group Rolesを右クリックして新規roleを追加する。 この際、"Privileges"タブから新規DBを作成する権限を付与する。

f:id:sd08419ttic:20211114151239p:plain

DBの読み込み

DBの基本操作の題材として、postgreSQLチュートリアル用に下記サイトでサンプルDBを公開している。

www.postgresqltutorial.com

上記サイトからdvdrental.zipをダウンロードする。その後、読み込み用のDBをpgadminから新規作成する。(ownerを↑で作成したroleにしておく) その後下記コマンドを用いてサンプルDBをリストアする。

pg_restore -d newdb --role=user -O -x '/home/path/dvdrental.tar' 

正しく読み込めると下記のようにサンプルDBが表示できる。

f:id:sd08419ttic:20211114171719p:plain

参考書


これからはじめる PostgreSQL入門

参考サイト

postgresweb.com

obel.hatenablog.jp

plotlyによるグラフ描画

概要

 pythonのライブラリ plotlyを用いて数値データをグラフ描画する。

plotly

plotlyはブラウザでインタラクティブに操作可能なグラフを生成することができる。 本記事では基本的な使い方と設定方法についてまとめる。

基本的なグラフの描画

plotlyのインストールは下記pipコマンドで行う。

pip install plotly

基本的なグラフの描画方法は公式チュートリアルの下記ページにまとめてある。

[https://plotly.com/python/line-charts/:embed:cite]

上記にはplotly expressという高レベルapiによる描画方法と従来のplotlyの描画方法(Graph objects)による方法が記述されている。 それぞれの方法でy=x2の線・散布図・棒グラフを下記のように記述することができる。

import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import numpy as np

x = np.arange(10)

#plotly expressによる描画
df = pd.DataFrame({ 'x_axis_label' : x,
                    'y_axis_label' : x**2})
fig = px.line(df, x="x_axis_label", y="y_axis_label", title='plot test') #散布図
#fig = px.scatter(df, x="x_axis_label", y="y_axis_label", title='plot test') #散布図
#fig = px.bar(df, x="x_axis_label", y="y_axis_label", title='plot test') #棒グラフ

#graph objectによる描画
#fig = go.Figure(data=go.Scatter(x=x, y=x**2, mode="lines"))  #線グラフ
#fig = go.Figure(data=go.Scatter(x=x, y=x**2, mode="markers"))  #散布図
#fig = go.Figure(data=go.Bar(x=x, y=x**2))  #棒グラフ


#描画設定

fig.update_layout(
    title_text='plot test',
    title_x=0.5,    #グラフタイトルを中央に寄せる
    xaxis_title_text='x axis label',    #x軸ラベル
    yaxis_title_text='y axis label',    #y軸ラベル
    title_font_size=30,                 #タイトルフォントサイズ
    title_font_family='Times New Roman',    #タイトルフォント
    title_font_color='red'  #タイトル色
)
fig.show()

f:id:sd08419ttic:20211024160328p:plain

plotly expressで描画する場合はpandas data frameを引数として指定する必要があるため、numpyのデータをpandasに変換する処理が必要となる。 また、タイトル名・軸名等は引数として設定することができる。graph objectの描画ではnumpyのデータを引数として指定する。グラフタイトルなどの設定はupdate_layoutによって設定する。

複数のグラフの描画

同じ軸設定で複数のグラフを表示する場合は下記のように実装できる。

import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import numpy as np

x = np.arange(10)

#plotly expressによる描画
# df = pd.DataFrame({ 'x_axis_label' : x,
#                     'y_data' : x**2,
#                     'y_data2' : x**2 -2.0,
#                     'y_data3' : x**2 * 0.5,})
#fig = px.line(df, x="x_axis_label", y=["y_data","y_data2","y_data3"], title='plot test') #線グラフ
#graph objectによる描画
fig = go.Figure()
fig.add_trace(go.Scatter(x=x, y=x**2, mode="lines"))
fig.add_trace(go.Scatter(x=x, y=x**2-2.0, mode="lines"))
fig.add_trace(go.Scatter(x=x, y=x**2 * 0.5, mode="lines"))

#描画設定
fig.update_layout(
    title_text='plot test',
    title_x=0.5,    #グラフタイトルを中央に寄せる
    xaxis_title_text='x axis label',    #x軸ラベル
    yaxis_title_text='y axis label',    #y軸ラベル
    title_font_size=30,                 #タイトルフォントサイズ
    title_font_family='Times New Roman',    #タイトルフォント
    title_font_color='red'  #タイトル色
)
fig.show()

f:id:sd08419ttic:20211024163906p:plain

plotly expressでは描画したいデータのy軸を含むcolumn名を指定すれば良い。 graph objectでは描画したいデータをfig.add_traceで追加する。

異なる種類のグラフを同じ画面で描画することもできる。

import plotly.graph_objects as go
import plotly.express as px
import pandas as pd
import numpy as np

x = np.arange(10)

#plotly expressによる描画
df = pd.DataFrame({ 'x_axis_label' : x,
                     'y_data' : x**2,
                     'y_data2' : x**2 -2.0,
                     'y_data3' : x**2 * 0.5,})
fig = px.line(df, x="x_axis_label", y=["y_data"], title='plot test') #線グラフ
fig2 = px.scatter(df, x="x_axis_label", y=["y_data2"],color_discrete_sequence=["red"]) #線グラフ
fig3 = px.bar(df, x="x_axis_label", y=["y_data3"],color_discrete_sequence=["green"]) #線グラフ
fig.add_trace(fig2.data[0])
fig.add_trace(fig3.data[0])

#graph objectによる描画
#fig = go.Figure()
#fig.add_trace(go.Scatter(x=x, y=x**2, mode="lines"))
#fig.add_trace(go.Scatter(x=x, y=x**2-2.0, mode="lines"))
#fig.add_trace(go.Scatter(x=x, y=x**2 * 0.5, mode="lines"))

#描画設定
fig.update_layout(
    title_text='plot test',
    title_x=0.5,    #グラフタイトルを中央に寄せる
    xaxis_title_text='x axis label',    #x軸ラベル
    yaxis_title_text='y axis label',    #y軸ラベル
    title_font_size=30,                 #タイトルフォントサイズ
    title_font_family='Times New Roman',    #タイトルフォント
    title_font_color='red'  #タイトル色
)
fig.show()

f:id:sd08419ttic:20211029005108p:plain

plotly express で各グラフの色を変えるためにはcolor_discrete_sequenceオプションを使うことに注意する。

グラフの保存

描画したグラフはhtmlや画像(png/jpeg等)で保存することができる。 保存する場合は下記関数を呼び出す。

fig.write_html("path/to/file.html")
fig.write_image("ファイル名(パス含む).拡張子")

htmlの保存時に必要なライブラリがエラーが発生する場合がある。警告に従って下記コマンドで必要なライブラリをインストールして解消できる。

pip3 install kaleido

参考記事

plotly.com

matplotlibによる3Dグラフ描画

この記事の目的

matplotlibを用いて3Dグラフを描画する方法についてまとめる

matplotlibを用いた3D線グラフ・散布図の描画

matplotlibで3Dグラフを描画する場合は下記のように実装する。

  • (1) 3D描画用モジュールのインポート

matplotlibのインポート時に3次元描画に関するライブラリ(mpl_toolkitsのAxes3D)をインポートする。

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
  • (2) 3D軸設定

描画する軸の設定時引数projection='3d'を付与することで3次元軸を追加する。

ax = fig.add_subplot(1,1,1,projection='3d')     #subplotの追加 (行/列/描画対象インデックス,3次元軸の追加)
  • (3) plot,scatter関数を3次元データを引数として呼び出す・

描画用関数(線グラフであればplot、散布図であればscatter)を呼び出す時にxyzの各座標を引数として呼び出す。 その際、xyzのデータ数は一致させる必要がある。

# xy平面にsin関数を描画する
xs = np.linspace(-np.pi, np.pi, 100)
ys = np.sin(xs)
ax.plot(xs, ys, zs=0, zdir='z', label='sin (x, y)')

上記を組み合わせて3次元軸にsin・cosを描画するサンプルコードを下記に示す。

import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(1,1,1,projection='3d')     #subplotの追加 (行/列/描画対象インデックス,3次元軸の追加)

# xy平面にsin関数を描画する
xs = np.linspace(-np.pi, np.pi, 100)
ys = np.sin(xs)
ax.plot(xs, ys, zs=0, zdir='z', label='sin (x, y)')

# xz平面にcos関数を描画する
xs = np.linspace(-np.pi, np.pi, 100)
ys= np.zeros([100])
zs = np.cos(xs)
ax.scatter(xs, ys, zs, zdir='z', label='cos (x, y)',color="red")

ax.legend()
ax.set_xlim(-np.pi, np.pi)
ax.set_ylim(-np.pi, np.pi)
ax.set_zlim(-np.pi, np.pi)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

f:id:sd08419ttic:20211017171516p:plain

3次元グラフの底面に画像を描画する

3次元でxyzを描画する際、グラフの底面に地図などの平面画像を描画したい場合がある。 その場合、画像をsurfaceとして読み込んで描画することで平面画像とグラフを同時に描画することが可能になる。

画像の読み込みは下記のように行う。

from PIL import Image
from pylab import ogrid

img = Image.open('mapImage.png')
testImg = np.zeros([256,256,4])
testImg[:,:,0:3]= np.array(img.resize((256, 256)))/255
testImg[:,:,3]= 0.5
X1, Y1 = ogrid[0:testImg.shape[0], 0:testImg.shape[1]]
X1 = X1 - 128
Y1 = Y1 - 128
ax.plot_surface(X1, Y1, np.atleast_2d(-50.0), rstride=5, cstride=5, facecolors=testImg)

上記例ではPILライブラリで画像を読み込んでから256×256に初期化する。 ここで、画像を0-1のfloatにするため全体を255で除算している。 また、画像の4次元目は透明度なので、0-1で任意の値に指定する。(0が透明、1が不透明) その後、pylabのogrid関数でsurface用のXY座標を取得する。ここで画像の中心を0にするために-128を引いて調整している。 最後にplot_surface関数で画像を描画している。np.atleast_2dの引数はz軸の値として任意に指定する。

サンプルコードと結果を下記に示す。


import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from PIL import Image
from pylab import ogrid

fig = plt.figure()
ax = fig.add_subplot(1,1,1,projection='3d')     #subplotの追加 (行/列/描画対象インデックス,3次元軸の追加)

#画像の読み込み
img = Image.open('mapImage.png')
testImg = np.zeros([256,256,4])
testImg[:,:,0:3]= np.array(img.resize((256, 256)))/255
testImg[:,:,3]= 0.5

# 画像を挿入(0など任意の値にどうぞ)
X1, Y1 = ogrid[0:testImg.shape[0], 0:testImg.shape[1]]
X1 = X1 - 128
Y1 = Y1 - 128
ax.plot_surface(X1, Y1, np.atleast_2d(-50.0), rstride=5, cstride=5, facecolors=testImg)

# xy平面にsin関数を描画する
xs = np.linspace(-np.pi, np.pi, 100)
ys = np.sin(xs)
ax.plot(xs*50, ys*50, zs=0, zdir='z', label='sin (x, y)')

# xz平面にcos関数を描画する
xs = np.linspace(-np.pi, np.pi, 100)
ys= np.zeros([100])
zs = np.cos(xs)
ax.scatter(xs*50, ys, zs*50, zdir='z', label='cos (x, y)',color="red")

ax.legend()
ax.set_xlim(-150, 150)
ax.set_ylim(-150, 150)
ax.set_zlim(-150, 150)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')

plt.show()

f:id:sd08419ttic:20211017171707p:plain

参考サイト

sabopy.com

qiita.com

C言語用コーディングスタイルの設定(VS Code)

この記事の目的

C言語用のコーディングスタイルの設定方法について記述する。

clang_format によるコーディングフォーマット設定

clang_formatはC言語用のフォーマットツールであり、本ツールを用いることでコードを設定値に応じた書式に自動で変換することができる。 VS codeを用いた使用方法を下記に示す。

  • 1 Clang-formatの導入

Ubuntuの場合下記コマンドを用いてaptからclang-formatをインストールする。

sudo apt install clang-format

Windowsの場合下記サイトから最新のLLVMをダウンロードし、インストールする。 LLVMをパスに通す設定があるので、"Add LLVM to the system Path for all user" を選択してパスを通す。

releases.llvm.org

次にVS codeを起動し、拡張機能 clang-formatをインストールする。

marketplace.visualstudio.com

上記完了後、VS codeでフォルダを開く際のルートディレクトリに".clang-format"を作成して設定を記述する。

例として下記ファイルを保存する。

# ベースとするコーディングスタイル
BasedOnStyle: Google

# インデント幅4つ
IndentWidth: 4

# タブは使わない
UseTab: Never

# インクルードはソートしない
SortIncludes: false

# 関数の戻り値の型の後に改行を入れる(ただし宣言ではでは入れない)
AlwaysBreakAfterReturnType: AllDefinitions

# 関数定義のカッコだけ改行、ifとかwhileとかは改行しない。elseの前は改行する
BreakBeforeBraces: Stroustrup

# "case"の行でインデントを入れない
IndentCaseLabels: false

ファイルを保存する際にフォーマッタを実行したい場合は下記設定を有効にする。 editor.formatOnSave

また、フォーマッタのみを実行したい場合は"shift+ alt + f"でフォーマッタによる変換を実行することができる。

フォーマッタのルールについては下記サイトを参考として設定する。

pystyle.info

エディタ設定(改行・スペース等)

上記に加えて、VS Codeの改行・スペース等の設定も統一しておくとコード修正時のトラブルが少なくなる。

VS Codeの改行コード設定はsetting.jsonに下記記述を追加することで設定できる。

# 改行コードを\nに統一(Linux用設定)
"files.eol": "\n"

また、tabキーについてはvs codeでtabをスペース4つに置き換える設定をすることができる。 ただし、C言語での開発の場合makefileはtabで入力しないと実行エラーになる箇所があるので下記の様に設定すると良い。

    "editor.insertSpaces": true,
    "editor.tabSize": 4,
    "[makefile]": {
        "editor.insertSpaces": false,
        "editor.detectIndentation": false
    }

git設定

上記によりvs code でコードが修正された場合の書式は統一されるが、他エディタでの修正が行われた場合にWindows用の改行コードが混在してそのまま gitにpushされる可能性がある。これを防ぐためには、gitに..gitattributesファイルを用意し改行コードを強制的に変換する設定をしておくとより安全である。

*.sh        text eol=lf
makefile        text eol=lf
*.c        text eol=lf
*.cpp        text eol=lf
*.h        text eol=lf

Visual Studio Code C言語開発環境の設定 (Linux/gcc)

この記事の目的

Visual studio codeを用いてLinux上でgccを用いたC言語開発をする時の設定方法について記述する。

1. 必要なツールのインストール

下記コマンドでgcc(build-essentialはコンパイラ・ライブラリ・makeツール)、gdb(デバッグ用ツール)をインストールする

sudo apt install build-essential
sudo apt install gdb

Visual studio codeには下記拡張機能をインストールする。

2. make環境の構築(makffile)

VS codeにはC言語プロジェクト用にビルド設定する機能があるが、本機能で環境構築するとプロジェクトのビルドがターミナルから実行できない。 よって、GNU makefileでビルド環境を構築し、VS codeでは拡張機能makefiletoolでそれを読み込んで実行できるようにする。

makefileの設定は下記サイト等を参考に行う。

urin.github.io

www.ecoop.net

本記事では例として、下記の2つのcファイルと1つのヘッダファイルについてmakefileの設定を記述する。

main.c

#include <stdlib.h>
#include <stdio.h>
#include "func.h"

int main(void) 
{
    int indx =0;
    for (indx=0; indx<5000; indx++) {
        fprintf(stderr,"count: %d\n",func(indx));
    }
    return 0;
}

func.c

#include <stdlib.h>
#include <stdio.h>

int func(int cnt) 
{
    return cnt*2;
}

include/func.h

#ifndef FUNC_H
#define FUNC_H

int func(int cnt);

#endif  //FUNC_H

makefile

#生成する実行ファイル名
TARGET = testPrj
#.oファイル生成用の中間フォルダ
OBJSDIR = ./Objs
#ヘッダインクルードフォルダ
MYINCDIR = ./include

#コンパイル対象とするCファイル
OBJS =   main.o \
       func.o\

#コンパイル用コマンド (c++ならばg++に変更)
CC = gcc
#Wall:警告をすべて出力、-g:デバッグ情報出力、GNU_SOURCE:非標準拡張機能の有効化
CFLAGS = -Wall -g -std=c99 -D_GNU_SOURCE
#lm:算術計算ライブラリ有効化
LDFLAGS = -lm
INCDIR = -I$(MYINCDIR)

OBJS_ALL = $(addprefix $(OBJSDIR)/, $(OBJS))

all:
  mkdir -p $(OBJSDIR)
  make $(TARGET)

$(OBJS): %.o: %.c
  $(CC) $(CFLAGS) -c $< $(INCDIR) -o $@
  mv $@ $(OBJSDIR)/$@

$(TARGET): $(OBJS)
  $(CC) -o $@ $(OBJS_ALL) $(LDFLAGS)

clean:
  rm -f *.o
  rm -f $(OBJSDIR)/*.o
  rm $(TARGET)

ターミナルで下記コマンドを実行すると、正しくビルド・実行できるかを確認できる。

make
sudo ./testPrj

3. VS codeの makefiletools設定

上記を設定後、Visual studio codeからbuildができるようにmakefileとリンク設定する。 makefileの設定はVS codeの『ファイル』⇛『ユーザー設定』⇛『設定』で検索バーに"makefile"と入力すると出てくる画面で"makefile:Configurations"を選択する。ここで、設定に保存先として"ユーザー"ではなく"ワークスペース"に切り替えておいたほうが良い。 上記手順後に表示されるsettings.jsonmakefile.configurationsで下記のように記述する。

    "makefile.configurations": [
        {
            "name": "testprj",
            "makeDirectory": "./prj"
        }
    ]

上記でnameはmake設定の識別名、makeDirecgtoryはmakefile相対パス(VS codeのルート設定フォルダから)を記入する。 上記設定後、拡張機能mekefile toolsのbuilt対象をtesprjに変更して実行ボタンを押すとVS codeからプロジェクトのビルドが可能になる。

f:id:sd08419ttic:20210919170238p:plain

4. インクルードパスの設定

VS codeではソースコードを分析してエラー・警告を表示する機能があるがインクルードパスが適切に設定されていないと正しい探索が行われない。 インクルードパスの設定をするためにコマンドパレットから『C/C++構成の編集(JSON)』を選択し、"includePath"にヘッダファイルがあるフォルダを追加する。

            "includePath": [
                "${workspaceFolder}/**",
                "${workspaceFolder}/prj/include"
            ],

4. デバッグ環境設定

コードの実行中の変数値の確認、ブレークポイントを用いたデバッグを実行するため、GDBの設定を行う。 VS code左側の拡張機能から『実行とデバッグ』を選択し、『launch.json』ファイルを作成しますボタンを押し、C++/GDB用のjsonを作成する。

作成された設定のプログラムのパスを変更する。

    "configurations": [
        {
            "name": "(gdb) 起動",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/prj/testPrj",
            以下略
         }
    ]

上記を設定後にgdbの起動メニューを実行すると、break pointを使ったデバッグ、変数値の確認がVS Code上からできるようになる。 f:id:sd08419ttic:20210919174010p:plain