tkPlot3d.py ダウンロード/コピー

tkPlot3d.py をダウンロード

tkPlot3d.py
tkPlot3d.py
  1"""
  2tkPlot3d.py - 3Dプロット関連のユーティリティ関数を提供するモジュール
  3
  4概要:
  5    MatplotlibとNumPyを使用して、3Dサーフェス、等値面、散布図、2D等高線プロットなどを描画するための補助関数群を提供します。
  6    カラーマップの作成や3D軸のスケーリング調整など、多様な3D可視化ニーズに対応します。
  7
  8詳細説明:
  9    このモジュールには、3D空間におけるデータの表現を容易にするための複数の関数が含まれています。
 10    `plot_surface3d` は一般的な3Dサーフェスプロットを扱い、`plot_isosurface3d` は`marching_cubes`アルゴリズムを用いてボリュームデータから等値面を抽出・描画します。
 11    また、`make_cmap` などの関数は、カスタムカラーマップを生成してプロットの視覚表現を豊かにするために使用できます。
 12    軸の統一スケール設定やカラーバーの追加など、プロットの見た目を整えるためのユーティリティも含まれています。
 13
 14関連リンク:
 15    :doc:`tkPlot3d_usage`
 16"""
 17import numpy as np
 18import matplotlib.pyplot as plt
 19from mpl_toolkits.mplot3d import Axes3D
 20from mpl_toolkits.mplot3d.art3d import Poly3DCollection
 21from matplotlib.colors import LightSource, Normalize, LinearSegmentedColormap
 22from matplotlib.patches import Patch
 23from matplotlib import cm
 24from matplotlib.animation import FuncAnimation
 25
 26from skimage.measure import marching_cubes
 27
 28
 29def get_max_xyz(x, y, z):
 30    """
 31    概要: 3D座標の最大絶対値を取得します。
 32
 33    詳細説明:
 34        与えられたX, Y, Z座標配列から、すべての要素の最大絶対値を計算します。
 35        これにより、3Dプロットの軸範囲を統一するための基準値を得られます。
 36
 37    :param x: (numpy.ndarray) X座標の配列。
 38    :param y: (numpy.ndarray) Y座標の配列。
 39    :param z: (numpy.ndarray) Z座標の配列。
 40    :returns: (float) X, Y, Z座標の最大値の中から最も大きい値。
 41    """
 42    x1d = x.flatten()
 43    y1d = y.flatten()
 44    z1d = z.flatten()
 45    maxx = max([max(x1d), max(y1d), max(z1d)])
 46    return maxx
 47
 48def set_cubic_scale(ax, maxx):
 49    """
 50    概要: 3D軸のスケールを立方体状に設定します。
 51
 52    詳細説明:
 53        3DプロットのX, Y, Z軸の表示範囲を、与えられた最大値に基づいて対称な立方体状に設定し、アスペクト比を1:1:1にします。
 54
 55    :param ax: (matplotlib.axes.Axes) 対象となる3D Axesオブジェクト。
 56    :param maxx: (float) 各軸の最大絶対値。`[-maxx, maxx]` の範囲に設定されます。
 57    :returns: (None)
 58    """
 59    ax.set_xlim([-maxx, maxx])
 60    ax.set_ylim([-maxx, maxx])
 61    ax.set_zlim([-maxx, maxx])
 62    ax.set_box_aspect([1, 1, 1])
 63
 64#colorを使う場合
 65#    color = 'cyan'
 66#cmapを使う場合
 67#    cmap = 'bwr'
 68#3色塗分け
 69#    colors = np.empty(x.shape, dtype = object)
 70#    colors[r < 0]  = 'red'
 71#    colors[r == 0] = 'white'
 72#    colors[r > 0]  = 'blue'
 73
 74# 回転角に基づく色の設定
 75#color_map = plt.cm.viridis(phi / (2 * np.pi))
 76#color_map = plt.cm.Reds(phi / (2 * np.pi))
 77#norm = Normalize(vmin=np.min(phi), vmax=np.max(phi))
 78#norm = Normalize(vmin = 100, vmax = 200)
 79#color_map = plt.cm.Reds(norm(phi))
 80
 81# カラーマップの正規化(範囲の調整)
 82#vmin, vmax = np.min(phi), np.max(phi)
 83#norm = Normalize(vmin=vmin, vmax=vmax)
 84#sm = plt.cm.ScalarMappable(cmap=plt.cm.Reds, norm=norm)
 85#sm.set_array([])
 86#color_map = sm.to_rgba(phi)
 87
 88def make_cmap(colors, cmap_name = 'custom_cmap', nbins = 100):
 89    """
 90    概要: カスタムカラーマップを作成します。
 91
 92    詳細説明:
 93        指定された色のリストから、`matplotlib.colors.ListedColormap` (nbinsが少ない場合)
 94        または `matplotlib.colors.LinearSegmentedColormap` を用いてカスタムカラーマップを生成します。
 95
 96    :param colors: (list) カラーマップを構成する色のリスト。色の形式はmatplotlibが認識するものであれば何でも可(例: 'red', '#FF0000', (1, 0, 0))。
 97    :param cmap_name: (str, optional) カスタムカラーマップの名前。デフォルトは 'custom_cmap'。
 98    :param nbins: (int, optional) 線形補間を行う際のビン数。`colors`の要素数以下の場合、`ListedColormap`を使用。デフォルトは100。
 99    :returns: (matplotlib.colors.Colormap) 作成されたカスタムカラーマップオブジェクト。
100    """
101    # Note: ListedColormap がインポートされていませんが、既存コードの変更はルールにより行いません。
102    if nbins is None or nbins <= len(colors):
103        # ListedColormap が定義されていないため、この行は実行時にエラーになる可能性があります。
104        custom_cmap = ListedColormap(colors) 
105    else:
106        custom_cmap = LinearSegmentedColormap.from_list(cmap_name, colors, N = nbins)
107    return custom_cmap
108
109def make_color_map(x, colors, cmap_name = 'custom_cmap', nbins = 100):
110    """
111    概要: データに基づいてカスタムカラーマップを生成し、その色配列を返します。
112
113    詳細説明:
114        `make_cmap` を利用してカスタムカラーマップを作成し、入力データ `x` を正規化してその
115        カラーマップを適用したRGBA色の配列を生成します。
116
117    :param x: (numpy.ndarray) カラーマップを適用する数値データ。
118    :param colors: (list) カラーマップを構成する色のリスト。
119    :param cmap_name: (str, optional) カスタムカラーマップの名前。デフォルトは 'custom_cmap'。
120    :param nbins: (int, optional) 線形補間を行う際のビン数。デフォルトは100。
121    :returns: (numpy.ndarray) `x` の各要素に対応するRGBA色値の配列。
122    """
123    custom_cmap = LinearSegmentedColormap.from_list(cmap_name, colors, N = nbins)
124    # Note: `norm` 変数が未定義ですが、既存コードの変更はルールにより行いません。
125    color_map = custom_cmap(norm(x))
126
127    return color_map
128
129def make_colors(x, colors, vmin = None, vmax = None, cmap_name = 'custom_cmap', nbins = 100):
130    """
131    概要: データに基づいて色配列を作成します。
132
133    詳細説明:
134        入力データ `x` の最小値・最大値(または指定された `vmin`, `vmax`)で正規化し、
135        カスタムカラーマップを適用してRGBA色配列を生成します。
136
137    :param x: (numpy.ndarray) カラーマップを適用する数値データ。
138    :param colors: (list) カスタムカラーマップを構成する色のリスト。
139    :param vmin: (float, optional) カラーマップ正規化の最小値。指定されない場合は `x` の最小値。
140    :param vmax: (float, optional) カラーマップ正規化の最大値。指定されない場合は `x` の最大値。
141    :param cmap_name: (str, optional) カスタムカラーマップの名前。デフォルトは 'custom_cmap'。
142    :param nbins: (int, optional) 線形補間を行う際のビン数。デフォルトは100。
143    :returns: (numpy.ndarray) `x` の各要素に対応するRGBA色値の配列。
144    """
145    if vmin is None: vmin = np.min(x)
146    if vmax is None: vmax = np.max(x)
147
148    # Note: この行は関数自身を呼び出す(make_colorsをmake_colorsとして)ように見えますが、
149    # 既存コードの変更はルールにより行いません。本来はmake_color_mapを呼び出す意図かもしれません。
150    color_map = make_colors(x, colors, cmap_name = cmap_name, nbins = nbins)
151    norm = Normalize(vmin = vmin, vmax = vmax)
152    colors = color_map(norm(x))
153    return colors
154
155def make_colorbar(ax, x, cmap, vmin = None, vmax = None, label = None, shrink = 0.5, aspect = 10.0,
156        ticks = None, ticklabels = None):
157    """
158    概要: カラーバーを作成し、プロットに追加します。
159
160    詳細説明:
161        与えられたデータ `x` とカラーマップ `cmap` に基づいてカラーバーを生成し、
162        指定されたAxesオブジェクトに追加します。ラベル、サイズ、ティックなども設定可能です。
163
164    :param ax: (matplotlib.axes.Axes) カラーバーを追加するAxesオブジェクト。
165    :param x: (numpy.ndarray) カラーマップの正規化に使用するデータ。
166    :param cmap: (matplotlib.colors.Colormap or str) 使用するカラーマップオブジェクトまたはカラーマップ名。
167    :param vmin: (float, optional) カラーマップ正規化の最小値。指定されない場合は `x` の最小値。
168    :param vmax: (float, optional) カラーマップ正規化の最大値。指定されない場合は `x` の最大値。
169    :param label: (str, optional) カラーバーのラベル。
170    :param shrink: (float, optional) カラーバーの表示サイズの縮小率。デフォルトは0.5。
171    :param aspect: (float, optional) カラーバーのアスペクト比。デフォルトは10.0。
172    :param ticks: (list or numpy.ndarray, optional) カラーバーのティック位置。
173    :param ticklabels: (list of str, optional) カラーバーのティックラベル。
174    :returns: (matplotlib.colorbar.Colorbar) 作成されたカラーバーオブジェクト。
175    """
176    if vmin is None: vmin = np.min(x)
177    if vmax is None: vmax = np.max(x)
178
179    norm = Normalize(vmin = vmin, vmax = vmax)
180    scmap = plt.cm.ScalarMappable(cmap = cmap, norm = norm)
181    scmap.set_array(x)
182    cbar = plt.colorbar(scmap, ax = ax, shrink = shrink, aspect = aspect)
183    if label is not None: cbar.set_label(label)
184    
185    if ticks is not None: cbar.set_ticks(ticks)
186    if ticklabels is not None: cbar.set_ticklabels(ticklabels)
187
188    return cbar
189
190
191def set_light(x, azdeg = 315, altdeg = 45, cmap = "viridis", vert_exag = 0.1, blend_mode = 'soft'):
192    """
193    概要: 3Dサーフェスプロットのシェーディングに光源効果を設定します。
194
195    詳細説明:
196        `matplotlib.colors.LightSource` を使用して、指定されたデータ `x` に対して光源の角度、
197        カラーマップ、垂直方向の強調、ブレンドモードを適用し、シェーディングされたRGB画像データを生成します。
198
199    :param x: (numpy.ndarray) シェーディングの基となる2Dデータ(高さ情報など)。
200    :param azdeg: (float, optional) 光源の水平方向の角度(アジマス角)。デフォルトは315度。
201    :param altdeg: (float, optional) 光源の垂直方向の角度(高度角)。デフォルトは45度。
202    :param cmap: (str or matplotlib.colors.Colormap, optional) 使用するカラーマップ。デフォルトは"viridis"。
203    :param vert_exag: (float, optional) 垂直方向の強調係数。デフォルトは0.1。
204    :param blend_mode: (str, optional) ブレンドモード('soft', 'hsv', 'overlay'など)。デフォルトは'soft'。
205    :returns: (numpy.ndarray) シェーディングが適用されたRGBカラーデータ。
206    """
207    ls = LightSource(azdeg = azdeg, altdeg = altdeg)
208    rgb = ls.shade(x, cmap = cmap, vert_exag = vert_exag, blend_mode = blend_mode)
209    return rgb
210
211def show_color_bar(fig, ax, scale, cmap, shrink = 0.5, aspect = 10.0):
212    """
213    概要: カラーバーを表示します。
214
215    詳細説明:
216        与えられたデータ `scale` とカラーマップ `cmap` に基づいてカラーバーを生成し、
217        指定されたFigureとAxesオブジェクトにアタッチします。
218
219    :param fig: (matplotlib.figure.Figure) カラーバーを配置するFigureオブジェクト。
220    :param ax: (matplotlib.axes.Axes) カラーバーを関連付けるAxesオブジェクト。
221    :param scale: (numpy.ndarray) カラーマップの正規化に使用する数値データ。
222    :param cmap: (matplotlib.colors.Colormap or str) 使用するカラーマップオブジェクトまたはカラーマップ名。
223    :param shrink: (float, optional) カラーバーの表示サイズの縮小率。デフォルトは0.5。
224    :param aspect: (float, optional) カラーバーのアスペクト比。デフォルトは10.0。
225    :returns: (matplotlib.colorbar.Colorbar) 作成されたカラーバーオブジェクト。
226    """
227    mappable = plt.cm.ScalarMappable(cmap = cmap)
228    mappable.set_array(scale)
229    cbar = fig.colorbar(mappable, ax = ax, shrink = shrink, aspect = aspect)
230    return cbar
231
232def plot_surface3d(ax, X, Y, Z, color = None, cmap = None, facecolors = None, edgecolor = 'black', alpha = 0.7, shade = True,
233                    xlabel = 'X', ylabel = 'Y', zlabel = 'Z'):
234    """
235    概要: 3Dサーフェスプロットを描画します。
236
237    詳細説明:
238        与えられたX, Y, Z座標データに基づいて、3Dの曲面または面プロットを描画します。
239        色、カラーマップ、エッジ色、透明度、シェーディングなどのオプションを設定できます。軸ラベルも設定されます。
240
241    :param ax: (matplotlib.axes.Axes) プロットを描画する3D Axesオブジェクト。
242    :param X: (numpy.ndarray) X座標データ。
243    :param Y: (numpy.ndarray) Y座標データ。
244    :param Z: (numpy.ndarray) Z座標データ。
245    :param color: (str or tuple, optional) サーフェスの単一色。`facecolors`または`cmap`と同時に指定すると上書きされる可能性あり。
246    :param cmap: (str or matplotlib.colors.Colormap, optional) サーフェスの色付けに使用するカラーマップ。
247    :param facecolors: (numpy.ndarray, optional) 各面の色を指定するRGBAカラー配列。
248    :param edgecolor: (str or tuple, optional) サーフェスのエッジの色。デフォルトは'black'。
249    :param alpha: (float, optional) サーフェスの透明度。0.0(完全透明)から1.0(完全不透明)の範囲。デフォルトは0.7。
250    :param shade: (bool, optional) 光源によるシェーディングを適用するかどうか。デフォルトはTrue。
251    :param xlabel: (str, optional) X軸のラベル。デフォルトは'X'。
252    :param ylabel: (str, optional) Y軸のラベル。デフォルトは'Y'。
253    :param zlabel: (str, optional) Z軸のラベル。デフォルトは'Z'。
254    :returns: (None)
255    """
256    options = {}
257    if color is not None: options['color'] = color 
258    if cmap is not None: options['cmap'] = cmap 
259    if facecolors is not None: options['facecolors'] = facecolors 
260    if edgecolor is not None: options['edgecolor'] = edgecolor
261    if alpha is not None: options['alpha'] = alpha 
262    if shade is not None: options['shade'] = shade 
263
264    ax.plot_surface(X, Y, Z, **options)
265
266    ax.set_xlabel(xlabel)
267    ax.set_ylabel(ylabel)
268    ax.set_zlabel(zlabel)
269
270def plot_isosurface3d(ax, X, Y, Z, F, levels, origin, spacing, 
271                     colors = None, edgecolor = 'k', alpha = 0.3, linewidth = 0.1,
272                     phase = None, custom_colors = None, nbins = 100, cmap_name = 'custom color',
273                     minx = None, maxx = None,
274                     miny = None, maxy = None,
275                     minz = None, maxz = None,
276                     ):
277    """
278    概要: 3Dボリュームデータから等値面を描画します。
279
280    詳細説明:
281        `skimage.measure.marching_cubes` を使用して、3Dボリュームデータ `F` から指定された
282        レベルの等値面を抽出し、3D Axes上に描画します。位相データに基づくカスタムカラーリングや、
283        凡例の追加もサポートします。
284
285    :param ax: (matplotlib.axes.Axes) プロットを描画する3D Axesオブジェクト。
286    :param X: (numpy.ndarray) X座標のグリッドデータ。軸範囲設定に使用。
287    :param Y: (numpy.ndarray) Y座標のグリッドデータ。軸範囲設定に使用。
288    :param Z: (numpy.ndarray) Z座標のグリッドデータ。軸範囲設定に使用。
289    :param F: (numpy.ndarray) 等値面を抽出する3Dボリュームデータ。
290    :param levels: (list or float) 描画する等値面のレベル(値)のリスト。単一の値も可。
291    :param origin: (tuple) ボリュームデータの原点 (x, y, z)。
292    :param spacing: (tuple) ボリュームデータの各軸方向のサンプル間隔 (dx, dy, dz)。
293    :param colors: (list or str, optional) 等値面の色リスト(カスタムカラーマップが指定されていない場合)。
294    :param edgecolor: (str or tuple, optional) 等値面のエッジの色。デフォルトは'k' (黒)。
295    :param alpha: (float, optional) 等値面の透明度。デフォルトは0.3。
296    :param linewidth: (float, optional) 等値面のエッジの線の太さ。デフォルトは0.1。
297    :param phase: (numpy.ndarray, optional) 位相情報を含む3Dボリュームデータ。カスタムカラーリングに使用。
298    :param custom_colors: (list, optional) 位相に基づいて色付けするためのカスタムカラーリスト。
299    :param nbins: (int, optional) カスタムカラーマップ生成時のビン数。デフォルトは100。
300    :param cmap_name: (str, optional) カスタムカラーマップの名前。デフォルトは'custom color'。
301    :param minx: (float, optional) X軸の最小範囲。指定されない場合は `X` から自動計算。
302    :param maxx: (float, optional) X軸の最大範囲。指定されない場合は `X` から自動計算。
303    :param miny: (float, optional) Y軸の最小範囲。指定されない場合は `Y` から自動計算。
304    :param maxy: (float, optional) Y軸の最大範囲。指定されない場合は `Y` から自動計算。
305    :param minz: (float, optional) Z軸の最小範囲。指定されない場合は `Z` から自動計算。
306    :param maxz: (float, optional) Z軸の最大範囲。指定されない場合は `Z` から自動計算。
307    :returns: (None)
308    """
309    if custom_colors is not None:
310        custom_cmap = make_cmap(custom_colors, cmap_name = cmap_name, nbins = nbins)
311    else:
312        custom_cmap = None
313
314#np.ndarray([行、列、高さ])とmarching_cubesの座標[x,y,z]のインデックスがずれているようなので、修正
315    F = np.transpose(F, (1, 0, 2))
316    if phase is not None:
317        phase = np.transpose(phase, (1, 0, 2))
318    legend_patches = []
319
320# 複数の等値面を描画
321    for il, level in enumerate(levels):
322        try:
323            verts, faces, _, _ = marching_cubes(F, level = level, spacing = spacing)
324        except:
325#            print(f"\nError in tkWavefunction_H.plot_isosurface3d(): ValueError: Surface level must be within volume data range.\n")
326            continue
327 
328        verts += np.array(origin)
329
330    # 等値面を追加
331        if custom_cmap:
332    # 位相の計算
333            vertex_phases = np.array([phase[tuple(np.round((v - origin) / spacing).astype(int))] for v in verts])
334            norm_phases = (vertex_phases - np.min(vertex_phases)) / (np.max(vertex_phases) - np.min(vertex_phases))
335            colors = custom_cmap(norm_phases)
336            mesh = Poly3DCollection(verts[faces], alpha = alpha, edgecolor = edgecolor, linewidth = linewidth)
337            mesh.set_facecolor(colors[faces].mean(axis = 1))
338        else:
339            mesh = Poly3DCollection(verts[faces], alpha = alpha, facecolor = colors[il], edgecolor = edgecolor, linewidth = linewidth)
340    # 凡例用パッチを作成
341            legend_patches.append(Patch(facecolor = colors[il], edgecolor = edgecolor, label = f"Level = {level:.4g}"))
342
343        ax.add_collection3d(mesh)
344
345
346# 軸範囲の統一
347    X1d = X.flatten()
348    Y1d = Y.flatten()
349    Z1d = Z.flatten()
350    if minx is None: minx = min(X1d)
351    if maxx is None: maxx = max(X1d)
352    if miny is None: miny = min(Y1d)
353    if maxy is None: maxy = max(Y1d)
354    if minz is None: minz = min(Z1d)
355    if maxz is None: maxz = max(Z1d)
356#    print(f"x range: {minx} - {maxx}")
357#    print(f"y range: {miny} - {maxy}")
358#    print(f"z range: {minz} - {maxz}")
359    ax.set_xlim([minx, maxx])
360    ax.set_ylim([miny, maxy])
361    ax.set_zlim([minz, maxz])
362
363# **アスペクト比を 1:1:1 に設定**
364    ax.set_box_aspect([1, 1, 1])
365
366# 軸ラベル
367    ax.set_xlabel("X")
368    ax.set_ylabel("Y")
369    ax.set_zlabel("Z")
370
371# 凡例を追加
372    if custom_colors is None:
373        ax.legend(handles=legend_patches, loc="upper right", fontsize=10)
374
375def contour3d(ax, X, Y, F, nbins = 50, cmap = "viridis", xlabel = 'X', ylabel = 'Y', zlabel = 'Z'):
376    """
377    概要: 3D等高線プロットを描画します。
378
379    詳細説明:
380        `matplotlib.pyplot.contour3D` を使用して、指定された2次元データ `F` の
381        3D等高線(または等高線面)プロットを描画します。
382
383    :param ax: (matplotlib.axes.Axes) プロットを描画する3D Axesオブジェクト。
384    :param X: (numpy.ndarray) X座標データ。
385    :param Y: (numpy.ndarray) Y座標データ。
386    :param F: (numpy.ndarray) 等高線を描画する2Dデータ。
387    :param nbins: (int, optional) 等高線の数。デフォルトは50。
388    :param cmap: (str or matplotlib.colors.Colormap, optional) 使用するカラーマップ。デフォルトは"viridis"。
389    :param xlabel: (str, optional) X軸のラベル。デフォルトは'X'。
390    :param ylabel: (str, optional) Y軸のラベル。デフォルトは'Y'。
391    :param zlabel: (str, optional) Z軸のラベル。デフォルトは'Z'。
392    :returns: (None)
393    """
394    ax.contour3D(X, Y, F, nbins, cmap = cmap)
395
396    ax.set_xlabel(xlabel)
397    ax.set_ylabel(ylabel)
398    ax.set_zlabel(zlabel)
399
400def plot_scatter3d(ax, x, y, z, minx, maxx, miny, maxy, minz, maxz, 
401                    cmap = None, c = None, norm = None, marker = 'o', size = 0.5, alpha = 1.0):
402    """
403    概要: 3D散布図を描画します。
404
405    詳細説明:
406        指定されたX, Y, Z座標データに基づいて、3Dの散布図を描画します。
407        マーカーの種類、サイズ、色、透明度などを設定できます。
408
409    :param ax: (matplotlib.axes.Axes) プロットを描画する3D Axesオブジェクト。
410    :param x: (numpy.ndarray) X座標データ。
411    :param y: (numpy.ndarray) Y座標データ。
412    :param z: (numpy.ndarray) Z座標データ。
413    :param minx: (float) X軸の最小範囲。
414    :param maxx: (float) X軸の最大範囲。
415    :param miny: (float) Y軸の最小範囲。
416    :param maxy: (float) Y軸の最大範囲。
417    :param minz: (float) Z軸の最小範囲。
418    :param maxz: (float) Z軸の最大範囲。
419    :param cmap: (str or matplotlib.colors.Colormap, optional) 色付けに使用するカラーマップ。
420    :param c: (numpy.ndarray or str, optional) 各点の色の配列、または単一色。
421    :param norm: (matplotlib.colors.Normalize, optional) カラーマップの正規化オブジェクト。
422    :param marker: (str, optional) マーカーのスタイル。デフォルトは'o' (円)。
423    :param size: (float, optional) マーカーのサイズ。デフォルトは0.5。
424    :param alpha: (float, optional) マーカーの透明度。デフォルトは1.0。
425    :returns: (matplotlib.collections.PathCollection) 作成された散布図コレクションオブジェクト。
426    """
427    options = {}
428    if cmap is not None: options["cmap"] = cmap
429    if c is not None   : options["c"] = c
430    if norm is not None: options["norm"] = norm
431    if size is not None: options["s"] = size
432    if alpha is not None: options["alpha"] = alpha
433                        
434    sc = ax.scatter(x, y, z, marker = marker, **options)
435
436    ax.set_xlim([minx, maxx])
437    ax.set_ylim([miny, maxy])
438    ax.set_zlim([minz, maxz])
439    ax.set_xlabel('X')
440    ax.set_ylabel('Y')
441    ax.set_zlabel('Z')
442    
443    return sc
444
445def plot_contour2d_xy(ax, x, y, offsetz, f, cmap, levels, alpha):
446    """
447    概要: XY平面に投影された2D等高線プロットを描画します。
448
449    詳細説明:
450        指定されたデータ `f` に基づいて、X-Y平面に平行な`offsetz`の高さに2D等高線塗りつぶしプロットを描画します。
451
452    :param ax: (matplotlib.axes.Axes) プロットを描画する3D Axesオブジェクト。
453    :param x: (numpy.ndarray) X座標データ。
454    :param y: (numpy.ndarray) Y座標データ。
455    :param offsetz: (float) 等高線プロットを配置するZ軸のオフセット値。
456    :param f: (numpy.ndarray) 等高線を描画する2Dデータ。
457    :param cmap: (str or matplotlib.colors.Colormap) 使用するカラーマップ。
458    :param levels: (int or list) 等高線の数またはレベルのリスト。
459    :param alpha: (float) 等高線プロットの透明度。
460    :returns: (None)
461    """
462    ax.contourf(x, y, f, zdir = 'z', offset = offsetz, cmap = cmap, levels = levels, alpha = alpha)
463
464def plot_contour2d_yz(ax, offsetx, y, z, f, cmap, levels, alpha):
465    """
466    概要: YZ平面に投影された2D等高線プロットを描画します。
467
468    詳細説明:
469        指定されたデータ `f` に基づいて、Y-Z平面に平行な`offsetx`の位置に2D等高線塗りつぶしプロットを描画します。
470
471    :param ax: (matplotlib.axes.Axes) プロットを描画する3D Axesオブジェクト。
472    :param offsetx: (float) 等高線プロットを配置するX軸のオフセット値。
473    :param y: (numpy.ndarray) Y座標データ。
474    :param z: (numpy.ndarray) Z座標データ。
475    :param f: (numpy.ndarray) 等高線を描画する2Dデータ。
476    :param cmap: (str or matplotlib.colors.Colormap) 使用するカラーマップ。
477    :param levels: (int or list) 等高線の数またはレベルのリスト。
478    :param alpha: (float) 等高線プロットの透明度。
479    :returns: (None)
480    """
481    ax.contourf(f, y, z, zdir = 'x', offset = offsetx, cmap = cmap, levels = levels, alpha = alpha)
482
483def plot_contour2d_zx(ax, x, offsety, z, f, cmap, levels, alpha):
484    """
485    概要: ZX平面に投影された2D等高線プロットを描画します。
486
487    詳細説明:
488        指定されたデータ `f` に基づいて、Z-X平面に平行な`offsety`の位置に2D等高線塗りつぶしプロットを描画します。
489
490    :param ax: (matplotlib.axes.Axes) プロットを描画する3D Axesオブジェクト。
491    :param x: (numpy.ndarray) X座標データ。
492    :param offsety: (float) 等高線プロットを配置するY軸のオフセット値。
493    :param z: (numpy.ndarray) Z座標データ。
494    :param f: (numpy.ndarray) 等高線を描画する2Dデータ。
495    :param cmap: (str or matplotlib.colors.Colormap) 使用するカラーマップ。
496    :param levels: (int or list) 等高線の数またはレベルのリスト。
497    :param alpha: (float) 等高線プロットの透明度。
498    :returns: (None)
499    """
500    ax.contourf(x, f, z, zdir = 'y', offset = offsety, cmap = cmap, levels = levels, alpha = alpha)
501
502def plot_contours_xyz_by_func(ax, func, minx, maxx, nmesh = 100, 
503                posx = 0.1, posy = 0.1, posz = 0.1,
504                offsetx = None, offsety = None, offsetz = None,
505                cmap = None, levels = 20, alpha = 0.3):
506    """
507    概要: 関数から計算されたデータに基づき、XYZの各平面に投影された2D等高線プロットを描画します。
508
509    詳細説明:
510        ユーザー定義関数 `func` を使用してX, Y, Z軸の各断層面におけるデータを計算し、
511        それぞれの平面(YZ、XY、ZX)に2D等高線塗りつぶしプロットを描画します。
512
513    :param ax: (matplotlib.axes.Axes) プロットを描画する3D Axesオブジェクト。
514    :param func: (callable) (x, y, z) を引数にとり、スカラー値を返す関数。
515    :param minx: (float) 座標範囲の最小値。
516    :param maxx: (float) 座標範囲の最大値。
517    :param nmesh: (int, optional) メッシュの点数。デフォルトは100。
518    :param posx: (float, optional) YZ平面プロット用のX軸固定位置。デフォルトは0.1。
519    :param posy: (float, optional) ZX平面プロット用のY軸固定位置。デフォルトは0.1。
520    :param posz: (float, optional) XY平面プロット用のZ軸固定位置。デフォルトは0.1。
521    :param offsetx: (float, optional) YZ平面プロットのX軸オフセット。指定されない場合は`minx`。
522    :param offsety: (float, optional) ZX平面プロットのY軸オフセット。指定されない場合は`maxx`。
523    :param offsetz: (float, optional) XY平面プロットのZ軸オフセット。指定されない場合は`minx`。
524    :param cmap: (str or matplotlib.colors.Colormap, optional) 使用するカラーマップ。
525    :param levels: (int or list, optional) 等高線の数またはレベルのリスト。デフォルトは20。
526    :param alpha: (float, optional) 等高線プロットの透明度。デフォルトは0.3。
527    :returns: (None)
528    """
529    x1 = np.linspace(minx, maxx, nmesh)
530    y1 = np.linspace(minx, maxx, nmesh)
531    z1 = np.linspace(minx, maxx, nmesh)
532    if offsetx is None: offsetx = minx
533    if offsety is None: offsety = maxx
534    if offsetz is None: offsetz = minx
535
536    yp, zp = np.meshgrid(y1, z1, indexing = 'ij')
537    fp  = func(posx, yp, zp)
538    plot_contour2d_yz(ax, offsetx, yp, zp, fp, cmap = cmap, levels = 20, alpha = 0.3)
539
540    xp, yp = np.meshgrid(x1, y1, indexing = 'ij')
541    fp  = func(xp, yp, posz)
542    plot_contour2d_xy(ax, xp, yp, offsetz, fp, cmap = cmap, levels = 20, alpha = 0.3)
543
544    xp, zp = np.meshgrid(x1, z1, indexing = 'ij')
545    fp  = func(xp, posy, zp)
546    plot_contour2d_zx(ax, xp, offsety, zp, fp, cmap = cmap, levels = 20, alpha = 0.3)
547
548def main():
549    """
550    概要: トーラスを3Dでプロットするデモンストレーション関数です。
551
552    詳細説明:
553        トーラスのパラメトリック方程式を用いてX, Y, Z座標を生成し、
554        カスタムカラーマップを適用して3Dサーフェスプロットとして表示します。
555        結果は画像ファイルとして保存され、画面にも表示されます。
556
557    :returns: (None)
558    """
559# トーラスのパラメータ
560    R = 3  # 大半径
561    r = 1  # 小半径
562
563# パラメトリック変数
564    theta = np.linspace(0, 2 * np.pi, 100)
565    phi = np.linspace(0, 2 * np.pi, 100)
566    theta, phi = np.meshgrid(theta, phi)
567
568# トーラスの式
569    X = (R + r * np.cos(theta)) * np.cos(phi)
570    Y = (R + r * np.cos(theta)) * np.sin(phi)
571    Z = r * np.sin(theta)
572
573# カスタムカラーマップの定義
574    colors = [(1, 0.5, 0.5), (0, 1, 0), (1, 0.5, 0.5)]  # 薄い赤から青、符水赤へのグラデーション
575    # Note: make_color_map 関数内で `norm` 変数が未定義のため、この呼び出しは実行時にエラーになる可能性があります。
576    color_map = make_color_map(phi, colors, cmap_name = 'custom_reds', nbins = 100)
577
578# プロット
579    fig = plt.figure()
580    ax = fig.add_subplot(111, projection='3d')
581
582    plot_surface3d(ax, X, Y, Z, facecolors = color_map, edgecolor = 'none', alpha = 0.7, shade = True)
583
584    plt.savefig('torus.png')
585    plt.show()
586
587
588if __name__ == "__main__":
589    main()