DFunction

Discrete function with interpolation

User level function of the Quantarhei package. To be used as:

>>> import quantarhei as qr
>>> f = qr.DFunction()

Discrete representation of a function with several modes of interpolation. Once defined, the function values are obtained by the method at(x), which takes the function argument and optionally a specification of the interpolation type. See examples below.

The linear interpolation is the default initially. Once the function is interpolated by splines (which happens why you call it with approx=”spline”), the default switches to “spline”. You can always enforce the type of interpolation by specifying it explicitely by the approx argument.

Examples

>>> import numpy
>>> x = numpy.linspace(0.0,95.0,20)
>>> y = numpy.exp(-x/30.0)
>>> u = ValueAxis(0.0,len(x),x[1]-x[0])
>>> f = DFunction(u,y)
>>> "%.4f" % f.axis.step
'5.0000'

Values at the points where the function was defined are exact

>>> "%.4f" % f.at(0.0)
'1.0000'
>>> "%.4f" % f.at(5.0)
'0.8465'

This is the exact value between the discrete points on which the function was defined

>>> "%.4f" % numpy.exp(-2.0/30.0)
'0.9355'

Default linear approximation leads to a difference at the second digit

>>> "%.4f" % f.at(2.0)
'0.9386'

Spline approximation is much better

>>> "%.4f" % f.at(2.0,approx='spline')
'0.9355'

Fourier transform of a DFunction

