Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 23 additions & 1 deletion specparam/modes/definitions.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from specparam.modes.mode import Mode
from specparam.modes.params import ParamDefinition
from specparam.modes.funcs import (expo_function, expo_nk_function, double_expo_function,
gaussian_function, skewed_gaussian_function, cauchy_function)
gaussian_function, skewed_gaussian_function,
cauchy_function, triangle_function)
from specparam.modes.jacobians import jacobian_gauss
from specparam.utils.checks import check_selection

Expand Down Expand Up @@ -149,12 +150,33 @@
powers_space='log10',
)

## PE - Triangle Mode

params_triangle = ParamDefinition(OrderedDict({
'cf' : 'Center frequency of the peak.',
'pw' : 'Power of the peak, over and above the aperiodic component.',
'bw' : 'Bandwidth of the peak.',
}))

pe_triangle = Mode(
name='triangle',
component='periodic',
description='Triangle peak fit function.',
func=triangle_function,
jacobian=None,
params=params_triangle,
ndim=2,
freq_space='linear',
powers_space='log10',
)


# Collect available periodic modes
PE_MODES = {
'gaussian' : pe_gaussian,
'skewed_gaussian' : pe_skewed_gaussian,
'cauchy' : pe_cauchy,
'triangle' : pe_triangle,
}

###################################################################################################
Expand Down
33 changes: 30 additions & 3 deletions specparam/modes/funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,7 @@ def skewed_gaussian_function(xs, *params):

ys = np.zeros_like(xs)

for ii in range(0, len(params), 4):

ctr, hgt, wid, skew = params[ii:ii+4]
for ctr, hgt, wid, skew in zip(*[iter(params)] * 4):

ts = (xs - ctr) / wid
temp = 2 / wid * (1 / np.sqrt(2 * np.pi) * np.exp(-ts**2 / 2)) * \
Expand Down Expand Up @@ -90,6 +88,35 @@ def cauchy_function(xs, *params):
return ys


def triangle_function(xs, *params):
"""Triangle fitting function.

Parameters
----------
xs : 1d array
Input x-axis values.
*params : float
Parameters that define a triangle function.

Returns
-------
ys : 1d array
Output values for triangle function.
"""

ys = np.zeros_like(xs)
fres = xs[1] - xs[0]

for ctr, hgt, wid in zip(*[iter(params)] * 3):

n_samples = int(np.ceil(2 * wid / fres))
n_samples += 1 if n_samples % 2 == 0 else 0
temp = np.arccos(np.cos(np.linspace(0, 2 * np.pi, n_samples)))
ys[np.abs(xs - ctr) <= (n_samples / 2) * fres] += hgt * normalize(temp)

return ys


## APERIODIC FUNCTIONS

def expo_function(xs, *params):
Expand Down
25 changes: 15 additions & 10 deletions specparam/tests/modes/test_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,8 @@
def test_gaussian_function():

ctr, hgt, wid = 50, 5, 10

xs = np.arange(1, 100)
xs = np.arange(1, 100, 1.)
ys = gaussian_function(xs, ctr, hgt, wid)

assert np.all(ys)

# Check distribution matches generated gaussian from scipy
Expand All @@ -28,7 +26,7 @@ def test_skewed_gaussian_function():

# Check that with no skew, approximate gaussian
ctr, hgt, wid, skew = 50, 5, 10, 1
xs = np.arange(1, 100)
xs = np.arange(1, 100, 1.)
ys_gaus = gaussian_function(xs, ctr, hgt, wid)
ys_skew = skewed_gaussian_function(xs, ctr, hgt, wid, skew)
np.allclose(ys_gaus, ys_skew, atol=0.001)
Expand All @@ -46,19 +44,26 @@ def test_skewed_gaussian_function():
def test_cauchy_function():

ctr, hgt, wid = 50, 5, 10

xs = np.arange(1, 100)
xs = np.arange(1, 100, 1.)
ys = cauchy_function(xs, ctr, hgt, wid)

assert np.all(ys)

def test_triangle_function():

ctr, hgt, wid = 50, 5, 10
xs = np.arange(1, 100, 1.)
ys = triangle_function(xs, ctr, hgt, wid)

assert np.any(ys)

## Aperiodic functions

def test_expo_function():

off, knee, exp = 10, 5, 2

xs = np.arange(1, 100)
xs = np.arange(1, 100, 1.)
ys = expo_function(xs, off, knee, exp)

assert np.all(ys)
Expand All @@ -74,7 +79,7 @@ def test_expo_nk_function():

off, exp = 10, 2

xs = np.arange(1, 100)
xs = np.arange(1, 100, 1.)
ys = expo_nk_function(xs, off, exp)

assert np.all(ys)
Expand Down Expand Up @@ -106,7 +111,7 @@ def test_linear_function():

off, sl = 10, 2

xs = np.arange(1, 100)
xs = np.arange(1, 100, 1.)
ys = linear_function(xs, off, sl)

assert np.all(ys)
Expand All @@ -120,7 +125,7 @@ def test_quadratic_function():

off, sl, curve = 10, 3, 2

xs = np.arange(1, 100)
xs = np.arange(1, 100, 1.)
ys = quadratic_function(xs, off, sl, curve)

assert np.all(ys)
Expand Down