開発版ドキュメント · 0.2.3 30c2f8ba · 入門例の検証対象 0.2.3 · 版情報 · 既知の制限

スカラーフィールドのスライス操作ガイド (4次元を維持する理由)#

注釈

このページを読むべき方: ScalarField を使用していて以下の疑問を感じた場合に参照してください。

  • field[0] としたのに 1次元配列にならず、4次元のままなのはなぜか?

  • インデクシング操作時に Shape Mismatch エラーが発生するのはなぜか?

  • squeeze() を使って良いタイミングと、使ってはいけないタイミングはいつか?

ScalarField がインデクシング操作時に4次元構造を常に維持する挙動について説明します。これは NumPy や GWpy の標準的な挙動とは異なり、多次元物理データの整合性を保つための「不変条件」として設計されています。

なぜ「4次元」を維持し続けるのか?#

ScalarField(axis 0, x, y, z) の 4 つの軸を持つ物理的な「場」を表します。axis 0 は時間軸(時間領域 FFT である fft_time() を適用した後は周波数軸)で、軸 1〜3 は空間軸 x, y, z です。各空間軸は fft_space() によって対応する k 空間 kx, ky, kz へ変換できます。したがって具体的な場は (t, x, y, z)(f, x, y, z)(f, kx, ky, kz) のように並びます。NumPy のようにスライス時に次元を削減(Rank Loss)しない理由は、主に以下の 4 つの柱 によります。

  1. ドメイン情報の保護:次元を削ると、その軸に紐付いたメタデータ(axis 0 の t0/f0、各空間軸の dx/dy/dz など)が失われ、元の物理空間へ戻せなくなります。

  2. FFT/変換の整合性: 常に 4D であることで、どの断面に対しても即座に fft(), ifft(), spatial_filter() などの多次元演算が可能です。

  3. ストリーム処理の安全性: 関数間で受け渡しをする際、次元数が変動しないためプログラムの堅牢性が向上します。

  4. ブロードキャストの一貫性: 常に 4D であるため、計算時の次元合わせ(reshape)の意図がコード上で明確になります。

NumPy vs GWexpy の挙動比較#

NumPy と GWexpy の 4 次元次元保持の比較

操作例

結果の次元 (NumPy)

結果の次元 (Field)

物理的意味

field[5]

3次元 (Rank Loss)

4次元 (1, X, Y, Z)

axis 0(時間)の特定インデックスでの断面(メタデータ維持)

field[:, 3, 3, 3]

1次元 (Rank Loss)

4次元 (T, 1, 1, 1)

空間点 (x, y, z) を固定した時系列(メタデータ維持)

field[10:20]

4次元 (維持)

4次元 (10, X, Y, Z)

axis 0(時間)方向の区間切り出し


注意

.squeeze() 使用時の重大な警告 squeeze() を呼び出して次元を削減すると、削減された軸に紐付くメタデータ(座標情報)は完全に失われます。 一度は削ったデータから field.fft() などを実行しても、正しい物理軸を再構成できなくなるため、squeeze() はプロットや CSV 保存などの「最終出力段階」でのみ使用することを強く推奨します。


実践的な操作例#

1. Slicing Behavior#

  • 目的: インデクシング後も軸メタデータが残ることを確認する

  • 入力: shape (100, 50, 10, 10)ScalarField

  • 出力: 長さ 1 の軸を保った snapshotplane

from gwexpy.fields import ScalarField
import numpy as np

# (t, x, y, z) = (100, 50, 10, 10)
field = ScalarField(np.zeros((100, 50, 10, 10)), ...)

# Extract a snapshot at a specific time
snapshot = field[50]
# Shape becomes (1, 50, 10, 10), preserving the time-axis metadata.

# Extract a spatial cross-section (x-y plane at a fixed z)
plane = field[:, :, :, 2]
# Shape becomes (100, 50, 10, 1), preserving the z-axis metadata.

2. When to Reduce Dimensions (squeeze)#

意図的に 1次元や 2次元として扱いたい場合(例:プロットや外部ライブラリへの入力)は、明示的に .squeeze() を呼び出します。

  • 目的: 最終出力段階でだけ次元を落とす

  • 入力: 空間点を切り出した ScalarField

  • 出力: 外部ライブラリに渡しやすい 1 次元配列

# Get time-series at a specific spatial point for plotting
point_ts = field[:, 2, 5, 5]      # (100, 1, 1, 1)
actual_ts = point_ts.squeeze(axis=(1, 2, 3))    # (100,) - compatible with TimeSeries

axis= を明示すると、「どの 1 要素軸を落とすのか」がコード上で分かりやすくなり、意図しない次元削減を避けやすくなります。

3. Broadcasting Considerations#

ScalarField は常に 4次元であるため、NumPy 配列を加減算する場合は形状を合わせる必要があります。

  • 目的: ブロードキャスト時の shape mismatch を避ける

  • 入力: ScalarField と 1 次元補正係数

  • 出力: 意図が明示された reshape(...) 付き演算

# ❌ Bad Example: Attempting to add a 1D array directly
field + np.array([1, 2, 3])  # Shape mismatch

# ✅ Good Example: Reshaping to the correct dimensions
calibration = np.array([1, 2, 3]).reshape(3, 1, 1, 1) # three coefficients along axis 0 (time/frequency)
field + calibration

ここで reshape(3, 1, 1, 1) としているのは、「3 つの値が axis 0(時間/周波数軸)に沿って並び、x・y・z の各軸には同じ値をブロードキャストする」ことを明示するためです。


よくある質問 (FAQ)#

Q: 常に 4次元だと、1次元の計算時に不便ではありませんか?#

A: ScalarField は空間・時間の広がりを持つデータを「場」として扱うためのクラスです。単一チャンネルの単純な時系列を扱う場合は、最初から TimeSeries クラスを使用することをお勧めします。

Q: ScalarField[0, 0, 0, 0] とスカラー抽出した場合は?#

A: インデックスがすべてスカラーの場合は、通常の Python スカラー値または NumPy スカラーが返されます。

次に読む#