nano_exit

基礎的なことこそ、簡単な例が必要だと思うのです。

化学シフト等、メッシュを変えずにグラフをシフト

グラフをただシフトさせるだけだったら、x軸のデータにシフト量を足し引きすればすぐに出来る。
問題は、例えばシフトさせる前と後で差を取りたい場合に、x軸が揃っていないと差が取れない点である。
つまり、横軸のメッシュは固定したまま、グラフだけ並行移動して欲しいのである。

シフトさせるさせないに関わらず、関数系は変えずにx軸だけ変更したい場合には、関数補間が必要になる。
グラフの形を別の関数でなるべく同じになる様に近似することで、データで与えられていない横軸の点でも値を求められるのである。
自分は大抵の場合には3次のスプライン補間(cubic spline)で大丈夫だと(勝手に)思っている。

これをシフトに応用するのだが、一つ問題がある。
補間には有限区間のデータが必要だが、その区間の外側に関しては基本的には補間は扱えない(補間法にも依るのかも知れないが)。それこそ一部を知って全部を知る逆問題みたいな話になってしまうし、そんなものは多くの境界条件を課さない限り(誤差の範囲でも)一意に決まらない。グラフの関数が完全にわかっているなら、全てのx点に対してy点の値が求まっているのと同義なので、そもそもその場合には補間は必要ない。
そして、シフトさせることによってグラフが補間の範囲からはみ出てしまうのである。
以下、手続きを順を追って説明すると、

  1.  ( x_i, y_i ) ( i = 1, 2, 3...) のグラフを補間するためのスプライン係数を求める。
  2. これにより、近似関数 f( x ) ( x_{min} \leq x \leq x_{max} )が与えられる。
  3. シフト量を \Deltaとし、 \zeta_i = f( x_i - \Delta )を得る。 \leftarrow
  4.  ( x_i, \zeta_i )をプロットすることで、シフトしたグラフを得る。

 \zetaを得るところで、 x_i - \Deltaが範囲を飛び出してしまい、(python: scipy.interpolate.interp1dでは)エラーが返って来る。
これを回避するためには、あまり格好は良くないが、 x_i - \Deltaが範囲を飛び出した時には \zeta_i = 0とするのが一番簡単な方法に思える。

 tan^{-1}(x)における横軸のシフトをpythonで実装すると、

#!/usr/bin/env python

import numpy as np
import spicy.interpolate as ipl
import matplotlib.pyplot as plt

x = np.linspace( 0, 10, 11 )
y = np.arctan( x )
f = ipl.interp1d( x, y, kind="cubic" )

shift = 2.
x_shift = [ xxx - shift for xxx in x ]

x_min = x[0]
x_max = x[-1]
y_chemshif = []
for xs in x_shift:
  if x_min <= xs <= x_max:
    y_chemshif.append( f( xs ) )
  else:
    y_chemshif.append( 0. )

plt.plot( x, y, "o", color="red" )
plt.plot( x, y_chemshif, "o", color="blue" )
plt.show()

f:id:koideforest:20171019180617p:plain