>>> from .time import TimeAxis
>>> dt = 0.1; Ns = 10000
>>> t = TimeAxis(-(Ns//2)*dt,Ns,dt,atype="complete")
>>> gg = 1.0/30.0
>>> y = numpy.exp(-numpy.abs(t.data)*gg)
>>> f = DFunction(t,y)
>>> F = f.get_Fourier_transform()
>>> print(numpy.allclose(F.at(0.0,approx="spline"),2.0/gg,rtol=1.0e-5))
True
>>> print(numpy.allclose(F.at(1.0),2*gg/(gg**2 + 1.0**2),rtol=1.0e-3))
True
>>> print(numpy.allclose(F.at(0.15),2*gg/(gg**2 + 0.15**2),rtol=1.0e-4))
True
>>> t = TimeAxis(0,Ns,dt)
>>> print(t.atype == "upper-half")
True
>>> gg = 1.0/30.0
>>> y = numpy.exp(-numpy.abs(t.data)*gg)
>>> f = DFunction(t,y)
>>> F = f.get_Fourier_transform()
>>> print(numpy.allclose(F.at(0.0,approx="spline"),2.0/gg,rtol=1.0e-5))
True
>>> print(numpy.allclose(F.at(1.0),2*gg/(gg**2 + 1.0**2),rtol=1.0e-3))
True
>>> print(numpy.allclose(F.at(0.15),2*gg/(gg**2 + 0.15**2),rtol=1.0e-4))
True

DFunction can be complex valued

>>> y = numpy.sin(t.data/10.0) + 1j*numpy.cos(t.data/10.0)
>>> fi = DFunction(t,y)
>>> print(numpy.allclose(fi.at(13.2,approx="spline"),    (numpy.sin(13.2/10.0) + 1j*numpy.cos(13.2/10.0)),rtol=1.0e-7))
True

Only “linear” and “spline” approximations are available >>> fval = fi.at(11.2, approx=”quadratic”) Traceback (most recent call last):

Exception: Unknown interpolation type

Class Details

class quantarhei.core.dfunction.DFunction(x=None, y=None)[source]

Discrete function with interpolation

Parameters:
  • x (ValueAxis (such as TimeAxis, FrequencyAxis etc.)) – Array of the values of the argument of the discrete function
  • y (numpy.ndarray) – Array of the function values

Examples

How not to create the DFunction:

First argument of the DFunction must be a ValueAxis

>>> x1 = numpy.array([0.0, 1.0, 2.0], dtype=REAL)
>>> y1 = numpy.array([0.0, 12.0, 24.0], dtype=REAL)
>>> f = DFunction(x=x1, y=y1)
Traceback (most recent call last):
    ...
Exception: First argument has to be of a ValueAxis type

Second argument must by a numpy array

>>> x1 = ValueAxis(0.0, 2, 1.0)
>>> y1 = [0.0, 12.0, 24.0]
>>> f = DFunction(x=x1, y=y1)
Traceback (most recent call last):
    ...
Exception: Second argument has to be one-dimensional numpy.ndarray

The two arguments have to have the same size (number of elements)

>>> x1 = ValueAxis(0.0, 2, 1.0)
>>> y1 = numpy.array([0.0, 12.0, 24.0, 36.0], dtype=REAL)
>>> f = DFunction(x=x1, y=y1)
Traceback (most recent call last):
    ...
Exception: Wrong number of elements in 1D numpy.ndarray
>>> x1 = ValueAxis(0.0, 2, 1.0)
>>> y1 = numpy.array([[0.0, 12.0, 24.0], [36.0, 48.0, 60.0]], dtype=REAL)
>>> f = DFunction(x=x1, y=y1)
Traceback (most recent call last):
    ...
Exception: Second argument has to be one-dimensional numpy.ndarray

Methods

apply_to_data(func) Applies a submitted function to the data
at(x[, approx]) Returns the function value at the argument x
change_axis(axis) Replaces the axis object with a compatible one, zero pads or trims the values
copy() Returns a shallow copy of the self
deepcopy() Returns a deep copy of the self
fit_exponential([guess]) Exponential fit of the function
fit_gaussian([N, guess, Nsvf]) Performs a Gaussian fit of the spectrum based on an initial guess
get_Fourier_transform([window]) Returns Fourier transform of the DFunction
get_inverse_Fourier_transform() Returns inverse Fourier transform of the DFunction
load(filename[, test]) Loads an object from a file and returns it
load_data(name[, with_axis]) Loads the data in a format determined by the file name extension
loaddir(dirname) Returns a directory of objects saved into a directory
plot([fig, title, title_font, axis, vmax, …]) Plotting of the DFunction’s data against the ValueAxis.
save(filename[, comment, test]) Saves the object with all its content into a file
save_data(name[, with_axis]) Saves the data into a format determined by the file name extension
savedir(dirname[, tag, comment, test]) Saves an object into directory containing a file with unique name
savefig(filename) Saves current figure into a file
scopy() Creates a copy of the object by saving and loading it
set_data_protected() Implement this method to put protections on data property
set_data_writable() Implement this method to lift existing protection of data property
apply_to_data(func)[source]

Applies a submitted function to the data

>>> x = TimeAxis(0.0, 314, 0.001)
>>> f1 = DFunction(x, x.data)
>>> f2 = DFunction(x, numpy.cos(x.data))
>>> f1.data[100] == f2.data[100]
False
>>> f1.apply_to_data(numpy.cos)
>>> f1.data[100] == f2.data[100]
True
>>> f1.data[160] == f2.data[160]
True
at(x, approx='default')[source]

Returns the function value at the argument x

Returns the value of the function at a given value of argument x. The default interpolation is linear, until the spline interpolation is initialized by calling the method with approx = “spline”. From then on, the default is spline.

Parameters:
  • x (number) – Function argument
  • approx (string {"default","linear","spline"}) – Type of interpolation

Examples

>>> time = TimeAxis(0.0, 100, 10.0)
>>> vals = numpy.cos(2.0*numpy.pi*time.data/300.0)
>>> fce = DFunction(time, vals)
>>> print("%.8f" % fce.at(213.4))
-0.23949089
>>> print("%.8f" % fce.at(213.4, approx="linear"))
-0.23949089
>>> print("%.8f" % fce.at(213.4, approx="spline"))
-0.24056615
>>> print("%.8f" % numpy.cos(2.0*numpy.pi*213.4/300.0))
-0.24056687

Once the splines are initialized, they become default >>> print(“%.8f” % fce.at(213.4)) -0.24056615

change_axis(axis)[source]

Replaces the axis object with a compatible one, zero pads or trims the values

Examples

>>> time = TimeAxis(0.0, 1000, 1.0)
>>> vals = numpy.cos(2.0*numpy.pi*time.data/500.0)
>>> fce = DFunction(time, vals)
>>> print("%.4f" % fce.at(914.0))
0.4707
>>> time1 = TimeAxis(0.0, 1000, 1.0)
>>> fce.change_axis(time1)
>>> fce.axis == time1
True
>>> time2 = TimeAxis(0.0, 900, 1.0)
>>> fce.change_axis(time2)
>>> print("%.4f" % fce.at(914.0))
Traceback (most recent call last):
    ...
Exception: Value out of bounds
>>> print("%.4f" % fce.at(814.0))
-0.6937

Zero-padding

>>> time3 = TimeAxis(0.0, 1000, 1.0)
>>> fce.change_axis(time3)
>>> print("%.4f" % fce.at(814.0))
-0.6937
>>> print("%.4f" % fce.at(914.0))
0.0000
>>> time4 = TimeAxis(0.0, 100, 10.0)
>>> fce.change_axis(time4)
Traceback (most recent call last):
    ...
Exception: Incompatible axis
fit_exponential(guess=None)[source]

Exponential fit of the function

Examples

>>> t = TimeAxis(0.0, 100, 1.0)
>>> f = DFunction(t, 2.3*numpy.exp(-(t.data)/(10.0))+0.32)
>>> popt = f.fit_exponential()
>>> print(popt)
[ 2.3   0.1   0.32]
fit_gaussian(N=1, guess=None, Nsvf=251)[source]

Performs a Gaussian fit of the spectrum based on an initial guess

Parameters:Nsvf (int) – Length of the Savitzky-Golay filter window (odd integer)

Examples

>>> t = TimeAxis(0.0, 100, 1.0)
>>> f = DFunction(t, 2.3*numpy.exp(-(4.0*numpy.log(2.0))*((t.data-30.0)**2)/(10.0**2))+0.32)
>>> popt = f.fit_gaussian(guess=[1.0, 33.0, 5.0, 0.5])
>>> print(popt)
[  2.3   30.    10.     0.32]
get_Fourier_transform(window=None)[source]

Returns Fourier transform of the DFunction

>>> t = TimeAxis(0.0, 200, 1.0)

The default type of TimeAxis is “upper-half”

>>> print(t.atype)
upper-half

We create a function with this TimeAxis

>>> f = DFunction(t, numpy.exp(((-t.data-50.0)**2)/(30.0**2)))
>>> F = f.get_Fourier_transform()

When TimeAxis is the “upper-half” it is assumed that only half of the function is specified. The “lower-half” corresponds to a complex conjugated function, and FT is real.

>>> rmax = numpy.max(numpy.abs(numpy.real(F.data)))
>>> imax = numpy.max(numpy.abs(numpy.imag(F.data)))
>>> imax/rmax < 1.0e-15
True
>>>

The same with “complete” gives a complex result

>>> t = TimeAxis(0.0, 200, 1.0, atype="complete")
>>> f = DFunction(t, numpy.exp((-(t.data-50.0)**2)/(30.0**2)))
>>> F = f.get_Fourier_transform()
>>> rmax = numpy.max(numpy.abs(numpy.real(F.data)))
>>> imax = numpy.max(numpy.abs(numpy.imag(F.data)))
>>> imax/rmax  < 1.0e-15
False
>>> f.axis.atype="lower-half"
>>> F = f.get_Fourier_transform()
Traceback (most recent call last):
    ...
Exception: Unknown time axis type
get_inverse_Fourier_transform()[source]

Returns inverse Fourier transform of the DFunction

>>> import quantarhei as qr
>>> t = TimeAxis(-100.0, 200, 1.0)
>>> f = DFunction(t, numpy.exp(-(t.data**2)/(30.0**2)))
>>> F = f.get_Fourier_transform()
>>> fn = F.get_inverse_Fourier_transform()
>>> numpy.testing.assert_allclose(numpy.real(fn.data[100]), f.data[100])
>>> dw = qr.convert(5.0,"1/cm","int")
>>> w = FrequencyAxis(0.0, 100, dw) #t.get_FrequencyAxis()
>>> delt = qr.convert(30.0,"1/cm","int")
>>> F = DFunction(w, numpy.exp((w.data**2)/(delt**2)))
>>> f = F.get_inverse_Fourier_transform()
>>> isinstance(f.axis, TimeAxis)
True
plot(fig=None, title=None, title_font=None, axis=None, vmax=None, vmin=None, xlabel=None, ylabel=None, label_font=None, text=None, text_font=None, label=None, text_loc=[0.05, 0.9], fontsize='20', real_only=True, show=False, color=None)[source]

Plotting of the DFunction’s data against the ValueAxis.

Parameters:
  • title (str) – Title of the plot
  • title_font (str) – Name of the title font
savefig(filename)[source]

Saves current figure into a file